`include "util.svh" module top #( ADDR_BITS = 14 , DATA_BITS = 12 ) ( input bit clk // verilator public , input bit reset_n // verilator public ); bit reset = 0; bit have_reset = 0; always_ff @(posedge clk) if (reset) have_reset <= 1; assign reset = !reset_n || !have_reset; bit mem_ready; bit mem_valid; bit mem_write; bit [ADDR_BITS-1:0] mem_address; bit [DATA_BITS-1:0] mem_write_data; bit mem_read_valid; bit [DATA_BITS-1:0] mem_read_data; mem #( .ADDR_BITS(ADDR_BITS) , .DATA_BITS(DATA_BITS) , .INIT_FILE("mem/mem.hex") ) memory ( .clk(clk) , .reset(reset) , .ready(mem_ready) , .valid(mem_valid) , .address(mem_address) , .write(mem_write) , .write_data(mem_write_data) , .read_valid(mem_read_valid) , .read_data(mem_read_data) ); bit rx_ready; bit rx_valid; bit [7:0] rx_data; bit tx_ready; bit tx_valid; bit [7:0] tx_data; jtag_uart #( .INSTANCE(0) ) uart0 ( .clk(clk) , .reset(reset) , .rx_ready(rx_ready) , .rx_valid(rx_valid) , .rx_data(rx_data) , .tx_ready(tx_ready) , .tx_valid(tx_valid) , .tx_data(tx_data) ); bit [ADDR_BITS-1:0] pc; bit [3:0] opcode; bit [7:0] operand; bit [DATA_BITS-1:0] acc; bit [ADDR_BITS-1:0] address; bit [DATA_BITS-1:0] sign_extended_operand; enum { FETCH , DECODE , INDIRECT , INDIRECTED , AGEN , MEMORY , HALT } state; always_ff @(posedge clk) begin if (reset) begin mem_valid = 0; rx_ready = 0; tx_valid = 0; tx_data = 0; pc = 0; acc = 0; state = state.first; end else begin if (`lag(tx_ready)) tx_valid = 0; case (state) FETCH: begin mem_valid = 1; mem_address = pc; mem_write = 0; if (`lag(mem_ready)) begin state = DECODE; ++pc; end end DECODE: begin mem_valid = 0; mem_write = 0; if (`lag(mem_read_valid)) begin state = FETCH; {opcode, operand} = `lag(mem_read_data); sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; case (opcode) 'h0: begin if (operand[0]) acc = 0; if (operand[1]) ++acc; if (operand[2]) --acc; if (operand[6]) state = MEMORY; if (operand == 0) state = HALT; end 'h1: acc = sign_extended_operand; 'h2, 'h3: begin address = {7'b0, operand[6:0]}; state = operand[7] ? INDIRECT : AGEN; end 'h4: if (acc != sign_extended_operand) ++pc; 'h5: begin if (operand[7]) begin address = {7'b0, operand[6:0]}; state = INDIRECT; end else begin pc = pc + {{(ADDR_BITS-7){operand[6]}}, operand[6:0]}; end end 'h6: begin mem_write_data = acc % 10 + 'h30; acc = acc / 10; address = {7'b0, operand[6:0]}; state = operand[7] ? INDIRECT : AGEN; end endcase end end INDIRECT: begin mem_valid = 1; mem_write = 0; mem_address = address; state = `lag(mem_ready) ? INDIRECTED : INDIRECT; end INDIRECTED: begin if (`lag(mem_ready)) begin mem_valid = 0; mem_write = 0; end if (`lag(mem_read_valid)) begin address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; state = AGEN; end end AGEN: begin mem_valid = 0; mem_write = 0; state = FETCH; case (opcode) 'h2: begin mem_valid = 1; mem_address = address; state = `lag(mem_ready) ? MEMORY : AGEN; end 'h3: begin mem_valid = 1; mem_address = address; mem_write = 1; mem_write_data = acc; state = `lag(mem_ready) ? FETCH : AGEN; end 'h5: pc = address; 'h6: begin mem_valid = 1; mem_address = address; mem_write = 1; state = `lag(mem_ready) ? FETCH : AGEN; end endcase end MEMORY: begin if (`lag(mem_ready)) begin mem_valid = 0; mem_write = 0; end state = FETCH; case (opcode) 'h0: begin if (operand[6]) begin if (tx_valid) begin state = MEMORY; end else begin tx_valid = 1; tx_data = acc[7:0]; end end end 'h2: begin if (`lag(mem_read_valid)) begin acc = acc + `lag(mem_read_data); end else begin state = MEMORY; end end endcase end HALT: $finish; endcase end end endmodule