Add register file test
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
This commit is contained in:
parent
4a05b75da0
commit
bb5f00d8dc
@ -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
|
||||
|
17
rtl/ALU.sv
17
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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user