M src/control_unit.sv => src/control_unit.sv +7 -4
@@ 3,8 3,8 @@ import cpu_types::*;
module control_unit(
input [31:0] instruction,
- // TODO: mask for: memory in and out
- // don't forget zero extension, sign extension...
+ output memory_mask_t memory_mask,
+ output memory_sign_extension,
// whether to save alu to memory
output memory_we,
@@ 47,6 47,8 @@ module control_unit(
wire alu_reg_add_one, alu_reg_negate, alu_reg_signed;
wire alu_jump_add_one, alu_jump_negate;
+ wire alu_override;
+
assign jump_instruction = conditional_jump;
instruction_decoder decoder(
@@ 55,8 57,9 @@ module control_unit(
.store_memory(memory_we),
.load_memory(load_memory),
- .load_memory_size(),
- .load_memory_sign_extension(),
+
+ .memory_mask(memory_mask),
+ .memory_sign_extension(memory_sign_extension),
.load_pc(load_pc),
.store_pc(store_pc),
M src/cpu.sv => src/cpu.sv +22 -2
@@ 12,6 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 reg memory_we
);
parameter WIDTH = 32;
@@ 38,7 39,23 @@ module cpu(
wire jump_instruction, jump_negate_zero;
wire jump_taken;
- assign memory_write = reg_rd2;
+ wire memory_sign_extension;
+
+ function bit[31:0] mem_sext_maybe;
+ input [31:0] num;
+ input memory_mask_t mask;
+ input sext;
+ begin
+ case(mask)
+ MEM_BYTE: return {{(32 - 8){sext & num[7]}}, num[7:0]};
+ MEM_HALFWORD: return {{(32 - 16){sext & num[15]}}, num[15:0]};
+ MEM_WORD: return num[31:0]; // rv32i, no 64 bit regs, no sign extension needed
+ default: return 0;
+ endcase
+ end
+ endfunction
+
+ assign memory_write = mem_sext_maybe(.num(reg_rd2), .mask(memory_mask), .sext(memory_sign_extension));
assign memory_address = alu_out;
// alu source 1
@@ 76,7 93,7 @@ module cpu(
case (reg_write_src)
RD_ALU : reg_write = alu_out;
RD_PC_PLUS : reg_write = pc + 4;
- RD_MEMORY : reg_write = memory_out;
+ RD_MEMORY : reg_write = mem_sext_maybe(.num(memory_out), .mask(memory_mask), .sext(memory_sign_extension));
default : ;
endcase
end
@@ 91,6 108,9 @@ module cpu(
.alu_negate(alu_negate),
.alu_signed(alu_signed),
+ .memory_mask(memory_mask),
+ .memory_sign_extension(memory_sign_extension),
+
.memory_we(memory_we),
.jump_instruction(jump_instruction),
M src/cpu_types.sv => src/cpu_types.sv +2 -0
@@ 3,4 3,6 @@ package cpu_types;
typedef enum bit[0:0] { REG_FILE_RS1, PC } alu_1_source_t;
typedef enum bit[0:0] { REG_FILE_RS2, IMMEDIATE } alu_2_source_t;
typedef enum bit[1:0] { RD_ALU, RD_PC_PLUS, RD_MEMORY } reg_rd_source_t;
+
+ typedef enum bit[1:0] { MEM_BYTE, MEM_HALFWORD, MEM_WORD } memory_mask_t;
endpackage
M src/instruction_decoder.sv => src/instruction_decoder.sv +15 -12
@@ 1,3 1,5 @@
+import cpu_types::* ;
+
module instruction_decoder(
input [31:0] instruction,
@@ 7,8 9,8 @@ module instruction_decoder(
// whether to load memory to rd
output reg load_memory,
- output reg [5:0] load_memory_size,
- output reg load_memory_sign_extension,
+ output memory_mask_t memory_mask,
+ output reg memory_sign_extension,
// put alu_jump to alu if conditional_jump
//
@@ 64,27 66,27 @@ module instruction_decoder(
// load memory mask/size
always_comb begin
- load_memory_size = 32;
- load_memory_sign_extension = 1'b0;
+ memory_mask = MEM_WORD;
+ memory_sign_extension = 1'b0;
case (funct3)
3'b000: begin
- load_memory_size = 8; // sign extends
- load_memory_sign_extension = 1'b1;
+ memory_mask = MEM_BYTE; // sign extends
+ memory_sign_extension = 1'b1;
end
3'b001: begin
- load_memory_size = 16; // sign extends
- load_memory_sign_extension = 1'b1;
+ memory_mask = MEM_HALFWORD; // sign extends
+ memory_sign_extension = 1'b1;
end
3'b010: begin
- load_memory_size = 32; // sign extends
- load_memory_sign_extension = 1'b1;
+ memory_mask = MEM_WORD; // sign extends
+ memory_sign_extension = 1'b1;
end
3'b100: begin
- load_memory_size = 8; // zero extends
+ memory_mask = MEM_BYTE; // zero extends
end
3'b101: begin
- load_memory_size = 16; // zero extends
+ memory_mask = MEM_HALFWORD; // zero extends
end
default : ;
endcase
@@ 93,6 95,7 @@ module instruction_decoder(
// immediate load
always_comb begin
case (instruction_type)
+ // beware, slli, srai and srli, are I, but have funct7
I : immediate = {{20{instruction[31]}}, instruction[31:20]};
S : immediate = {{20{instruction[31]}}, instruction[31:25], instruction[11:7]};
SB : immediate = {{20{instruction[31]}}, instruction[7], instruction[30:25], instruction[11:8], 1'b0};
M src/ram.sv => src/ram.sv +13 -3
@@ 1,13 1,23 @@
+import cpu_types::*;
+
module ram (
input clk, we,
input [31:0] a, wd,
+ input memory_mask_t mask,
output [31:0] rd);
- reg [31:0] RAM[0:127];
+ reg [4095:0] RAM;
- assign rd = RAM[a[8:2]]; // word aligned
+ assign rd = RAM[a[11:0] +:32]; // word aligned
always @(posedge clk)
- if(we) RAM[a[8:2]] <= wd;
+ if(we) begin
+ case(mask)
+ MEM_BYTE: RAM[a[11:0] +:8] <= wd[7:0];
+ MEM_HALFWORD: RAM[a[11:0] +:16] <= wd[15:0];
+ MEM_WORD: RAM[{a[11:0]} +:32] <= wd[31:0];
+ default: ;
+ endcase
+ end
endmodule
M testbench/tb_control_unit.sv => testbench/tb_control_unit.sv +9 -1
@@ 27,6 27,9 @@ module tb_control_unit();
wire [4:0] reg_rd;
wire reg_we;
+ memory_mask_t memory_mask;
+ wire memory_sign_extension;
+
control_unit uut(
.instruction(instruction),
.memory_we(memory_we),
@@ 44,7 47,9 @@ module tb_control_unit();
.reg_rs2(reg_rs2),
.reg_rd_src(reg_rd_src),
.reg_rd(reg_rd),
- .reg_we(reg_we)
+ .reg_we(reg_we),
+ .memory_mask(memory_mask),
+ .memory_sign_extension(memory_sign_extension)
);
initial begin
@@ 103,6 108,9 @@ module tb_control_unit();
#5 // lui
instruction = {20'hA000A, 5'b00001, 7'b0110111};
+ #5
+ instruction = 32'b1000000000101111101011110010011;
+
#5 $finish;
end
M testbench/tb_cpu_simple.sv => testbench/tb_cpu_simple.sv +7 -0
@@ 1,9 1,14 @@
+
+import cpu_types::*;
+
module tb_cpu_simple();
reg clk, rst_n;
wire [31:0] memory_address, memory_write, memory_out;
wire memory_we;
+ memory_mask_t memory_mask;
+
wire [31:0] pc;
reg [31:0] instruction;
@@ 17,12 22,14 @@ module tb_cpu_simple();
.memory_address(memory_address),
.memory_out(memory_out),
.memory_write(memory_write),
+ .memory_mask(memory_mask),
.memory_we(memory_we)
);
ram memory_inst(
.clk(clk),
.a(memory_address),
+ .mask(memory_mask),
.we(memory_we),
.wd(memory_write),
.rd(memory_out)