diff options
author | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2024-05-05 10:27:21 +0200 |
---|---|---|
committer | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2024-05-05 10:27:21 +0200 |
commit | 8d5d730269cc94fa8d5caed0e1996e3d94be25d1 (patch) | |
tree | 73154eacc2c7483a24aecd05a984638ff322d5d6 | |
parent | f6a55d5faba42120aa900e2514d9ff5d80dfca8b (diff) | |
download | riscv_cpu-8d5d730269cc94fa8d5caed0e1996e3d94be25d1.tar.gz riscv_cpu-8d5d730269cc94fa8d5caed0e1996e3d94be25d1.zip |
added register file
-rw-r--r-- | gentestvec/gentestvec_register_file.c | 48 | ||||
-rw-r--r-- | include/log2.vh | 12 | ||||
-rw-r--r-- | sim/testbench_alu.v | 10 | ||||
-rw-r--r-- | src/alu.v | 42 | ||||
-rw-r--r-- | src/arithmetic_unit.v | 22 | ||||
-rw-r--r-- | src/logic_unit.v | 20 | ||||
-rw-r--r-- | src/register_file.v | 30 | ||||
-rw-r--r-- | src/shift_unit.v | 16 |
8 files changed, 145 insertions, 55 deletions
diff --git a/gentestvec/gentestvec_register_file.c b/gentestvec/gentestvec_register_file.c new file mode 100644 index 0000000..2533772 --- /dev/null +++ b/gentestvec/gentestvec_register_file.c @@ -0,0 +1,48 @@ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +uint32_t registers[32]; + +uint32_t read_reg(uint32_t addr) { return addr == 0 ? 0 : registers[addr]; } + +void write_reg(uint32_t addr, uint32_t data, bool we) { + if (addr != 0 && we) + registers[addr] = data; +} + +void test(uint32_t addr_rs0, uint32_t addr_rs1, uint32_t addr_rd2, + uint32_t data_rd2, bool we) { + write_reg(addr_rd2, data_rd2, we); + uint32_t data_rs0 = read_reg(addr_rs0); + uint32_t data_rs1 = read_reg(addr_rs1); + printf("%08X_%08X__%08X_%08X__%08X_%08X_%01X\n", addr_rs0, data_rs0, addr_rs1, + data_rs1, addr_rd2, data_rd2, we); +} + +void tests(int num) { + for (int i = 0; i < num; ++i) { + uint32_t addr_rs0 = ((uint32_t)((rand() << 16) | rand())) % 32; + uint32_t addr_rs1 = ((uint32_t)((rand() << 16) | rand())) % 32; + uint32_t addr_rd2 = ((uint32_t)((rand() << 16) | rand())) % 32; + uint32_t data_rd2 = ((uint32_t)((rand() << 16) | rand())); + bool we = ((uint32_t)rand()) % 2; + test(addr_rs0, addr_rs1, addr_rd2, data_rd2, we); + } +} + +int main(int argc, const char *argv[]) { + srand(time(NULL)); + for (int i = 0; i < 32; ++i) + registers[0] = 0; + + for (int i = 0; i < 32; ++i) + test(i, i, 0, 0, false); + + for (int i = 0; i < 32; ++i) + test(i, i, i, 0xffffffff, true); + + tests(1000); + return 0; +} diff --git a/include/log2.vh b/include/log2.vh new file mode 100644 index 0000000..097061d --- /dev/null +++ b/include/log2.vh @@ -0,0 +1,12 @@ +function integer log2; + input integer value; + integer temp; + begin + log2 = 0; + temp = value - 1; + while (temp > 0) begin + log2 = log2 + 1; + temp = temp >> 1; + end + end +endfunction diff --git a/sim/testbench_alu.v b/sim/testbench_alu.v index 068efc3..45cce1b 100644 --- a/sim/testbench_alu.v +++ b/sim/testbench_alu.v @@ -76,11 +76,11 @@ module testbench_alu(); alu #(.N(32)) alu ( - .alu_src0(a), - .alu_src1(b), - .alu_op(op), - .alu_result(result), - .alu_zero(zero) + .src0(a), + .src1(b), + .op(op), + .result(result), + .zero(zero) ); endmodule @@ -1,43 +1,43 @@ module alu #( parameter N = 32 )( - input [N-1:0] alu_src0, alu_src1, - input [3:0] alu_op, // alu_op[3:2] 00: ARITHMETIC, 01: LOGIC, 10: SHIFT - output reg [N-1:0] alu_result, - output alu_zero + input [N-1:0] src0, src1, + input [3:0] op, // alu_op[3:2] 00: ARITHMETIC, 01: LOGIC, 10: SHIFT + output reg [N-1:0] result, + output zero ); wire [N-1:0] arithmetic_result, logic_result, shift_result; arithmetic_unit #(.N(N)) au ( - .au_src0(alu_src0), - .au_src1(alu_src1), - .au_op(alu_op[1:0]), - .au_result(arithmetic_result) + .src0(src0), + .src1(src1), + .op(op[1:0]), + .result(arithmetic_result) ); logic_unit #(.N(N)) lu ( - .lu_src0(alu_src0), - .lu_src1(alu_src1), - .lu_op(alu_op[1:0]), - .lu_result(logic_result) + .src0(src0), + .src1(src1), + .op(op[1:0]), + .result(logic_result) ); shift_unit #(.N(N)) su ( - .su_src0(alu_src0), - .su_shamt(alu_src1), - .su_op(alu_op[1:0]), - .su_result(shift_result) + .src0(src0), + .shamt(src1), + .op(op[1:0]), + .result(shift_result) ); always @ (*) begin - case (alu_op[3:2]) - 2'b00: alu_result <= arithmetic_result; - 2'b01: alu_result <= logic_result; - 2'b10: alu_result <= shift_result; + case (op[3:2]) + 2'b00: result <= arithmetic_result; + 2'b01: result <= logic_result; + 2'b10: result <= shift_result; endcase end -assign alu_zero = ~|alu_result; +assign zero = ~|result; endmodule diff --git a/src/arithmetic_unit.v b/src/arithmetic_unit.v index 71255c2..59f5cae 100644 --- a/src/arithmetic_unit.v +++ b/src/arithmetic_unit.v @@ -1,23 +1,23 @@ module arithmetic_unit #( parameter N = 32 )( - input [N-1:0] au_src0, au_src1, - input [1:0] au_op, // 00: ADD, 01: SUB, 11: SLT - output [N-1:0] au_result + input [N-1:0] src0, src1, + input [1:0] op, // 00: ADD, 01: SUB, 11: SLT + output [N-1:0] result ); -wire [N-1:0] au_src1_inv, au_sum; -wire au_cin, au_src0_lt_src1, au_overflow; +wire [N-1:0] src1_inv, sum; +wire cin, src0_lt_src1, overflow; -assign au_src1_inv = au_op[0] ? ~au_src1 : au_src1; -assign au_cin = au_op[0]; +assign src1_inv = op[0] ? ~src1 : src1; +assign cin = op[0]; -assign au_sum = au_src0 + au_src1_inv + au_cin; +assign sum = src0 + src1_inv + cin; -assign au_overflow = ~(au_src0[N-1] ^ au_src1[N-1] ^ au_op[0]) & (au_src0[N-1] ^ au_sum[N-1]); +assign overflow = ~(src0[N-1] ^ src1[N-1] ^ op[0]) & (src0[N-1] ^ sum[N-1]); -assign au_src0_lt_src1 = au_overflow ^ au_sum[N-1]; +assign src0_lt_src1 = overflow ^ sum[N-1]; -assign au_result = au_op[1] ? {{(N-1){1'b0}}, au_src0_lt_src1} : au_sum; +assign result = op[1] ? {{(N-1){1'b0}}, src0_lt_src1} : sum; endmodule diff --git a/src/logic_unit.v b/src/logic_unit.v index 85c9137..0bbd642 100644 --- a/src/logic_unit.v +++ b/src/logic_unit.v @@ -1,17 +1,17 @@ module logic_unit #( parameter N = 32 )( - input [N-1:0] lu_src0, lu_src1, - input [1:0] lu_op, // 00: AND, 01: OR, 10: XOR - output reg [N-1:0] lu_result + input [N-1:0] src0, src1, + input [1:0] op, // 00: AND, 01: OR, 10: XOR + output reg [N-1:0] result ); - always @ (*) begin - case (lu_op) - 2'b00: lu_result <= lu_src0 & lu_src1; - 2'b01: lu_result <= lu_src0 | lu_src1; - 2'b10: lu_result <= lu_src0 ^ lu_src1; - endcase - end +always @ (*) begin + case (op) + 2'b00: result <= src0 & src1; + 2'b01: result <= src0 | src1; + 2'b10: result <= src0 ^ src1; + endcase +end endmodule diff --git a/src/register_file.v b/src/register_file.v new file mode 100644 index 0000000..81bce34 --- /dev/null +++ b/src/register_file.v @@ -0,0 +1,30 @@ +module register_file #( + parameter N = 32, + parameter XLEN = 32 +)( + input clk, rst, we, + input [log2(N)-1:0] addr_rs0, addr_rs1, addr_rd2, + input [N-1:0] data_rd2, + output [N-1:0] data_rs0, data_rs1 +); + +`include "include/log2.vh" + +reg [N-1:0] registers[XLEN-1:1]; + +assign data_rs0 = (addr_rs0 == 0) ? 0 : registers[addr_rs0]; +assign data_rs1 = (addr_rs1 == 0) ? 0 : registers[addr_rs1]; + + + +integer i; +always @(posedge clk) begin + if (rst) begin + for (i = 1; i < XLEN; i = i + 1) + registers[i] <= 0; + end else if (we && (addr_rd2 != 0)) begin + registers[addr_rd2] <= data_rd2; + end +end + +endmodule diff --git a/src/shift_unit.v b/src/shift_unit.v index 372fec0..d0aa9d3 100644 --- a/src/shift_unit.v +++ b/src/shift_unit.v @@ -1,17 +1,17 @@ module shift_unit #( parameter N = 32 )( - input signed [N-1:0] su_src0, - input [N-1:0] su_shamt, - input [1:0] su_op, // 00: SLL, 01: SRL, 11: SRA - output reg [N-1:0] su_result + input signed [N-1:0] src0, + input [N-1:0] shamt, + input [1:0] op, // 00: SLL, 01: SRL, 11: SRA + output reg [N-1:0] result ); always @ (*) begin - case (su_op) - 2'b00: su_result <= su_src0 << su_shamt % N; - 2'b01: su_result <= su_src0 >> su_shamt % N; - 2'b11: su_result <= su_src0 >>> su_shamt % N; + case (op) + 2'b00: result <= src0 << shamt % N; + 2'b01: result <= src0 >> shamt % N; + 2'b11: result <= src0 >>> shamt % N; endcase end |