Initial commit
[yule.git] / processor_4.v
CommitLineData
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
55module 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
264endmodule
This page took 0.023953 seconds and 4 git commands to generate.