From bb5f00d8dc6661ceb77207655c7bc61227bc098d Mon Sep 17 00:00:00 2001 From: Mario1159 Date: Thu, 23 Feb 2023 22:31:08 +0000 Subject: [PATCH] Add register file test --- cmake/utils.cmake | 3 +++ rtl/ALU.sv | 17 ++++++------ rtl/RV32IDefs.sv | 9 +++++++ test/CMakeLists.txt | 20 ++++++++++---- test/Test_ALU.sv | 33 ++++++++++++----------- test/Test_RegisterFile.sv | 55 ++++++++++++++++++++++++++++++++------- 6 files changed, 98 insertions(+), 39 deletions(-) diff --git a/cmake/utils.cmake b/cmake/utils.cmake index db7b298..674a8d3 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -34,6 +34,7 @@ function(rvscc_add_test) cmake_parse_arguments(TEST "" "NAME" + "TOP" "SOURCES" ${ARGN} ) @@ -43,12 +44,14 @@ function(rvscc_add_test) if ("${CMAKE_BUILD_TYPE}" EQUAL "Release") verilate(${TEST_TARGET_NAME} SOURCES ${TEST_SOURCES} + TOP_MODULE ${TEST_TOP} SYSTEMC VERILATOR_ARGS --timing ) else() # Debug verilate(${TEST_TARGET_NAME} SOURCES ${TEST_SOURCES} + TOP_MODULE ${TEST_TOP} TRACE SYSTEMC VERILATOR_ARGS --timing diff --git a/rtl/ALU.sv b/rtl/ALU.sv index 15e3781..0dc933b 100644 --- a/rtl/ALU.sv +++ b/rtl/ALU.sv @@ -1,36 +1,37 @@ -`timescale 1ns / 1ps +import rv32i_defs::*; + // N = Bit width module ALU #( parameter integer N = 32 ) ( input logic [N-1:0] a, input logic [N-1:0] b, - input logic [ 2:0] opcode, + input alu_opcode operation, output logic [N-1:0] result, output logic [ 3:0] status ); logic n, z, c, v; always_comb begin - case (opcode) - 'b000: begin // Addition + case (operation) + SUM: begin // Addition {c, result} = a + b; v = (result[N-1] & !a[N-1] & !b[N-1]) | (!result[N-1] & a[N-1] & b[N-1]); end - 'b001: begin // Substraction + SUB: begin // Substraction {c, result} = a - b; v = (result[N-1] & !a[N-1] & !b[N-1]) | (!result[N-1] & a[N-1] & b[N-1]); end - 'b011: begin // Or + OR: begin // Or result = a | b; c = 'b0; v = 'b0; end - 'b010: begin // And + AND: begin // And result = a & b; c = 'b0; v = 'b0; end - 'b101: begin // Set less than + SLT: begin // Set less than result = {31'd0, a < b}; c = 'b0; v = 'b0; diff --git a/rtl/RV32IDefs.sv b/rtl/RV32IDefs.sv index 28d2b1d..6f61c68 100644 --- a/rtl/RV32IDefs.sv +++ b/rtl/RV32IDefs.sv @@ -1,4 +1,13 @@ package rv32i_defs; + + typedef enum logic[2:0]{ + SUM = 'b000, + SUB = 'b001, + OR = 'b011, + AND = 'b010, + SLT = 'b101 + } alu_opcode; + typedef enum logic[6:0]{ STALL = 'b0000000, REG_OPERATION = 'b0110011, diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f66279c..0d69a7d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -35,9 +35,12 @@ function(rvscc_add_test) add_test(NAME ${TEST_TARGET_NAME} COMMAND ${TEST_TARGET_NAME}) endfunction() -rvscc_add_test(NAME alu - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_ALU.sv - ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/ALU.sv +rvscc_add_test( + NAME alu + TOP Test_ALU + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/RV32IDefs.sv + ${CMAKE_CURRENT_SOURCE_DIR}/Test_ALU.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/ALU.sv ) rvscc_add_test(NAME priority-encoder @@ -47,10 +50,17 @@ rvscc_add_test(NAME priority-encoder rvscc_add_test(NAME data-memory SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_DataMemory.sv - ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/DataMemory.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/DataMemory.sv ) rvscc_add_test(NAME imm-extend SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_ImmExtend.sv - ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/ImmExtend.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/ImmExtend.sv +) + +rvscc_add_test( + NAME register-file + TOP Test_RegisterFile + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_RegisterFile.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/RegisterFile.sv ) diff --git a/test/Test_ALU.sv b/test/Test_ALU.sv index 11c5987..b028d23 100644 --- a/test/Test_ALU.sv +++ b/test/Test_ALU.sv @@ -1,42 +1,41 @@ -`timescale 1ns / 1ps +import rv32i_defs::alu_opcode; module Test_ALU (); logic [31:0] a, b; - logic [ 2:0] opcode; + alu_opcode operation; logic [31:0] result; logic [ 3:0] status; ALU alu ( .a(a), .b(b), - .opcode(opcode), + .operation(operation), .result(result), .status(status) ); localparam RandomSumIterations = 32; + task operation_test(input logic[31:0] a_value, input logic[31:0] b_value, input alu_opcode operation, input logic[31:0] expected_result, input logic[3:0] expected_status); + a = a_value; + b = b_value; + operation = operation; + #1; + assert(result == expected_result) else $error("Incorrent result in operation: %0s %0d, %0d = %0d (expected %0d)", operation.name(), a, b, result, expected_result); + assert(status == expected_status) else $error("Incorrent flags in operation: %0s %0d, %0d = %0d (n: %0b, z: %0b, c: %0b, v: %0b) (expected %4b)", operation.name(), a, b, result, status[3], status[2], status[1], status[0], expected_status); + endtask + initial begin $dumpfile("dump.vcd"); $dumpvars; - a = 'd0; - b = 'd0; - opcode = 'd0; - #1 - assert(result == 'd0) else $error("Incorrent result in operation: %d + %d", a, b); - assert(status == 'b0100) else $error("Incorrent flags in operation: %d + %d", a, b); - - a = 'hFFFF_FFFF; - b = 'd0; - #1 - assert(result == 'hFFFF_FFFF) else $error("Incorrent result in operation: %d + %d", a, b); - assert(status == 'b1000) else $error("Incorrent flags in operation: %d + %d", a, b); + operation_test('d0, 'd0, SUM, 'd0, 'b0100); + operation_test('hFFFF_FFFF, 'd0, SUM, 'hFFFF_FFFF, 'b1000); for(int i = 0; i < RandomSumIterations; i++) begin a = $random; b = $random; - opcode = 'd0; - #1 + operation = SUM; + #1; assert(result == a + b) else $error("Failed in operation: %d + %d", a, b); end $finish; diff --git a/test/Test_RegisterFile.sv b/test/Test_RegisterFile.sv index 8c44039..dde9112 100644 --- a/test/Test_RegisterFile.sv +++ b/test/Test_RegisterFile.sv @@ -2,7 +2,7 @@ module Test_RegisterFile(); logic clk, rst; - logic[31:0] addr_1, addr_2, addr_3; + logic[4:0] addr_1, addr_2, addr_3; logic write_enable_3; logic[31:0] write_data_3; @@ -22,19 +22,56 @@ module Test_RegisterFile(); always #1 clk = ~clk; + localparam N_REG_ADDR = 5; + localparam N_DATA = 32; + logic [N_REG_ADDR-1:0][N_DATA-1:0] write_values; initial begin + $dumpfile("regfile.vcd"); + $dumpvars; + // Reset clk = 0; rst = 1; - addr_1 = 0; - addr_2 = 'd5; - addr_3 = 0; write_enable_3 = 0; - write_data_3 = 0; - #5 + #4; rst = 0; - #5 - addr_3 = 'd5; - write_data_3 = 'd14; + #1; + // Write to all registers write_enable_3 = 1; + for (int i = 0; i < 2**N_REG_ADDR; i++) begin + addr_1 = 5'($urandom_range(0, 2**5)); + addr_2 = 5'($urandom); + addr_3 = i[4:0]; + write_values[i] = $random(); + write_data_3 = write_values[i]; + #2; + end + // Read and compare the values stored in each register using addr_1 + write_enable_3 = 0; + #4; + for (int i = 0; i < 2**N_REG_ADDR; i++) begin + addr_1 = i[4:0]; + addr_2 = 5'($random()); + addr_3 = 5'($random()); + #2; + if (i == 0) begin + assert (read_data_1 == 'd0) + else $error("Read failed at register x0 using addr_1, value should stay at 0"); + end else begin + assert (read_data_1 == write_values[i]) + else $error("Read failed at register x%h using addr_1 %d, %d", addr_1, read_data_1, write_values[i]); + end + end + // Read and compare the values stored in each register using addr_2 + write_enable_3 = 0; + #4; + for (int i = 0; i < 2**N_REG_ADDR; i++) begin + addr_1 = 5'($random()); + addr_2 = i[4:0]; + addr_3 = 5'($random()); + #2; + assert (read_data_2 == write_values[i]) + else $error("Read failed at address %h using addr_2 %d", addr_2, read_data_2); + end + $finish; end endmodule