diff --git a/src/beepo.v b/src/beepo.v index 97d3e4a..990d378 100644 --- a/src/beepo.v +++ b/src/beepo.v @@ -1,4 +1,4 @@ -`include "instructions.v" +// `include "instructions.v" module Beepo #( parameter FREQ = 27_000_000, @@ -32,16 +32,16 @@ module Beepo #( localparam [3:0] ARG_A = 7; // Absolute address immediate, 64 bit localparam [3:0] ARG_N = 8; // No argument - localparam [0:31] ARG_SIZES = {4'd1, 4'd4, 4'd2, 4'd1, 4'd2, 4'd4, 4'd8, 4'd8}; + localparam [0:31] ARG_SIZES = {4'h1, 4'h4, 4'h2, 4'h1, 4'h2, 4'h4, 4'h8, 4'h8}; localparam PC_START = 0; localparam NUM_REGS = 4; reg [2:0] r_state = IDLE; - reg [WORD_SIZE-1:0] r_tick = 0; // Registers reg [WORD_SIZE-1:0] r_pc = PC_START; // program counter + reg [3:0] r_inc_pc = 1; reg [WORD_SIZE-1:0] r_registers [0: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 @@ -62,7 +62,12 @@ module Beepo #( reg [7:0] r_mem_index = 0; // the index of the byte in transfer reg [7:0] r_mem_reg = 0; // the register currently used in transfer wire [WORD_SIZE-1:0] w_mem_addr = r_mem_trans ? r_arg_addr : r_pc; - wire [7:0] w_mem_fetch; + // wire [7:0] w_mem_fetch; + wire [255:0] w_mem_fetch; + + reg [7:0] r_mem_tx_size = 1; + reg r_mem_start = 0; + wire [0:0] w_mem_flags = r_mem_wre; reg r_breakpoint = 0; assign o_breakpoint = r_breakpoint; @@ -72,7 +77,7 @@ module Beepo #( reg r_uart_busy = 0; reg [7:0] r_uart_left = 0; reg [WORD_SIZE-1:0] r_uart_addr = 0; - wire w_uart_ready; + wire w_uart_ready; genvar i; @@ -82,13 +87,13 @@ module Beepo #( end endgenerate - always @(posedge i_clk) r_tick <= r_tick + 1; - always @(posedge i_clk) begin if (r_breakpoint == 1) begin r_breakpoint = ~i_resume; end else if (r_mem_busy == 1) begin - r_mem_busy = 0; + r_pc <= r_pc + r_inc_pc; + r_inc_pc <= 0; + r_mem_busy <= ~w_mem_ready; end else case (r_state) IDLE: begin r_state <= FETCHI; @@ -101,7 +106,6 @@ module Beepo #( r_arg_bit <= 0; r_mem_trans <= 0; - case (w_mem_fetch) `TX: r_arg_types_packed = `TX_ARGS; `NOP: r_arg_types_packed = `NOP_ARGS; @@ -123,14 +127,14 @@ module Beepo #( default: r_arg_types_packed = {ARG_N, ARG_N, ARG_N, ARG_N}; endcase - r_pc = r_pc + 1; - r_mem_busy = 1; + r_inc_pc <= 1; + r_mem_busy <= 1; if (r_arg_types_packed[15:12] != ARG_N) begin r_state <= FETCHA; - r_arg_bytes <= ARG_SIZES[r_arg_types_packed[15:12]*4+:4]; - r_arg_current_type <= r_arg_types_packed[15:12]; + r_arg_current_type = r_arg_types_packed[15:12]; + r_mem_tx_size = ARG_SIZES[r_arg_current_type*4+:4]; r_arg_types[0] <= r_arg_types_packed[15:12]; r_arg_types[1] <= r_arg_types_packed[11:8]; @@ -143,38 +147,36 @@ module Beepo #( r_arg_regs[3] <= 0; r_arg_imm <= 0; r_arg_addr <= 0; + end else r_state <= EXEC; end FETCHA: begin 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_mem_fetch; + ARG_O: r_arg_addr <= w_mem_fetch; + ARG_P: r_arg_addr <= w_mem_fetch; + ARG_B: r_arg_imm <= w_mem_fetch; + ARG_H: r_arg_imm <= w_mem_fetch; + ARG_W: r_arg_imm <= w_mem_fetch; + ARG_D: r_arg_imm <= w_mem_fetch; + ARG_A: r_arg_addr <= w_mem_fetch; endcase - r_pc <= r_pc + 1; - r_mem_busy <= 1; - r_arg_bytes = r_arg_bytes - 1; - r_arg_bit <= r_arg_bit + 8; - - if (r_arg_bytes == 0) begin - r_arg_index = r_arg_index + 1; - r_arg_current_type = r_arg_types[r_arg_index]; + r_arg_index = r_arg_index + 1; + r_inc_pc = ARG_SIZES[r_arg_current_type*4+:4]; + r_arg_current_type = r_arg_types[r_arg_index]; - // 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_bytes <= ARG_SIZES[r_arg_current_type*4+:4]; - end + // Execute when there is no next argument or r_arg_index has overflowed + if (r_arg_current_type == ARG_N || r_arg_index == 0) begin + r_state <= EXEC; + r_pc <= r_pc + r_inc_pc; + r_inc_pc <= 0; + end else begin + r_mem_busy <= 1; + r_mem_tx_size = ARG_SIZES[(r_arg_current_type)*4+:4]; end end end @@ -193,21 +195,26 @@ module Beepo #( r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]]; r_mem_index <= 0; r_mem_reg <= r_arg_regs[0]; - r_mem_busy <= 1; r_state <= MEMR; - r_mem_trans <= 1; + r_mem_tx_size <= r_arg_imm; + r_mem_busy <= 1; + // r_mem_trans <= 1; end end `ST: begin if (r_arg_imm > 0) begin r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]]; - r_mem_index <= 1; r_mem_reg <= r_arg_regs[0]; r_mem_wre <= 1; - r_mem_in <= r_registers[r_arg_regs[0]][0+:8]; + r_mem_tx_size <= r_arg_imm; + r_mem_in <= r_registers[r_arg_regs[0]]; r_mem_busy <= 1; - r_state <= MEMR; - r_mem_trans <= 1; + + // r_mem_index <= 1; + // r_mem_in <= r_registers[r_arg_regs[0]][0+:8]; + // r_mem_busy <= 1; + // r_state <= MEMR; + // r_mem_trans <= 1; end end `EBP: r_breakpoint = 1; @@ -236,29 +243,33 @@ module Beepo #( end MEMR: begin case (r_instr) - `LD: set_reg_part(r_mem_reg, w_mem_fetch, r_mem_index*8); - `ST: r_mem_in <= r_registers[r_mem_reg][r_mem_index*8+:8]; - endcase + `LD: set_reg_dword(r_mem_reg, w_mem_fetch); + endcase - r_mem_busy <= 1; + // case (r_instr) + // `LD: set_reg_part(r_mem_reg, w_mem_fetch, r_mem_index*8); + // `ST: r_mem_in <= r_registers[r_mem_reg][r_mem_index*8+:8]; + // endcase - if (r_arg_imm == 1) begin - // reached the end of the transfer - r_mem_wre <= 0; - r_mem_trans <= 0; - r_state <= FETCHI; - end else begin - r_mem_index = r_mem_index + 1; + // r_mem_busy <= 1; - if (r_mem_index == WORD_SIZE / 8) begin - // reached the end of this register - r_mem_reg <= r_mem_reg + 1; - r_mem_index <= 0; - end + // if (r_arg_imm == 1) begin + // // reached the end of the transfer + // r_mem_wre <= 0; + // r_mem_trans <= 0; + // r_state <= FETCHI; + // end else begin + // r_mem_index = r_mem_index + 1; - r_arg_addr <= r_arg_addr + 1; - r_arg_imm <= r_arg_imm - 1; - end + // if (r_mem_index == WORD_SIZE / 8) begin + // // reached the end of this register + // r_mem_reg <= r_mem_reg + 1; + // r_mem_index <= 0; + // end + + // r_arg_addr <= r_arg_addr + 1; + // r_arg_imm <= r_arg_imm - 1; + // end end endcase @@ -319,14 +330,25 @@ module Beepo #( // .tx_pin(o_uart_tx) // ); - spMem mem ( - .clk(i_clk), - .ad(w_mem_addr), - .din(r_mem_in), - .dout(w_mem_fetch), - .oce(0), - .ce(1), - .reset(0), - .wre(r_mem_wre) + // spMem mem ( + // .clk(i_clk), + // .ad(w_mem_addr), + // .din(r_mem_in), + // .dout(w_mem_fetch), + // .oce(0), + // .ce(1), + // .reset(0), + // .wre(r_mem_wre) + // ); + + Mmu mem ( + .i_clk(i_clk), + .i_addr(w_mem_addr), + .i_in(r_mem_in), + .i_flags(w_mem_flags), + .i_size(r_mem_tx_size), + .i_start(r_mem_busy), + .o_ready(w_mem_ready), + .o_out(w_mem_fetch) ); endmodule \ No newline at end of file diff --git a/src/bus.v b/src/mmu.v similarity index 52% rename from src/bus.v rename to src/mmu.v index 486f250..700a17f 100644 --- a/src/bus.v +++ b/src/mmu.v @@ -11,7 +11,7 @@ // 3. Set i_flags.0 to 1 // 4. Pulse i_start high // 5. When o_ready goes high, the transfer is complete -module Bus#( +module Mmu#( parameter ADDR_WIDTH = 16, parameter DATA_WIDTH = 256 ) ( @@ -30,41 +30,61 @@ module Bus#( localparam S_IDLE = 0; localparam S_BUSY = 1; - reg r_status = S_IDLE; - reg r_enable = 0; + reg r_status = S_IDLE; + reg r_enabled = 0; + reg r_ready = 0; reg [5:0] r_tx_size = 0; reg [5:0] r_byte_index = 0; - reg [7:0] r_in = 0; + reg [7:0] r_in = 0; reg [ADDR_WIDTH-1:0] r_mem_addr; + reg [DATA_WIDTH-1:0] r_out = 0; - assign o_ready = r_byte_index == 0 || r_byte_index > r_tx_size; + wire [7:0] w_mem_fetch; + + assign o_ready = r_ready; + assign o_out = r_out; always @(posedge i_clk or posedge i_start) begin - if (i_start && !r_enable) begin + if (i_clk && r_ready) begin + r_ready <= 0; + end else if (i_start && !r_enabled) 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_out <= 0; 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; + r_enabled <= 1; + end else if (r_status == S_BUSY) begin + r_status <= S_IDLE; + end else if (r_enabled) begin + if (r_tx_size == 1) begin + r_out[(r_byte_index-1)*8+:8] = w_mem_fetch; + r_ready <= 1; + r_enabled = 0; + end else begin + // increment address, input next byte + r_status <= S_BUSY; + r_in <= i_in[r_byte_index*8+:8]; + r_out[(r_byte_index-1)*8+:8] = w_mem_fetch; + r_mem_addr = r_mem_addr + 1; + r_byte_index = r_byte_index + 1; + + if (r_byte_index >= r_tx_size) begin + r_ready <= 1; + r_enabled = 0; + end + end end end spMem memory ( - .dout(o_out), //output [7:0] dout + .dout(w_mem_fetch), //output [7:0] dout .clk(i_clk), //input clk .oce(1'b0), //input oce (unused) - .ce(r_enable), //input ce + .ce(r_enabled), //input ce .reset(1'b0), //input reset - .wre(i_flags[0]), //input wre (write enable) + .wre(i_flags[0]), //input wre (write enabled) .ad(r_mem_addr), //input [15:0] ad .din(r_in) //input [7:0] din ); diff --git a/tests/Makefile b/tests/Makefile index cc7ffa0..63c4c41 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -5,7 +5,7 @@ HBASM = ./hbasm SPMEM = spmem.v INPUT_FILE = inputs.txt -BUILD_DEPS = ../src/beepo.v ../src/instructions.v ../src/uart_tx.v ../src/multi7.v ../src/bus.v +BUILD_DEPS = ../src/beepo.v ../src/instructions.v ../src/uart_tx.v ../src/multi7.v ../src/mmu.v %.clean: %/build rm -r $< diff --git a/tests/inputs.txt b/tests/inputs.txt index a4e9858..c78aa0b 100644 --- a/tests/inputs.txt +++ b/tests/inputs.txt @@ -1,4 +1,4 @@ ../src/instructions.v ../src/uart_tx.v ../src/multi7.v -../src/bus.v +../src/mmu.v diff --git a/tests/mem/program.rhai b/tests/mem/program.rhai index 62e6c48..ff5106c 100644 --- a/tests/mem/program.rhai +++ b/tests/mem/program.rhai @@ -1,2 +1,13 @@ -nop(); -ebp(); \ No newline at end of file +li64 (r4, 0x1020304050607080); +st (r4, r0, 0x400, 8); +ld (r1, r0, 0x400, 8); +ebp(); + +ld (r2, r0, 0x404, 4); +ebp(); + +li64 (r1, 0x1010202030304040); +li64 (r2, 0x5050606070708080); +st (r1, r0, 0x410, 16); +ld (r3, r0, 0x410, 16); +tx(); \ No newline at end of file diff --git a/tests/mem/top.v b/tests/mem/top.v index f65d79b..e682d45 100644 --- a/tests/mem/top.v +++ b/tests/mem/top.v @@ -21,7 +21,8 @@ module tb_beepo(); wire w_breakpoint; Beepo #( - .FREQ(1) + .FREQ(1), + .WORD_SIZE(64) ) bep ( .i_clk(r_clk), .i_resume(r_resume), @@ -46,20 +47,16 @@ module tb_beepo(); $display("BREAK"); case (r_test) T_STLD: begin - // `assert(bep.r_registers[1], 64'h1020304050607080); - `assert(bep.r_registers[1], 16'h1020); + `assert(bep.r_registers[1], 64'h1020304050607080); $display("[MEM] ST/LD test passed"); end T_STLD_HALF: begin - // `assert(bep.r_registers[2], 64'h0000000010203040); - `assert(bep.r_registers[2], 16'h10); + `assert(bep.r_registers[2], 64'h0000000010203040); $display("[MEM] ST/LD Half test passed"); end T_STLD_DOUBLE: begin - // `assert(bep.r_registers[3], 64'h1010202030304040); - // `assert(bep.r_registers[4], 64'h5050606070708080); - `assert(bep.r_registers[3], 64'h1010); - `assert(bep.r_registers[4], 64'h5050); + `assert(bep.r_registers[3], 64'h1010202030304040); + `assert(bep.r_registers[4], 64'h5050606070708080); $display("[MEM] ST/LD Double test passed"); end endcase @@ -76,7 +73,7 @@ module tb_beepo(); end initial #100000 begin - $display("[ADDING] Timeout"); + $display("[MEM] Timeout"); $finish; end endmodule \ No newline at end of file