]>
Commit | Line | Data |
---|---|---|
1 | `include "news.v" | |
2 | ||
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 | |
11 | ||
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 | ||
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); | |
22 | ||
23 | // parity is unimplemented | |
24 | ||
25 | // OP_LOADA | |
26 | wire [3:0] flagr = I[3:0]; | |
27 | wire bsel = I[4]; | |
28 | wire [0:7] aluc = I[12:5]; | |
29 | ||
30 | // OP_LOADB | |
31 | wire [3:0] cond = I[3:0]; | |
32 | wire inv = I[4]; | |
33 | wire [0:7] alus = I[12:5]; | |
34 | ||
35 | // OP_STORE | |
36 | wire [3:0] flagw = I[3:0]; | |
37 | wire edge_ = I[7]; | |
38 | wire [3:0] cube = I[11:8]; | |
39 | ||
40 | // OP_LED | |
41 | wire mode = I[4]; | |
42 | wire [1:0] offset = I[1:0]; | |
43 | wire [3:0] leds = I[3:0]; | |
44 | ||
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; | |
52 | reg [7:0] alu_sum = 0; | |
53 | reg [7:0] alu_carry = 0; | |
54 | reg [15:0] cube_in; | |
55 | ||
56 | // these are not really regs | |
57 | ||
58 | reg [15:0] alu_sum_out; | |
59 | reg [15:0] alu_carry_out; | |
60 | ||
61 | reg [2:0] alu_index [15:0]; | |
62 | ||
63 | reg [15:0] idx; | |
64 | ||
65 | always @* begin | |
66 | for(idx = 0; idx < 16; idx=idx+1) begin | |
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 | |
71 | end | |
72 | ||
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 | ||
92 | reg [15:0] flags_in; | |
93 | wire [15:0] flags_out; | |
94 | reg flags_write; | |
95 | ||
96 | reg [15:0] latest_news; | |
97 | ||
98 | RAM #(.ADDRESS_BITS(3)) flags (.clk(clk), .write(flags_write), .addr(flags_addr[2:0]), .in(flags_in), .out(flags_out)); | |
99 | ||
100 | reg [15:0] flag_or_news; | |
101 | reg [15:0] news_out; | |
102 | ||
103 | news newspaper (.news_in(latest_news), .direction(flags_addr[2:0]), .news_out(news_out)); | |
104 | ||
105 | assign flag_or_news = flags_addr[3] ? news_out : flags_out; | |
106 | ||
107 | always @ (posedge clk) begin | |
108 | if(mem_write) | |
109 | mem_write <= 0; | |
110 | if(flags_write) begin | |
111 | flags_write <= 0; | |
112 | flags_addr_latch <= 0; | |
113 | end | |
114 | ||
115 | case (op) | |
116 | `OP_NOP: begin end | |
117 | ||
118 | `OP_LOADA: | |
119 | begin | |
120 | alu_carry <= aluc; | |
121 | F <= flag_or_news; | |
122 | A <= mem_out; | |
123 | C <= mem_out; | |
124 | if (bsel) | |
125 | B <= cube_in; | |
126 | end | |
127 | ||
128 | `OP_LOADB: | |
129 | begin | |
130 | alu_sum <= alus; | |
131 | Cond <= inv ? ~flag_or_news : flag_or_news; | |
132 | B <= mem_out; | |
133 | R <= mem_out; | |
134 | end | |
135 | ||
136 | `OP_STORE: | |
137 | begin | |
138 | for(idx = 0; idx < 16; idx++) begin | |
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 | |
146 | mem_in <= alu_sum_out; | |
147 | mem_write <= 1; | |
148 | end | |
149 | ||
150 | `OP_STOREI: | |
151 | begin | |
152 | mem_in <= I; | |
153 | mem_write <= 1; | |
154 | end | |
155 | /* | |
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 | |
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 | |
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 |