From a400aceb574400fad6b269927793a5c13aab647c Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sun, 5 Nov 2023 20:53:02 +0100 Subject: [PATCH] feat: make RAM word aligned, add byte_enable Support sb, sh, lb, lh using byte enable instead of non-word aligned reads and writes. --- programs/start.S | 3 ++- src/cpu.sv | 22 +++++++++++++++++++--- src/ram.sv | 28 ++++++++++++++++------------ testbench/tb_cpu_add.sv | 7 +++---- testbench/tb_cpu_branches.sv | 7 +++---- testbench/tb_cpu_gcd.sv | 7 +++---- testbench/tb_cpu_simple.sv | 7 +++---- testbench/tb_cpu_tests.sv | 7 +++---- 8 files changed, 52 insertions(+), 36 deletions(-) diff --git a/programs/start.S b/programs/start.S index 85821c6..71cb102 100755 --- a/programs/start.S +++ b/programs/start.S @@ -2,7 +2,8 @@ .text _start: - addi sp, x0, 127 + addi sp, x0, 124 call main _loop: + ebreak j _loop diff --git a/src/cpu.sv b/src/cpu.sv index c734df3..54446e7 100755 --- a/src/cpu.sv +++ b/src/cpu.sv @@ -12,7 +12,7 @@ module cpu( output [31:0] memory_address, input [31:0] memory_out, output reg [31:0] memory_write, - output memory_mask_t memory_mask, + output [3:0] memory_byte_enable, output reg memory_we ); parameter WIDTH = 32; @@ -41,6 +41,8 @@ module cpu( wire memory_sign_extension; + memory_mask_t memory_mask; + function bit[31:0] mem_sext_maybe; input [31:0] num; input memory_mask_t mask; @@ -55,7 +57,20 @@ module cpu( end endfunction - assign memory_write = mem_sext_maybe(.num(reg_rd2), .mask(memory_mask), .sext(memory_sign_extension)); + function bit[3:0] mask_to_mask_bytes; + input memory_mask_t mask; + begin + case(mask) + MEM_BYTE: return 4'b0001; + MEM_HALFWORD: return 4'b0011; + MEM_WORD: return 4'b1111; + default: return 0; + endcase + end + endfunction + + assign memory_byte_enable = mask_to_mask_bytes(.mask(memory_mask)) << memory_address[1:0]; + assign memory_write = reg_rd2 << (8*memory_address[1:0]); assign memory_address = alu_out; // alu source 1 @@ -89,11 +104,12 @@ module cpu( end // register file write source + // TODO forwarding pipelined, split to two instead always_comb begin case (reg_write_src) RD_ALU : reg_write = alu_out; RD_PC_PLUS : reg_write = pc + 4; - RD_MEMORY : reg_write = mem_sext_maybe(.num(memory_out), .mask(memory_mask), .sext(memory_sign_extension)); + RD_MEMORY : reg_write = mem_sext_maybe(.num(memory_out >> (8*memory_address[1:0])), .mask(memory_mask), .sext(memory_sign_extension)); default : ; endcase end diff --git a/src/ram.sv b/src/ram.sv index 69500b8..b324184 100755 --- a/src/ram.sv +++ b/src/ram.sv @@ -3,21 +3,25 @@ import cpu_types::*; module ram ( input clk, we, input [31:0] a, wd, - input memory_mask_t mask, + input [3:0] write_byte_enable, output [31:0] rd); - reg [4095:0] RAM; + reg [31:0] mask; + reg [31:0] memory[128]; - assign rd = RAM[(a[11:0] * 8) +:32]; // word aligned + assign rd = memory[a[8:2]]; // word aligned - always @(posedge clk) - if(we) begin - case(mask) - MEM_BYTE: RAM[(a[11:0] * 8) +:8] <= wd[7:0]; - MEM_HALFWORD: RAM[(a[11:0] * 8) +:16] <= wd[15:0]; - MEM_WORD: RAM[(a[11:0] * 8) +:32] <= wd[31:0]; - default: ; - endcase - end + always_comb begin + mask = { + {8{write_byte_enable[3]}}, + {8{write_byte_enable[2]}}, + {8{write_byte_enable[1]}}, + {8{write_byte_enable[0]}} + }; + end + + always_ff @ (posedge clk) + if(we) + memory[a[8:2]] = (rd & ~mask) | (wd & mask); endmodule diff --git a/testbench/tb_cpu_add.sv b/testbench/tb_cpu_add.sv index 3aaa50a..005a841 100755 --- a/testbench/tb_cpu_add.sv +++ b/testbench/tb_cpu_add.sv @@ -5,10 +5,9 @@ module tb_cpu_add(); reg clk, rst_n; wire [31:0] memory_address, memory_write, memory_out; + wire [3:0] memory_write_byte_enable; wire memory_we; - memory_mask_t memory_mask; - wire [31:0] pc; reg [31:0] instruction; @@ -22,14 +21,14 @@ module tb_cpu_add(); .memory_address(memory_address), .memory_out(memory_out), .memory_write(memory_write), - .memory_mask(memory_mask), + .memory_byte_enable(memory_write_byte_enable), .memory_we(memory_we) ); ram memory_inst( .clk(clk), .a(memory_address), - .mask(memory_mask), + .write_byte_enable(memory_write_byte_enable), .we(memory_we), .wd(memory_write), .rd(memory_out) diff --git a/testbench/tb_cpu_branches.sv b/testbench/tb_cpu_branches.sv index 0a78fb4..e976cd9 100755 --- a/testbench/tb_cpu_branches.sv +++ b/testbench/tb_cpu_branches.sv @@ -4,10 +4,9 @@ module tb_cpu_branches(); reg clk, rst_n; wire [31:0] memory_address, memory_write, memory_out; + wire [3:0] memory_write_byte_enable; wire memory_we; - memory_mask_t memory_mask; - wire [31:0] pc; reg [31:0] instruction; @@ -21,14 +20,14 @@ module tb_cpu_branches(); .memory_address(memory_address), .memory_out(memory_out), .memory_write(memory_write), - .memory_mask(memory_mask), + .memory_byte_enable(memory_write_byte_enable), .memory_we(memory_we) ); ram memory_inst( .clk(clk), .a(memory_address), - .mask(memory_mask), + .write_byte_enable(memory_write_byte_enable), .we(memory_we), .wd(memory_write), .rd(memory_out) diff --git a/testbench/tb_cpu_gcd.sv b/testbench/tb_cpu_gcd.sv index 527d027..e0fa1a5 100755 --- a/testbench/tb_cpu_gcd.sv +++ b/testbench/tb_cpu_gcd.sv @@ -4,10 +4,9 @@ module tb_cpu_gcd(); reg clk, rst_n; wire [31:0] memory_address, memory_write, memory_out; + wire [3:0] memory_write_byte_enable; wire memory_we; - memory_mask_t memory_mask; - wire [31:0] pc; reg [31:0] instruction; @@ -21,14 +20,14 @@ module tb_cpu_gcd(); .memory_address(memory_address), .memory_out(memory_out), .memory_write(memory_write), - .memory_mask(memory_mask), + .memory_byte_enable(memory_write_byte_enable), .memory_we(memory_we) ); ram memory_inst( .clk(clk), .a(memory_address), - .mask(memory_mask), + .write_byte_enable(memory_write_byte_enable), .we(memory_we), .wd(memory_write), .rd(memory_out) diff --git a/testbench/tb_cpu_simple.sv b/testbench/tb_cpu_simple.sv index d994bc1..88e0bdb 100755 --- a/testbench/tb_cpu_simple.sv +++ b/testbench/tb_cpu_simple.sv @@ -5,10 +5,9 @@ module tb_cpu_simple(); reg clk, rst_n; wire [31:0] memory_address, memory_write, memory_out; + wire [3:0] memory_write_byte_enable; wire memory_we; - memory_mask_t memory_mask; - wire [31:0] pc; reg [31:0] instruction; @@ -22,14 +21,14 @@ module tb_cpu_simple(); .memory_address(memory_address), .memory_out(memory_out), .memory_write(memory_write), - .memory_mask(memory_mask), + .memory_byte_enable(memory_write_byte_enable), .memory_we(memory_we) ); ram memory_inst( .clk(clk), .a(memory_address), - .mask(memory_mask), + .write_byte_enable(memory_write_byte_enable), .we(memory_we), .wd(memory_write), .rd(memory_out) diff --git a/testbench/tb_cpu_tests.sv b/testbench/tb_cpu_tests.sv index 6d1464a..4a5c4da 100755 --- a/testbench/tb_cpu_tests.sv +++ b/testbench/tb_cpu_tests.sv @@ -4,10 +4,9 @@ module tb_cpu_tests(); reg clk, rst_n; wire [31:0] memory_address, memory_write, memory_out; + wire [3:0] memory_write_byte_enable; wire memory_we; - memory_mask_t memory_mask; - wire [31:0] pc; reg [31:0] instruction; @@ -21,14 +20,14 @@ module tb_cpu_tests(); .memory_address(memory_address), .memory_out(memory_out), .memory_write(memory_write), - .memory_mask(memory_mask), + .memory_byte_enable(memory_write_byte_enable), .memory_we(memory_we) ); ram memory_inst( .clk(clk), .a(memory_address), - .mask(memory_mask), + .write_byte_enable(memory_write_byte_enable), .we(memory_we), .wd(memory_write), .rd(memory_out) -- 2.48.1