Commit | Line | Data |
---|---|---|
a051754e MG |
1 | `include "asciihex.v" |
2 | `include "generic_fifo_sc_a.v" | |
3 | `include "gc.v" | |
4 | `include "ram.v" | |
5 | `include "rom.v" | |
6 | `include "prescaler.v" | |
7 | `include "single_trigger.v" | |
8 | `include "uart.v" | |
9 | ||
10 | `define INST_JPZ 4'b0111 | |
11 | `define INST_JP 4'b0110 | |
12 | `define INST_STM 4'b0101 | |
13 | `define INST_LDM 4'b0100 | |
14 | `define INST_SUB 4'b0011 | |
15 | `define INST_ADD 4'b0010 | |
16 | `define INST_LDI 4'b0001 | |
17 | `define INST_HALT 4'b0000 | |
18 | `define INST_READ 4'b1000 | |
19 | `define INST_WRITE 4'b1001 | |
20 | `define INST_CONS 4'b1010 | |
21 | `define INST_LDQ 4'b1110 | |
22 | `define INST_RDQ 4'b1100 | |
23 | `define INST_CAR 4'b1111 | |
24 | `define INST_CDR 4'b1101 | |
25 | ||
26 | `define STORE_BUTTON buttons[8] | |
27 | `define CLEAR_BUTTON buttons[9] | |
28 | `define PC_INC_BUTTON buttons[10] | |
29 | `define PC_DEC_BUTTON buttons[11] | |
30 | `define PC_CLR_BUTTON buttons[12] | |
31 | `define ACCUM_CLR_BUTTON buttons[13] | |
32 | `define RUN_BUTTON buttons[14] | |
33 | `define EXECUTE_BUTTON buttons[15] | |
34 | ||
35 | `define GCOP_NOP 4'd0 | |
36 | `define GCOP_CDR 4'd1 | |
37 | `define GCOP_CAR 4'd2 | |
38 | `define GCOP_CDRQ 4'd3 | |
39 | `define GCOP_CARQ 4'd4 | |
40 | `define GCOP_CARR 4'd5 | |
41 | `define GCOP_CDRRX 4'd6 | |
42 | `define GCOP_CARRX 4'd7 | |
43 | `define GCOP_CDRQX 4'd8 | |
44 | `define GCOP_CONS 4'd9 | |
45 | `define GCOP_XCONS 4'd10 | |
46 | `define GCOP_RPLACDR 4'd11 | |
47 | `define GCOP_LDQ 4'd12 | |
48 | `define GCOP_RDQ 4'd13 | |
49 | `define GCOP_RDQA 4'd14 | |
50 | `define GCOP_RDQCDRRX 4'd15 | |
51 | ||
52 | // This is a simple four bit accumulator machine. It is a Havard architecture with separate | |
53 | // program and user memory address spaces. | |
54 | ||
55 | module PROCESSOR (input clk, output [23:0] led, output [3:0] indicators, input [15:0] buttons, output uart_tx, input uart_rx); | |
56 | // storage unit | |
57 | reg [7:0] Ein; | |
58 | wire [7:0] Eout; | |
59 | reg [3:0] gcop = 4'b0; | |
60 | wire [6:0] ostate; | |
61 | wire step_eval; | |
62 | ||
63 | reg reading_E = 0; | |
64 | ||
65 | // Handle running | |
66 | ||
67 | reg running = 1; | |
68 | ||
69 | always @ (posedge `RUN_BUTTON) begin | |
70 | running <= !running; | |
71 | end | |
72 | ||
73 | // Generate running clock | |
74 | ||
75 | wire running_counter; | |
76 | ||
77 | PRESCALER #(.BITS(1)) scal0 (.clk(clk), .out(running_counter)); | |
78 | ||
79 | wire running_clk = running & running_counter; | |
80 | ||
81 | // Handle execution | |
82 | ||
83 | wire execute_trigger; | |
84 | ||
85 | SINGLE_TRIGGER trig0 (.clk(clk), .trigger_in(`EXECUTE_BUTTON), .trigger_out(execute_trigger)); | |
86 | ||
87 | wire running_trigger; | |
88 | ||
89 | SINGLE_TRIGGER trig1 (.clk(clk), .trigger_in(running_clk), .trigger_out(running_trigger)); | |
90 | ||
91 | wire gc_clock = (!running & execute_trigger) | running_clk; | |
92 | wire eval_clock = !gc_clock & step_eval; | |
93 | ||
94 | GC gc (.clk(gc_clock), .mclk(clk), .Ein(Ein), .Eout(Eout), .gcop(gcop), .ostate(ostate), .step_eval(step_eval)); | |
95 | ||
96 | // Handle halt | |
97 | ||
98 | reg halt = 0; | |
99 | ||
100 | always @ (posedge eval_clock) begin | |
101 | if (inst == `INST_HALT) | |
102 | halt <= 1; | |
103 | ||
104 | if (!running) | |
105 | halt <= 0; | |
106 | end | |
107 | ||
108 | // UART outputs | |
109 | wire uart_rx_signal; | |
110 | wire [7:0] uart_rx_byte; | |
111 | wire uart_is_receiving; | |
112 | wire uart_is_transmitting; | |
113 | wire uart_rx_error; | |
114 | ||
115 | // Handle program space | |
116 | wire [7:0] programOut; | |
117 | ||
118 | wire [3:0] inst = programOut[7:4]; | |
119 | wire [3:0] argu = programOut[3:0]; | |
120 | ||
121 | ROM programMemory (.clk(clk), .addr(pc), .data(programOut)); | |
122 | ||
123 | // Input logic | |
124 | wire [3:0] fifo_in; | |
125 | wire [3:0] fifo_out; | |
126 | wire fifo_full; | |
127 | wire fifo_empty; | |
128 | wire fifo_re = eval_clock & inst == `INST_READ & !fifo_empty; | |
129 | wire fifo_we = uart_rx_signal & !fifo_full; | |
130 | ||
131 | ascii_to_hex a2h (.ascii({1'b0, uart_rx_byte[6:0]}), .hex(fifo_in)); | |
132 | ||
133 | generic_fifo_sc_a #(.dw(4), .aw(4)) fifo | |
134 | (.clk(clk), | |
135 | .rst(1'b1), | |
136 | .re(fifo_re), | |
137 | .we(fifo_we), | |
138 | .din(fifo_in), | |
139 | .dout(fifo_out), | |
140 | .full(fifo_full), | |
141 | .empty(fifo_empty)); | |
142 | ||
143 | // Output logic | |
144 | reg started_writing = 0; | |
145 | ||
146 | always @ (posedge eval_clock) begin | |
147 | if (started_writing) | |
148 | started_writing <= 0; | |
149 | else if (inst == `INST_WRITE & !uart_is_transmitting) | |
150 | started_writing <= 1; | |
151 | end | |
152 | ||
153 | // Handle PC | |
154 | reg [3:0] pc = 0; | |
155 | ||
156 | wire [3:0] next = pc + 4'b0001; | |
157 | wire [3:0] prev = pc + 4'b1111; | |
158 | ||
159 | wire pc_prev_trigger; | |
160 | wire pc_next_trigger; | |
161 | wire pc_zero_trigger; | |
162 | ||
163 | SINGLE_TRIGGER trig3 (.clk(clk), .trigger_in(`PC_INC_BUTTON), .trigger_out(pc_next_trigger)); | |
164 | SINGLE_TRIGGER trig4 (.clk(clk), .trigger_in(`PC_DEC_BUTTON), .trigger_out(pc_prev_trigger)); | |
165 | SINGLE_TRIGGER trig5 (.clk(clk), .trigger_in(`PC_CLR_BUTTON), .trigger_out(pc_zero_trigger)); | |
166 | ||
167 | wire [3:0] newPc = | |
168 | (inst == `INST_JP) ? argu : | |
169 | (inst == `INST_JPZ) & (accum == 4'b0000) ? argu : | |
170 | started_writing ? next : | |
171 | (inst == `INST_WRITE) ? pc : | |
172 | (inst == `INST_READ) & !fifo_re ? pc : | |
173 | (inst == `INST_RDQ) & !reading_E ? pc : | |
174 | (inst != `INST_HALT) ? next : | |
175 | /* !running & pc_zero_trigger ? 4'b00000 : | |
176 | !running & pc_next_trigger ? next : | |
177 | !running & pc_prev_trigger ? prev : */ | |
178 | pc; | |
179 | ||
180 | always @ (posedge eval_clock) begin | |
181 | pc <= newPc; | |
182 | end | |
183 | ||
184 | // Handle user memory | |
185 | wire [3:0] userMemoryOut; | |
186 | ||
187 | RAM #(.DATA_BITS(4),.ADDRESS_BITS(4)) userMemory (.clk(clk), .write(eval_clock & (inst == `INST_STM)), .addr(argu), .in_data(accum), .out_data(userMemoryOut)); | |
188 | ||
189 | // Handle accumulator | |
190 | reg [3:0] accum = 0; | |
191 | ||
192 | wire [3:0] newAccum = | |
193 | (inst == `INST_LDI) ? argu : | |
194 | (inst == `INST_ADD) ? accum + argu : | |
195 | (inst == `INST_SUB) ? accum - argu : | |
196 | (inst == `INST_LDM) ? userMemoryOut : | |
197 | fifo_re ? fifo_out : | |
198 | reading_E ? Eout[3:0] : | |
199 | accum; | |
200 | ||
201 | always @ (posedge eval_clock) begin | |
202 | accum <= newAccum; | |
203 | end | |
204 | ||
205 | // UART logic | |
206 | wire uart_tx_signal = started_writing; | |
207 | wire [7:0] uart_tx_byte; | |
208 | ||
209 | hex_to_ascii h2a (.hex(accum), .ascii(uart_tx_byte)); | |
210 | ||
211 | // 300-ish baud uart | |
212 | uart #(.CLOCK_DIVIDE(81)) uart (.clk(clk), .rx(uart_rx), .tx(uart_tx), .transmit(uart_tx_signal), .tx_byte(uart_tx_byte), .received(uart_rx_signal), .rx_byte(uart_rx_byte), .is_receiving(uart_is_receiving), .is_transmitting(uart_is_transmitting), .recv_error (uart_rx_error)); | |
213 | ||
214 | // GC logic | |
215 | always @ (posedge eval_clock) begin | |
216 | if (reading_E) begin | |
217 | reading_E <= 0; | |
218 | gcop <= `GCOP_NOP; | |
219 | end else begin | |
220 | if(inst == `INST_CONS) begin | |
221 | Ein <= {4'b0, accum}; | |
222 | gcop <= `GCOP_CONS; | |
223 | end else if(inst == `INST_LDQ) begin | |
224 | Ein <= {4'b0, accum}; | |
225 | gcop <= `GCOP_LDQ; | |
226 | end else if(inst == `INST_RDQ) begin | |
227 | Ein <= 8'b0; | |
228 | reading_E <= 1; | |
229 | gcop <= `GCOP_RDQ; | |
230 | end else if(inst == `INST_CAR) begin | |
231 | Ein <= {4'b0, accum}; | |
232 | gcop <= `GCOP_CAR; | |
233 | end else if(inst == `INST_CDR) begin | |
234 | Ein <= {4'b0, accum}; | |
235 | gcop <= `GCOP_CDR; | |
236 | end else begin | |
237 | Ein <= 8'b0; | |
238 | gcop <= `GCOP_NOP; | |
239 | end | |
240 | end | |
241 | end | |
242 | ||
243 | // Assign the outputs | |
244 | ||
245 | /* assign led[0] = uart_tx; | |
246 | assign led[1] = uart_is_transmitting; | |
247 | assign led[2] = uart_is_receiving; | |
248 | assign led[3] = uart_rx_signal; | |
249 | assign led[4] = uart_rx_error; | |
250 | assign led[5] = fifo_empty; | |
251 | assign led[6] = fifo_full; | |
252 | assign led[7] = fifo_re;*/ | |
253 | assign led[7:4] = Ein[3:0]; | |
254 | assign led[3:0] = Eout[3:0]; | |
255 | // assign led[15:8] = programOut; | |
256 | // assign led[15:8] = uart_rx_byte; | |
257 | assign led[15] = step_eval; | |
258 | assign led[14] = eval_clock; | |
259 | assign led[13:8] = ostate; | |
260 | assign led[19:16] = pc; | |
261 | assign led[23:20] = accum; | |
262 | assign indicators = {1'b0, (!running & `EXECUTE_BUTTON) | running_clk, halt, running & !halt}; | |
263 | ||
264 | endmodule |