Commit | Line | Data |
---|---|---|
3b542afc MG |
1 | `include "news.v" |
2 | ||
7f1b6bd9 MG |
3 | `define OP_NOP 3'd0 |
4 | `define OP_LOADA 3'd1 | |
5 | `define OP_LOADB 3'd2 | |
6 | `define OP_STORE 3'd3 | |
7 | `define OP_STOREI 3'd4 | |
8 | `define OP_LOADI 3'd5 | |
9 | `define OP_ROUTE 3'd6 | |
10 | `define OP_LED 3'd7 | |
5a2a82dc | 11 | |
23c26e04 MG |
12 | `define DIRECTION_N 3'd0 |
13 | `define DIRECTION_NE 3'd1 | |
14 | `define DIRECTION_E 3'd2 | |
15 | `define DIRECTION_SE 3'd3 | |
16 | `define DIRECTION_S 3'd4 | |
17 | `define DIRECTION_SW 3'd5 | |
18 | `define DIRECTION_W 3'd6 | |
19 | `define DIRECTION_NW 3'd7 | |
20 | ||
46a95fd3 | 21 | module chip(input clk, input [2:0] op, input [15:0] I, output reg [15:0] mem_in, input [15:0] mem_out, output reg mem_write, output reg [3:0] led_out = 0); |
5a2a82dc MG |
22 | |
23 | // parity is unimplemented | |
24 | ||
25 | // OP_LOADA | |
23c26e04 MG |
26 | wire [3:0] flagr = I[3:0]; |
27 | wire bsel = I[4]; | |
28 | wire [0:7] aluc = I[12:5]; | |
5a2a82dc MG |
29 | |
30 | // OP_LOADB | |
23c26e04 MG |
31 | wire [3:0] cond = I[3:0]; |
32 | wire inv = I[4]; | |
33 | wire [0:7] alus = I[12:5]; | |
5a2a82dc MG |
34 | |
35 | // OP_STORE | |
23c26e04 | 36 | wire [3:0] flagw = I[3:0]; |
5a2a82dc MG |
37 | wire edge_ = I[7]; |
38 | wire [3:0] cube = I[11:8]; | |
39 | ||
7f1b6bd9 MG |
40 | // OP_LED |
41 | wire mode = I[4]; | |
42 | wire [1:0] offset = I[1:0]; | |
43 | wire [3:0] leds = I[3:0]; | |
5a2a82dc | 44 | |
7f1b6bd9 MG |
45 | |
46 | reg [15:0] A = 0; | |
47 | reg [15:0] B = 0; | |
48 | reg [15:0] C = 0; | |
49 | reg [15:0] F = 0; | |
50 | reg [15:0] Cond = 0; | |
51 | reg [15:0] R = 0; | |
23c26e04 MG |
52 | reg [7:0] alu_sum = 0; |
53 | reg [7:0] alu_carry = 0; | |
7f1b6bd9 | 54 | reg [15:0] cube_in; |
5a2a82dc MG |
55 | |
56 | // these are not really regs | |
57 | ||
7f1b6bd9 MG |
58 | reg [15:0] alu_sum_out; |
59 | reg [15:0] alu_carry_out; | |
23c26e04 | 60 | |
46a95fd3 | 61 | reg [2:0] alu_index [15:0]; |
23c26e04 MG |
62 | |
63 | reg [15:0] idx; | |
5a2a82dc MG |
64 | |
65 | always @* begin | |
7f1b6bd9 | 66 | for(idx = 0; idx < 16; idx=idx+1) begin |
23c26e04 MG |
67 | alu_index[idx] = (A[idx] << 2) + (B[idx] << 1) + F[idx]; |
68 | alu_sum_out[idx] <= alu_sum[alu_index[idx]]; | |
69 | alu_carry_out[idx] <= alu_carry[alu_index[idx]]; | |
70 | end | |
5a2a82dc MG |
71 | end |
72 | ||
23c26e04 MG |
73 | reg [3:0] flags_addr_latch; |
74 | reg [3:0] flags_addr; | |
75 | ||
76 | always @* begin | |
77 | if(flags_addr_latch) | |
78 | flags_addr <= flags_addr_latch; | |
79 | else | |
80 | case(op) | |
81 | `OP_LOADA: | |
82 | flags_addr <= flagr; | |
83 | `OP_LOADB: | |
84 | flags_addr <= cond; | |
85 | `OP_STORE: | |
86 | flags_addr <= flagw; | |
87 | default: | |
88 | flags_addr <= 0; | |
89 | endcase | |
90 | end // always @ * | |
91 | ||
7f1b6bd9 MG |
92 | reg [15:0] flags_in; |
93 | wire [15:0] flags_out; | |
5a2a82dc MG |
94 | reg flags_write; |
95 | ||
7f1b6bd9 | 96 | reg [15:0] latest_news; |
5a2a82dc | 97 | |
23c26e04 MG |
98 | RAM #(.ADDRESS_BITS(3)) flags (.clk(clk), .write(flags_write), .addr(flags_addr[2:0]), .in(flags_in), .out(flags_out)); |
99 | ||
7f1b6bd9 MG |
100 | reg [15:0] flag_or_news; |
101 | reg [15:0] news_out; | |
23c26e04 | 102 | |
46a95fd3 | 103 | news newspaper (.news_in(latest_news), .direction(flags_addr[2:0]), .news_out(news_out)); |
23c26e04 | 104 | |
3b542afc | 105 | assign flag_or_news = flags_addr[3] ? news_out : flags_out; |
5a2a82dc MG |
106 | |
107 | always @ (posedge clk) begin | |
108 | if(mem_write) | |
109 | mem_write <= 0; | |
23c26e04 MG |
110 | if(flags_write) begin |
111 | flags_write <= 0; | |
112 | flags_addr_latch <= 0; | |
113 | end | |
5a2a82dc MG |
114 | |
115 | case (op) | |
116 | `OP_NOP: begin end | |
117 | ||
118 | `OP_LOADA: | |
119 | begin | |
120 | alu_carry <= aluc; | |
23c26e04 | 121 | F <= flag_or_news; |
5a2a82dc MG |
122 | A <= mem_out; |
123 | C <= mem_out; | |
5a2a82dc MG |
124 | if (bsel) |
125 | B <= cube_in; | |
126 | end | |
127 | ||
128 | `OP_LOADB: | |
129 | begin | |
130 | alu_sum <= alus; | |
23c26e04 | 131 | Cond <= inv ? ~flag_or_news : flag_or_news; |
5a2a82dc MG |
132 | B <= mem_out; |
133 | R <= mem_out; | |
134 | end | |
135 | ||
136 | `OP_STORE: | |
137 | begin | |
7f1b6bd9 | 138 | for(idx = 0; idx < 16; idx++) begin |
23c26e04 MG |
139 | flags_in[idx] = Cond[idx] ? alu_carry_out[idx] : flags_out[idx]; |
140 | latest_news[idx] <= flags_in[idx]; | |
141 | end | |
142 | if(flags_addr) begin // we do not write to flag 0 | |
143 | flags_write <= 1; | |
144 | flags_addr_latch <= flags_addr; | |
145 | end | |
5a2a82dc MG |
146 | mem_in <= alu_sum_out; |
147 | mem_write <= 1; | |
5a2a82dc MG |
148 | end |
149 | ||
7f1b6bd9 | 150 | `OP_STOREI: |
5a2a82dc | 151 | begin |
7f1b6bd9 MG |
152 | mem_in <= I; |
153 | mem_write <= 1; | |
5a2a82dc | 154 | end |
7f1b6bd9 | 155 | /* |
5a2a82dc MG |
156 | `OP_LOADI: |
157 | begin | |
158 | C <= mem_out; | |
159 | A <= I; | |
160 | alu_sum <= 8'b11110000; // out of A, B, F, select exactly A | |
161 | end | |
7f1b6bd9 MG |
162 | */ |
163 | ||
164 | `OP_LED: | |
165 | begin | |
166 | if(!mode) | |
167 | led_out <= leds; | |
168 | else if(offset == 0) | |
169 | led_out <= mem_out[3:0]; | |
170 | else if(offset == 1) | |
171 | led_out <= mem_out[7:4]; | |
172 | else if(offset == 2) | |
173 | led_out <= mem_out[11:8]; | |
174 | else if(offset == 3) | |
175 | led_out <= mem_out[15:12]; | |
176 | end | |
5a2a82dc MG |
177 | |
178 | /* `OP_RUG: | |
179 | begin | |
180 | if(!rw && ac && !news) | |
181 | begin | |
182 | rug[reg_] <= A; | |
183 | C <= mem_out; | |
184 | end | |
185 | if(!rw && !ac && !news) | |
186 | begin | |
187 | rug[reg_] <= C; | |
188 | A <= mem_out; | |
189 | end | |
190 | if(rw && ac && !news) | |
191 | begin | |
192 | A <= rug[reg_]; | |
193 | mem_in <= C; | |
194 | end | |
195 | if(rw && !ac && !news) | |
196 | begin | |
197 | C <= rug[reg_]; | |
198 | mem_in <= A; | |
199 | end | |
200 | if(rw && !ac && news) | |
201 | begin | |
202 | R <= mem_out; | |
203 | cube_in <= mem_out; | |
204 | end | |
205 | if(rw && ac && news) | |
206 | begin | |
207 | cube_in <= mem_out; | |
208 | end | |
209 | end | |
210 | */ | |
211 | endcase | |
212 | end | |
213 | endmodule |