Add register file test
Some checks reported errors
continuous-integration/drone/push Build was killed

This commit is contained in:
Mario Romero 2023-02-23 22:31:08 +00:00
parent 4a05b75da0
commit bb5f00d8dc
6 changed files with 98 additions and 39 deletions

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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
)

View File

@ -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;

View File

@ -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