`include "asciihex.v" `include "generic_fifo_sc_a.v" `include "gc.v" `include "ram.v" `include "rom.v" `include "prescaler.v" `include "single_trigger.v" `include "uart.v" `define INST_JPZ 4'b0111 `define INST_JP 4'b0110 `define INST_STM 4'b0101 `define INST_LDM 4'b0100 `define INST_SUB 4'b0011 `define INST_ADD 4'b0010 `define INST_LDI 4'b0001 `define INST_HALT 4'b0000 `define INST_READ 4'b1000 `define INST_WRITE 4'b1001 `define INST_CONS 4'b1010 `define INST_LDQ 4'b1110 `define INST_RDQ 4'b1100 `define INST_CAR 4'b1111 `define INST_CDR 4'b1101 `define GCOP_NOP 4'd0 `define GCOP_CDR 4'd1 `define GCOP_CAR 4'd2 `define GCOP_CDRQ 4'd3 `define GCOP_CARQ 4'd4 `define GCOP_CARR 4'd5 `define GCOP_CDRRX 4'd6 `define GCOP_CARRX 4'd7 `define GCOP_CDRQX 4'd8 `define GCOP_CONS 4'd9 `define GCOP_XCONS 4'd10 `define GCOP_RPLACDR 4'd11 `define GCOP_LDQ 4'd12 `define GCOP_RDQ 4'd13 `define GCOP_RDQA 4'd14 `define GCOP_RDQCDRRX 4'd15 // This is a simple four bit accumulator machine. It is a Havard architecture with separate // program and user memory address spaces. module PROCESSOR (input clk, output [4:0] led, output uart_tx, input uart_rx); // storage unit reg [7:0] Ein; wire [7:0] Eout; reg [3:0] gcop = 4'b0; wire [6:0] ostate; wire step_eval; reg reading_E = 0; // Handle running reg running = 1; // Generate eval and gc clocks reg gc_clock = 0; wire eval_clock = !gc_clock & step_eval; always @ (posedge clk) gc_clock <= !gc_clock; GC gc (.clk(gc_clock), .mclk(clk), .Ein(Ein), .Eout(Eout), .gcop(gcop), .ostate(ostate), .step_eval(step_eval)); // Handle halt reg halt = 0; always @ (posedge eval_clock) begin if (inst == `INST_HALT) halt <= 1; if (!running) halt <= 0; end // UART outputs wire uart_rx_signal; wire [7:0] uart_rx_byte; wire uart_is_receiving; wire uart_is_transmitting; wire uart_rx_error; // Handle program space wire [7:0] programOut; wire [3:0] inst = programOut[7:4]; wire [3:0] argu = programOut[3:0]; ROM programMemory (.clk(clk), .addr(pc), .data(programOut)); // Input logic wire [3:0] fifo_in; wire [3:0] fifo_out; wire fifo_full; wire fifo_empty; wire fifo_re = eval_clock & inst == `INST_READ & !fifo_empty; wire fifo_we = uart_rx_signal & !fifo_full; ascii_to_hex a2h (.ascii({1'b0, uart_rx_byte[6:0]}), .hex(fifo_in)); generic_fifo_sc_a #(.dw(4), .aw(4)) fifo (.clk(clk), .rst(1'b1), .re(fifo_re), .we(fifo_we), .din(fifo_in), .dout(fifo_out), .full(fifo_full), .empty(fifo_empty)); // Output logic reg started_writing = 0; always @ (posedge eval_clock) begin if (started_writing) started_writing <= 0; else if (inst == `INST_WRITE & !uart_is_transmitting) started_writing <= 1; end // Handle PC reg [3:0] pc = 0; wire [3:0] next = pc + 4'b0001; wire [3:0] prev = pc + 4'b1111; wire [3:0] newPc = (inst == `INST_JP) ? argu : (inst == `INST_JPZ) & (accum == 4'b0000) ? argu : started_writing ? next : (inst == `INST_WRITE) ? pc : (inst == `INST_READ) & !fifo_re ? pc : (inst == `INST_RDQ) & !reading_E ? pc : (inst != `INST_HALT) ? next : pc; always @ (posedge eval_clock) begin pc <= newPc; end // Handle user memory wire [3:0] userMemoryOut; RAM #(.DATA_BITS(4),.ADDRESS_BITS(4)) userMemory (.clk(clk), .write(eval_clock & (inst == `INST_STM)), .addr(argu), .in_data(accum), .out_data(userMemoryOut)); // Handle accumulator reg [3:0] accum = 0; wire [3:0] newAccum = (inst == `INST_LDI) ? argu : (inst == `INST_ADD) ? accum + argu : (inst == `INST_SUB) ? accum - argu : (inst == `INST_LDM) ? userMemoryOut : fifo_re ? fifo_out : reading_E ? Eout[3:0] : accum; always @ (posedge eval_clock) begin accum <= newAccum; end // UART logic wire uart_tx_signal = started_writing; wire [7:0] uart_tx_byte; hex_to_ascii h2a (.hex(accum), .ascii(uart_tx_byte)); // 300 baud uart 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)); // GC logic always @ (posedge eval_clock) begin if (reading_E) begin reading_E <= 0; gcop <= `GCOP_NOP; end else begin if(inst == `INST_CONS) begin Ein <= {4'b0, accum}; gcop <= `GCOP_CONS; end else if(inst == `INST_LDQ) begin Ein <= {4'b0, accum}; gcop <= `GCOP_LDQ; end else if(inst == `INST_RDQ) begin Ein <= 8'b0; reading_E <= 1; gcop <= `GCOP_RDQ; end else if(inst == `INST_CAR) begin Ein <= {4'b0, accum}; gcop <= `GCOP_CAR; end else if(inst == `INST_CDR) begin Ein <= {4'b0, accum}; gcop <= `GCOP_CDR; end else begin Ein <= 8'b0; gcop <= `GCOP_NOP; end end end // Assign the outputs /* assign led[0] = uart_tx; assign led[1] = uart_is_transmitting; assign led[2] = uart_is_receiving; assign led[3] = uart_rx_signal; assign led[4] = uart_rx_error; assign led[5] = fifo_empty; assign led[6] = fifo_full; assign led[7] = fifo_re; assign led[7:4] = Ein[3:0]; assign led[3:0] = Eout[3:0]; // assign led[15:8] = programOut; // assign led[15:8] = uart_rx_byte; assign led[13:8] = ostate; assign led[19:16] = pc; assign led[23:20] = accum; assign indicators = {1'b0, (!running & `EXECUTE_BUTTON) | running_clk, halt, running & !halt};*/ assign led[0] = eval_clock; assign led[1] = uart_is_transmitting; assign led[2] = uart_is_receiving; assign led[3] = recv_error; endmodule