]>
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 | ||
a051754e MG |
26 | `define GCOP_NOP 4'd0 |
27 | `define GCOP_CDR 4'd1 | |
28 | `define GCOP_CAR 4'd2 | |
29 | `define GCOP_CDRQ 4'd3 | |
30 | `define GCOP_CARQ 4'd4 | |
31 | `define GCOP_CARR 4'd5 | |
32 | `define GCOP_CDRRX 4'd6 | |
33 | `define GCOP_CARRX 4'd7 | |
34 | `define GCOP_CDRQX 4'd8 | |
35 | `define GCOP_CONS 4'd9 | |
36 | `define GCOP_XCONS 4'd10 | |
37 | `define GCOP_RPLACDR 4'd11 | |
38 | `define GCOP_LDQ 4'd12 | |
39 | `define GCOP_RDQ 4'd13 | |
40 | `define GCOP_RDQA 4'd14 | |
41 | `define GCOP_RDQCDRRX 4'd15 | |
42 | ||
43 | // This is a simple four bit accumulator machine. It is a Havard architecture with separate | |
44 | // program and user memory address spaces. | |
45 | ||
9e30ab0c | 46 | module PROCESSOR (input clk, output [4:0] led, output uart_tx, input uart_rx); |
a051754e MG |
47 | // storage unit |
48 | reg [7:0] Ein; | |
49 | wire [7:0] Eout; | |
50 | reg [3:0] gcop = 4'b0; | |
51 | wire [6:0] ostate; | |
52 | wire step_eval; | |
53 | ||
54 | reg reading_E = 0; | |
55 | ||
56 | // Handle running | |
57 | ||
58 | reg running = 1; | |
59 | ||
9e30ab0c | 60 | // Generate eval and gc clocks |
a051754e | 61 | |
9e30ab0c | 62 | reg gc_clock = 0; |
a051754e MG |
63 | wire eval_clock = !gc_clock & step_eval; |
64 | ||
9e30ab0c MG |
65 | always @ (posedge clk) |
66 | gc_clock <= !gc_clock; | |
67 | ||
a051754e MG |
68 | GC gc (.clk(gc_clock), .mclk(clk), .Ein(Ein), .Eout(Eout), .gcop(gcop), .ostate(ostate), .step_eval(step_eval)); |
69 | ||
70 | // Handle halt | |
71 | ||
72 | reg halt = 0; | |
73 | ||
74 | always @ (posedge eval_clock) begin | |
75 | if (inst == `INST_HALT) | |
76 | halt <= 1; | |
77 | ||
78 | if (!running) | |
79 | halt <= 0; | |
80 | end | |
81 | ||
82 | // UART outputs | |
83 | wire uart_rx_signal; | |
84 | wire [7:0] uart_rx_byte; | |
85 | wire uart_is_receiving; | |
86 | wire uart_is_transmitting; | |
87 | wire uart_rx_error; | |
88 | ||
89 | // Handle program space | |
90 | wire [7:0] programOut; | |
91 | ||
92 | wire [3:0] inst = programOut[7:4]; | |
93 | wire [3:0] argu = programOut[3:0]; | |
94 | ||
95 | ROM programMemory (.clk(clk), .addr(pc), .data(programOut)); | |
96 | ||
97 | // Input logic | |
98 | wire [3:0] fifo_in; | |
99 | wire [3:0] fifo_out; | |
100 | wire fifo_full; | |
101 | wire fifo_empty; | |
102 | wire fifo_re = eval_clock & inst == `INST_READ & !fifo_empty; | |
103 | wire fifo_we = uart_rx_signal & !fifo_full; | |
104 | ||
105 | ascii_to_hex a2h (.ascii({1'b0, uart_rx_byte[6:0]}), .hex(fifo_in)); | |
106 | ||
107 | generic_fifo_sc_a #(.dw(4), .aw(4)) fifo | |
108 | (.clk(clk), | |
109 | .rst(1'b1), | |
110 | .re(fifo_re), | |
111 | .we(fifo_we), | |
112 | .din(fifo_in), | |
113 | .dout(fifo_out), | |
114 | .full(fifo_full), | |
115 | .empty(fifo_empty)); | |
116 | ||
117 | // Output logic | |
118 | reg started_writing = 0; | |
119 | ||
120 | always @ (posedge eval_clock) begin | |
121 | if (started_writing) | |
122 | started_writing <= 0; | |
123 | else if (inst == `INST_WRITE & !uart_is_transmitting) | |
124 | started_writing <= 1; | |
125 | end | |
126 | ||
127 | // Handle PC | |
128 | reg [3:0] pc = 0; | |
129 | ||
130 | wire [3:0] next = pc + 4'b0001; | |
131 | wire [3:0] prev = pc + 4'b1111; | |
132 | ||
a051754e MG |
133 | wire [3:0] newPc = |
134 | (inst == `INST_JP) ? argu : | |
135 | (inst == `INST_JPZ) & (accum == 4'b0000) ? argu : | |
136 | started_writing ? next : | |
137 | (inst == `INST_WRITE) ? pc : | |
138 | (inst == `INST_READ) & !fifo_re ? pc : | |
139 | (inst == `INST_RDQ) & !reading_E ? pc : | |
140 | (inst != `INST_HALT) ? next : | |
a051754e MG |
141 | pc; |
142 | ||
143 | always @ (posedge eval_clock) begin | |
144 | pc <= newPc; | |
145 | end | |
146 | ||
147 | // Handle user memory | |
148 | wire [3:0] userMemoryOut; | |
149 | ||
150 | RAM #(.DATA_BITS(4),.ADDRESS_BITS(4)) userMemory (.clk(clk), .write(eval_clock & (inst == `INST_STM)), .addr(argu), .in_data(accum), .out_data(userMemoryOut)); | |
151 | ||
152 | // Handle accumulator | |
153 | reg [3:0] accum = 0; | |
154 | ||
155 | wire [3:0] newAccum = | |
156 | (inst == `INST_LDI) ? argu : | |
157 | (inst == `INST_ADD) ? accum + argu : | |
158 | (inst == `INST_SUB) ? accum - argu : | |
159 | (inst == `INST_LDM) ? userMemoryOut : | |
160 | fifo_re ? fifo_out : | |
161 | reading_E ? Eout[3:0] : | |
162 | accum; | |
163 | ||
164 | always @ (posedge eval_clock) begin | |
165 | accum <= newAccum; | |
166 | end | |
167 | ||
168 | // UART logic | |
169 | wire uart_tx_signal = started_writing; | |
170 | wire [7:0] uart_tx_byte; | |
171 | ||
172 | hex_to_ascii h2a (.hex(accum), .ascii(uart_tx_byte)); | |
173 | ||
9e30ab0c MG |
174 | // 300 baud uart |
175 | uart #(.CLOCK_DIVIDE(5)) 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)); | |
a051754e MG |
176 | |
177 | // GC logic | |
178 | always @ (posedge eval_clock) begin | |
179 | if (reading_E) begin | |
180 | reading_E <= 0; | |
181 | gcop <= `GCOP_NOP; | |
182 | end else begin | |
183 | if(inst == `INST_CONS) begin | |
184 | Ein <= {4'b0, accum}; | |
185 | gcop <= `GCOP_CONS; | |
186 | end else if(inst == `INST_LDQ) begin | |
187 | Ein <= {4'b0, accum}; | |
188 | gcop <= `GCOP_LDQ; | |
189 | end else if(inst == `INST_RDQ) begin | |
190 | Ein <= 8'b0; | |
191 | reading_E <= 1; | |
192 | gcop <= `GCOP_RDQ; | |
193 | end else if(inst == `INST_CAR) begin | |
194 | Ein <= {4'b0, accum}; | |
195 | gcop <= `GCOP_CAR; | |
196 | end else if(inst == `INST_CDR) begin | |
197 | Ein <= {4'b0, accum}; | |
198 | gcop <= `GCOP_CDR; | |
199 | end else begin | |
200 | Ein <= 8'b0; | |
201 | gcop <= `GCOP_NOP; | |
202 | end | |
203 | end | |
204 | end | |
205 | ||
206 | // Assign the outputs | |
207 | ||
208 | /* assign led[0] = uart_tx; | |
209 | assign led[1] = uart_is_transmitting; | |
210 | assign led[2] = uart_is_receiving; | |
211 | assign led[3] = uart_rx_signal; | |
212 | assign led[4] = uart_rx_error; | |
213 | assign led[5] = fifo_empty; | |
214 | assign led[6] = fifo_full; | |
9e30ab0c | 215 | assign led[7] = fifo_re; |
a051754e MG |
216 | assign led[7:4] = Ein[3:0]; |
217 | assign led[3:0] = Eout[3:0]; | |
218 | // assign led[15:8] = programOut; | |
219 | // assign led[15:8] = uart_rx_byte; | |
a051754e MG |
220 | assign led[13:8] = ostate; |
221 | assign led[19:16] = pc; | |
222 | assign led[23:20] = accum; | |
9e30ab0c | 223 | assign indicators = {1'b0, (!running & `EXECUTE_BUTTON) | running_clk, halt, running & !halt};*/ |
a051754e | 224 | |
9e30ab0c MG |
225 | assign led[0] = eval_clock; |
226 | assign led[1] = uart_is_transmitting; | |
227 | assign led[2] = uart_is_receiving; | |
228 | assign led[3] = recv_error; | |
a051754e | 229 | endmodule |