`include "util.svh" module core #( ADDR_BITS = 12 , DATA_BITS = 12 ) ( input bit clk , input bit 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("build/mem/hello.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:7] page; bit [ADDR_BITS-1:0] pc; bit [2:0] opcode; bit [8:0] operand; bit [DATA_BITS-1:0] acc; bit link; bit i; bit z; bit [6:0] wip; bit [ADDR_BITS-1:0] address; enum { FETCH , DECODE , INDIRECT , INDIRECTED , PREINC , AGEN , EXEC , MEMWAIT , HALT } state; always_ff @(posedge clk) begin if (reset) begin mem_valid = 0; rx_ready = 0; tx_valid = 0; tx_data = 0; pc = 'o200; acc = 0; link = 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; page = pc[ADDR_BITS-1:7]; ++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); {i, z, wip} = operand; if (z) address = {page, wip}; else address = {5'b0, wip}; case (opcode) 'b000, 'b001, 'b010: state = i ? INDIRECT : AGEN; 'b011, 'b100: state = i ? INDIRECT : EXEC; 'b101: begin if (i) begin state = INDIRECT; end else begin pc = address; end 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 if (address[7:3] == 5'b00001) begin address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; address += 1; state = PREINC; end else begin address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; case (opcode) 'b000, 'b001, 'b010: state = AGEN; 'b011, 'b100: state = EXEC; 'b101: begin pc = address; state = FETCH; end endcase end end end PREINC: begin mem_valid = 1; mem_write = 1; mem_write_data = address[DATA_BITS-1:0]; case (opcode) 'b000, 'b001, 'b010: state = `lag(mem_ready) ? PREINC : AGEN; 'b011, 'b100, 'b101: state = `lag(mem_ready) ? PREINC : EXEC; endcase end AGEN: begin mem_valid = 1; case (opcode) 'b000, 'b001, 'b010: mem_write = 0; endcase mem_address = address; state = `lag(mem_ready) ? EXEC : AGEN; end EXEC: begin automatic bit stall = 0; if (`lag(mem_ready)) begin mem_valid = 0; mem_write = 0; end else if (mem_valid) begin stall = 1; end case (opcode) 'b000, 'b001, 'b010: if (! `lag(mem_read_valid)) stall = 1; endcase if (! stall) begin state = FETCH; case (opcode) 'b000: acc &= `lag(mem_read_data); 'b001: {link, acc} += {1'b0, `lag(mem_read_data)}; 'b010: begin mem_valid = 1; mem_address = address; mem_write = 1; mem_write_data = `lag(mem_read_data) + 1; if (mem_write_data == 0) ++pc; state = MEMWAIT; end 'b011: begin mem_valid = 1; mem_address = address; mem_write = 1; mem_write_data = acc; acc = 0; state = MEMWAIT; end 'b100: begin mem_valid = 1; mem_address = address; mem_write = 1; mem_write_data = pc[DATA_BITS-1:0]; pc = address + 1; state = MEMWAIT; end 'b101: pc = address; endcase end end MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT; HALT: $finish; endcase end end endmodule