~ruther/verilog-riscv-semestral-project

a400aceb574400fad6b269927793a5c13aab647c — Rutherther 1 year, 5 months ago e7b5d98
feat: make RAM word aligned, add byte_enable

Support sb, sh, lb, lh using byte enable
instead of non-word aligned reads and writes.
M programs/start.S => programs/start.S +2 -1
@@ 2,7 2,8 @@

.text
_start:
    addi sp, x0, 127
    addi sp, x0, 124
    call main
_loop:
    ebreak
    j _loop

M src/cpu.sv => src/cpu.sv +19 -3
@@ 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

M src/ram.sv => src/ram.sv +16 -12
@@ 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

M testbench/tb_cpu_add.sv => testbench/tb_cpu_add.sv +3 -4
@@ 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)

M testbench/tb_cpu_branches.sv => testbench/tb_cpu_branches.sv +3 -4
@@ 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)

M testbench/tb_cpu_gcd.sv => testbench/tb_cpu_gcd.sv +3 -4
@@ 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)

M testbench/tb_cpu_simple.sv => testbench/tb_cpu_simple.sv +3 -4
@@ 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)

M testbench/tb_cpu_tests.sv => testbench/tb_cpu_tests.sv +3 -4
@@ 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)

Do not follow this link