diff --git a/src/beepo.v b/src/beepo.v index 126aeb6..fd831f7 100644 --- a/src/beepo.v +++ b/src/beepo.v @@ -14,6 +14,7 @@ module Beepo #( localparam FETCHI = 1; // Instruction is fetched, start fetching first argument localparam FETCHA = 2; // Argument byte is fetched localparam EXEC = 3; // Start running + localparam MEMR = 4; // Transferring bytes between memory and registers localparam DONE = 7; // Done executing // Argument types @@ -33,13 +34,12 @@ module Beepo #( localparam NUM_REGS = 4; reg [2:0] r_state = IDLE; - reg r_fetching = 0; // counter for waiting before reading from memory reg [63:0] r_tick = 0; // Registers reg [63:0] r_pc = PC_START; // program counter reg [63:0] r_pc_latch = PC_START; // address input to ROM - reg [63:0] r_registers [0:NUM_REGS]; // up to 255 modifiable registers + reg [63:0] r_registers [1:NUM_REGS]; // up to 255 modifiable registers reg [7:0] r_instr; // the current instruction reg [7:0] r_arg_regs [0:3]; // register arguments reg [63:0] r_arg_imm = 0; // immediate argument @@ -52,7 +52,16 @@ module Beepo #( reg [3:0] r_arg_current_type = 8; // the type of the current argument reg [5:0] r_arg_bit = 0; // the current lower bit index being fetched for the current argument - wire [7:0] w_mem_fetch; + reg r_bus_wre = 0; + reg [7:0] r_bus_in = 0; + reg [4:0] r_bus_bytes = 1; // the number of bytes to transfer on the bus + reg [7:0] r_bus_index = 0; // the index of the byte in transfer + reg [7:0] r_bus_reg = 0; // the register currently used in transfer + reg r_bus_start = 0; // pulsed high when the bus should start a transfer + reg r_bus_trans = 0; // trans rights (the bus is executing a transfer instruction) + wire [63:0] w_bus_addr = r_bus_trans ? r_arg_addr : r_pc_latch; + wire [4:0] w_bus_bytes = r_bus_trans ? r_bus_bytes : 1; + wire [7:0] w_bus_fetch; genvar i; @@ -65,20 +74,23 @@ module Beepo #( always @(posedge i_clk) r_tick <= r_tick + 1; always @(posedge i_clk) begin - if (r_fetching) r_fetching <= r_fetching + 1; - else case (r_state) + if (w_bus_ready == 0) begin + r_bus_start <= 0; + r_bus_trans <= r_bus_trans & ~w_bus_ready; + end else case (r_state) IDLE: begin r_pc_latch <= r_pc; r_pc <= r_pc + 1; - r_fetching <= 1; + r_bus_start <= 1; r_state <= FETCHI; + r_bus_wre <= 0; end FETCHI: begin - r_instr <= w_mem_fetch; + r_instr <= w_bus_fetch; r_arg_index <= 0; r_arg_bit <= 0; - case (w_mem_fetch) + case (w_bus_fetch) `TX: r_arg_types_packed = `TX_ARGS; `NOP: r_arg_types_packed = `NOP_ARGS; `ADD8: r_arg_types_packed = `ADD8_ARGS; @@ -93,6 +105,8 @@ module Beepo #( `LI16: r_arg_types_packed = `LI16_ARGS; `LI32: r_arg_types_packed = `LI32_ARGS; `LI64: r_arg_types_packed = `LI64_ARGS; + `LD: r_arg_types_packed = `LD_ARGS; + `ST: r_arg_types_packed = `ST_ARGS; default: r_arg_types_packed = {ARG_N, ARG_N, ARG_N, ARG_N}; endcase @@ -100,7 +114,7 @@ module Beepo #( r_state <= FETCHA; r_pc_latch <= r_pc; r_pc <= r_pc + 1; - r_fetching <= 1; + r_bus_start <= 1; r_arg_bytes <= ARG_SIZES[r_arg_types_packed[15:12]*4+:4]; r_arg_current_type <= r_arg_types_packed[15:12]; @@ -122,19 +136,19 @@ module Beepo #( if (r_arg_current_type == ARG_N) r_state <= IDLE; else begin case (r_arg_current_type) - ARG_R: r_arg_regs[r_arg_index] <= w_mem_fetch; - ARG_O: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch; - ARG_P: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch; - ARG_B: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch; - ARG_H: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch; - ARG_W: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch; - ARG_D: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch; - ARG_A: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch; + ARG_R: r_arg_regs[r_arg_index] <= w_bus_fetch; + ARG_O: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch; + ARG_P: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch; + ARG_B: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch; + ARG_H: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch; + ARG_W: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch; + ARG_D: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch; + ARG_A: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch; endcase r_pc_latch <= r_pc; r_pc <= r_pc + 1; - r_fetching <= 1; + r_bus_start <= 1; r_arg_bytes = r_arg_bytes - 1; r_arg_bit <= r_arg_bit + 8; @@ -143,21 +157,11 @@ module Beepo #( r_arg_index = r_arg_index + 1; r_arg_current_type = r_arg_types[r_arg_index]; - if (r_arg_current_type == ARG_N) r_state <= EXEC; + // Execute when there is no next argument or r_arg_index has overflowed + if (r_arg_current_type == ARG_N || r_arg_index == 0) r_state <= EXEC; else begin - r_arg_bit <= 0; + r_arg_bit <= 0; r_arg_bytes <= ARG_SIZES[r_arg_current_type*4+:4]; - - case (r_arg_current_type) - ARG_R: r_arg_regs[r_arg_index] <= 0; - ARG_O: r_arg_addr[r_arg_bit-1] <= 0; - ARG_P: r_arg_addr[r_arg_bit-1] <= 0; - ARG_B: r_arg_imm[r_arg_bit-1] <= 0; - ARG_H: r_arg_imm[r_arg_bit-1] <= 0; - ARG_W: r_arg_imm[r_arg_bit-1] <= 0; - ARG_D: r_arg_imm[r_arg_bit-1] <= 0; - ARG_A: r_arg_addr[r_arg_bit-1] <= 0; - endcase end end end @@ -180,13 +184,57 @@ module Beepo #( `LI16: set_register(r_arg_regs[0], r_arg_imm); `LI32: set_register(r_arg_regs[0], r_arg_imm); `LI64: set_register(r_arg_regs[0], r_arg_imm); + `LD: begin + if (r_arg_imm > 0) begin + r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]]; + r_bus_index <= 0; + r_bus_reg <= r_arg_regs[0]; + r_state <= MEMR; + r_bus_start <= 1; + r_bus_trans <= 1; + r_bus_bytes <= 1; + end + end + `ST: begin + if (r_arg_imm > 0) begin + r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]]; + r_bus_index <= 0; + r_bus_reg <= r_arg_regs[0]; + r_bus_wre <= 1; + r_bus_in <= r_registers[r_arg_regs[0]][0+:8]; + r_state <= MEMR; + r_bus_start <= 1; + r_bus_trans <= 1; + r_bus_bytes <= 1; + end + end endcase end + MEMR: begin + case (r_instr) + `LD: set_register(r_arg_regs[0], w_bus_fetch); + `ST: r_bus_in <= r_registers[r_arg_regs[0]][r_bus_index]; + endcase + + if (r_arg_imm == 1) begin + // reached the end of the transfer + r_bus_wre <= 0; + r_state <= FETCHI; + end else begin + if (r_bus_index == 6) begin + // reached the end of this register + r_bus_reg <= r_bus_reg + 1; + end + + r_arg_addr <= r_arg_addr + 1; + r_arg_imm <= r_arg_imm - 1; + r_bus_start <= 1; + r_bus_trans <= 1; + end + end endcase end - - task automatic set_register( input [7:0] being_set, input [63:0] setting_to @@ -194,23 +242,29 @@ module Beepo #( if (being_set != 0) r_registers[being_set] = setting_to; endtask + task automatic set_reg_byte( + input [7:0] being_set, + input [2:0] byte_idx, + input [7:0] setting_to + ); + if (being_set != 0) r_registers[being_set][byte_idx*8+:8] = setting_to; + endtask + Multi7 display ( .i_clk(i_clk), .i_hex({r_registers[1][15:0]}), .o_segments_drive(o_segments_drive), .o_displays_neg(o_displays_neg) ); - - // TODO: Bus - // For now this is just ROM - spMem memory ( - .dout(w_mem_fetch), //output [7:0] dout - .clk(i_clk), //input clk - .oce(1'b0), //input oce (unused) - .ce(1'b1), //input ce - .reset(1'b0), //input reset - .wre(1'b0), //input wre (write enable) - .ad(r_pc_latch[0+:32]), //input [15:0] ad - .din(1'b0) //input [7:0] din + + Bus bus ( + .i_clk(i_clk), + .i_addr(w_bus_addr), + .i_in(r_bus_in), + .i_flags(r_bus_wre), + .i_size(r_bus_bytes), + .i_start(r_bus_start), + .o_ready(w_bus_ready), + .o_out(w_bus_fetch) ); endmodule \ No newline at end of file diff --git a/src/bus.v b/src/bus.v new file mode 100644 index 0000000..486f250 --- /dev/null +++ b/src/bus.v @@ -0,0 +1,71 @@ +// To read: +// 1. Set i_addr to start address +// 2. Set i_flags.0 to 0 +// 3. Set i_size to number of bytes to read +// 4. Pulse i_start high +// 5. When o_ready goes high, the read data will be in o_out + +// To write: +// 1. Set i_addr to start address +// 2. Set i_in to the data to write +// 3. Set i_flags.0 to 1 +// 4. Pulse i_start high +// 5. When o_ready goes high, the transfer is complete +module Bus#( + parameter ADDR_WIDTH = 16, + parameter DATA_WIDTH = 256 +) ( + input i_clk, + input [ADDR_WIDTH-1:0] i_addr, + input [DATA_WIDTH-1:0] i_in, + input [0:0] i_flags, // flags.0: read(0)/write(1) + input [5:0] i_size, + input i_start, // pulsed high to start transfer + output o_ready, + output [DATA_WIDTH-1:0] o_out +); + localparam F_READ = 'b0; + localparam F_WRITE = 'b1; + + localparam S_IDLE = 0; + localparam S_BUSY = 1; + + reg r_status = S_IDLE; + reg r_enable = 0; + reg [5:0] r_tx_size = 0; + reg [5:0] r_byte_index = 0; + reg [7:0] r_in = 0; + reg [ADDR_WIDTH-1:0] r_mem_addr; + + assign o_ready = r_byte_index == 0 || r_byte_index > r_tx_size; + + always @(posedge i_clk or posedge i_start) begin + if (i_start && !r_enable) begin + r_mem_addr <= i_addr; + r_enable <= 1; + r_status <= S_BUSY; + r_tx_size <= i_size; + r_in <= i_in[0+:8]; + r_byte_index <= 1; // 0 is transferring now + end else if (r_status == S_BUSY) r_status <= S_IDLE; + else if (r_enable && r_byte_index > r_tx_size) r_enable <= 0; + else if (r_enable) begin + // increment address, input next byte + r_mem_addr <= r_mem_addr + 1; + r_status <= S_BUSY; + r_in <= i_in[r_byte_index*8+:8]; + r_byte_index <= r_byte_index + 1; + end + end + + spMem memory ( + .dout(o_out), //output [7:0] dout + .clk(i_clk), //input clk + .oce(1'b0), //input oce (unused) + .ce(r_enable), //input ce + .reset(1'b0), //input reset + .wre(i_flags[0]), //input wre (write enable) + .ad(r_mem_addr), //input [15:0] ad + .din(r_in) //input [7:0] din + ); +endmodule \ No newline at end of file diff --git a/src/instructions.v b/src/instructions.v index d99692a..65852ef 100644 --- a/src/instructions.v +++ b/src/instructions.v @@ -51,5 +51,11 @@ `define LI64 'h4B `define LI64_ARGS {ARG_R, ARG_D, ARG_N, ARG_N} +// Absolute addresing memory access operations +`define LD 'h4D +`define LD_ARGS {ARG_R, ARG_R, ARG_A, ARG_H} +`define ST 'h4E +`define ST_ARGS {ARG_R, ARG_R, ARG_A, ARG_H} + // Conditional jump `define JEQ 'h56 \ No newline at end of file diff --git a/tests/adding/Makefile b/tests/adding/Makefile index 3e53cff..d42b002 100644 --- a/tests/adding/Makefile +++ b/tests/adding/Makefile @@ -5,8 +5,10 @@ HBASM = ../hbasm SPMEM = ../spmem.v INPUT_FILE = inputs.txt -BUILD_DEPS = ../../src/beepo.v ../../src/instructions.v adding.v ../../src/uart_tx.v ../../src/multi7.v build/spmem_gen.v +BUILD_DEPS = ../../src/beepo.v ../../src/instructions.v adding.v ../../src/uart_tx.v ../../src/multi7.v ../../src/bus.v build/spmem_gen.v +clean: + rm -r build ${SLAPPER_BUILD}: cargo build --manifest-path ${SLAPPER_DIR}/Cargo.toml -r @@ -34,5 +36,5 @@ wave: build/dump.vcd assemble: build/program.bin insert-mem: build/spmem_gen.v -synthesize: build/out -run: build/dump.vcd \ No newline at end of file +synth: build/out +run: build/dump.vcd diff --git a/tests/adding/adding.v b/tests/adding/adding.v index 1407c48..df49d0b 100644 --- a/tests/adding/adding.v +++ b/tests/adding/adding.v @@ -22,7 +22,11 @@ module tb_adding(); initial begin $dumpfile("build/dump.vcd"); - $dumpvars(0, tb_adding, bep.r_registers[1]); + $dumpvars(0, tb_adding, + bep.r_arg_regs[0], bep.r_arg_regs[1], + bep.r_arg_regs[2], bep.r_arg_regs[3], + bep.r_registers[1] + ); end // should probably do more granular tests diff --git a/tests/adding/inputs.txt b/tests/adding/inputs.txt index d805ac5..7701394 100644 --- a/tests/adding/inputs.txt +++ b/tests/adding/inputs.txt @@ -2,4 +2,5 @@ adding.v ../../src/uart_tx.v ../../src/multi7.v +../../src/bus.v build/spmem_gen.v