Compare commits
3 Commits
e826f9ff88
...
d6f0499217
Author | SHA1 | Date | |
---|---|---|---|
d6f0499217 | |||
74940e6dda | |||
98f15a4961 |
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
fw/build
|
3
CMakeLists.txt
Normal file
3
CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
project(rvscc)
|
||||||
|
|
||||||
|
include_directories(test)
|
16
rtl/ALU.sv
16
rtl/ALU.sv
@ -10,21 +10,15 @@ module ALU #(
|
|||||||
output logic [ 3:0] status
|
output logic [ 3:0] status
|
||||||
);
|
);
|
||||||
logic n, z, c, v;
|
logic n, z, c, v;
|
||||||
logic opsign_comp, v_value;
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
// Check if the signs of the operands are equal considering substraction sign simplification over the B operand
|
|
||||||
opsign_comp = (a[N-1] == (b[N-1] ^ opcode[0]));
|
|
||||||
// There is an overflow if the signs are equal and the result differ from the operation sign
|
|
||||||
// The overflow flag only gets assign when the operation is either a sum or a substraction
|
|
||||||
v_value = opsign_comp && (result != a[N-1]);
|
|
||||||
case (opcode)
|
case (opcode)
|
||||||
'b000: begin // Addition
|
'b000: begin // Addition
|
||||||
{c, result} = a + b;
|
{c, result} = a + b;
|
||||||
v = v_value;
|
v = (result[N-1] & !a[N-1] & !b[N-1]) | (!result[N-1] & a[N-1] & b[N-1]);
|
||||||
end
|
end
|
||||||
'b001: begin // Substraction
|
'b001: begin // Substraction
|
||||||
{c, result} = a - b;
|
{c, result} = a - b;
|
||||||
v = v_value;
|
v = (result[N-1] & !a[N-1] & !b[N-1]) | (!result[N-1] & a[N-1] & b[N-1]);
|
||||||
end
|
end
|
||||||
'b011: begin // Or
|
'b011: begin // Or
|
||||||
result = a | b;
|
result = a | b;
|
||||||
@ -37,14 +31,14 @@ module ALU #(
|
|||||||
v = 'b0;
|
v = 'b0;
|
||||||
end
|
end
|
||||||
'b101: begin // Set less than
|
'b101: begin // Set less than
|
||||||
result = a < b;
|
result = {31'd0, a < b};
|
||||||
c = 'b0;
|
c = 'b0;
|
||||||
v = 'b0;
|
v = 'b0;
|
||||||
end
|
end
|
||||||
default: begin
|
default: begin
|
||||||
result = 'dx;
|
result = 'dx;
|
||||||
c = 'dx;
|
c = 1'bx;
|
||||||
v = 'dx;
|
v = 1'bx;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
n = result[N-1];
|
n = result[N-1];
|
||||||
|
@ -9,9 +9,9 @@ module PriorityEncoder #(
|
|||||||
output logic valid
|
output logic valid
|
||||||
);
|
);
|
||||||
always_comb begin
|
always_comb begin
|
||||||
data_out = 'dx;
|
data_out = 3'dx;
|
||||||
for (int i = 0; i < 2 ** N; i++) begin
|
for (int i = 0; i < 2 ** N; i++) begin
|
||||||
if (data_in[i]) data_out = i;
|
if (data_in[i]) data_out = i[N-1:0];
|
||||||
end
|
end
|
||||||
if (data_in == 0) valid = 0;
|
if (data_in == 0) valid = 0;
|
||||||
else valid = 1;
|
else valid = 1;
|
||||||
|
50
test/CMakeLists.txt
Normal file
50
test/CMakeLists.txt
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(rvscc-tests CXX)
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
find_package(verilator HINTS $ENV{VERILATOR_ROOT})
|
||||||
|
if (NOT verilator_FOUND)
|
||||||
|
message(FATAL_ERROR "Verilator was not found. Either install it, or set the VERILATOR_ROOT environment variable")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
find_package(SystemCLanguage QUIET)
|
||||||
|
|
||||||
|
function(custom_add_test)
|
||||||
|
cmake_parse_arguments(TEST
|
||||||
|
""
|
||||||
|
"NAME"
|
||||||
|
"SOURCES"
|
||||||
|
${ARGN}
|
||||||
|
)
|
||||||
|
set(TEST_TARGET_NAME test-${TEST_NAME})
|
||||||
|
add_executable(${TEST_TARGET_NAME} sim_individual_test.cpp)
|
||||||
|
verilate(${TEST_TARGET_NAME}
|
||||||
|
SOURCES ${TEST_SOURCES}
|
||||||
|
SYSTEMC
|
||||||
|
VERILATOR_ARGS --timing
|
||||||
|
)
|
||||||
|
set_property(TARGET ${TEST_TARGET_NAME} PROPERTY CXX_STANDARD ${SystemC_CXX_STANDARD})
|
||||||
|
verilator_link_systemc(${TEST_TARGET_NAME})
|
||||||
|
list(GET TEST_SOURCES 0 TEST_TOP_MODULE)
|
||||||
|
get_filename_component(TEST_TOP_MODULE_NAME ${TEST_TOP_MODULE} NAME_WE)
|
||||||
|
target_compile_definitions(${TEST_TARGET_NAME} PRIVATE
|
||||||
|
TEST_HEADER="V${TEST_TOP_MODULE_NAME}.h"
|
||||||
|
TEST_CLASS=V${TEST_TOP_MODULE_NAME}
|
||||||
|
)
|
||||||
|
add_test(NAME ${TEST_TARGET_NAME} COMMAND ${TEST_TARGET_NAME})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
custom_add_test(NAME alu
|
||||||
|
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_ALU.sv
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/ALU.sv
|
||||||
|
)
|
||||||
|
|
||||||
|
custom_add_test(NAME priority-encoder
|
||||||
|
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_PriorityEncoder.sv
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/PriorityEncoder.sv
|
||||||
|
)
|
@ -1,15 +1,25 @@
|
|||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
module Test_ALU();
|
module Test_ALU ();
|
||||||
logic[31:0] a, b;
|
logic [31:0] a, b;
|
||||||
logic[2:0] opcode;
|
logic [ 2:0] opcode;
|
||||||
logic[31:0] result;
|
logic [31:0] result;
|
||||||
logic[3:0] status;
|
logic [ 3:0] status;
|
||||||
ALU alu(a, b, opcode, result, status);
|
ALU alu (
|
||||||
|
.a(a),
|
||||||
initial begin
|
.b(b),
|
||||||
a = 'd3;
|
.opcode(opcode),
|
||||||
b = 'd11;
|
.result(result),
|
||||||
opcode = 'd0;
|
.status(status)
|
||||||
end
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
a = 'd3;
|
||||||
|
b = 'd11;
|
||||||
|
opcode = 'd0;
|
||||||
|
assert(result != 'd14) $display("3 + 11 != 14");
|
||||||
|
assert(status != 'b0000) $display("status(3 + 11) != 0000");
|
||||||
|
$display("Test successful");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -3,11 +3,16 @@
|
|||||||
module Test_PriorityEncoder();
|
module Test_PriorityEncoder();
|
||||||
logic[7:0] data_in;
|
logic[7:0] data_in;
|
||||||
logic[2:0] data_out;
|
logic[2:0] data_out;
|
||||||
PriorityEncoder#(.N(3)) encoder(data_in, data_out);
|
logic valid;
|
||||||
|
PriorityEncoder#(.N(3)) encoder(
|
||||||
|
.data_in(data_in),
|
||||||
|
.data_out(data_out),
|
||||||
|
.valid(valid)
|
||||||
|
);
|
||||||
initial begin
|
initial begin
|
||||||
data_in = 'b00000001;
|
data_in = 'b00000001;
|
||||||
for (int i = 0; i < 8; i++) begin
|
for (int i = 0; i < 8; i++) begin
|
||||||
assert (data_out == i + 1) else $error("[One-hot] Failed at " + i);
|
assert (data_out == i[2:0] + 1 || valid == 1) else $error("[One-hot] Failed at %d", i);
|
||||||
#1
|
#1
|
||||||
data_in = data_in << 'd1;
|
data_in = data_in << 'd1;
|
||||||
end
|
end
|
||||||
@ -17,5 +22,6 @@ module Test_PriorityEncoder();
|
|||||||
#1
|
#1
|
||||||
data_in = 'b10101010;
|
data_in = 'b10101010;
|
||||||
assert (data_out == 'd7) else $error("[Manual entry] Failed at " + 7);
|
assert (data_out == 'd7) else $error("[Manual entry] Failed at " + 7);
|
||||||
|
$finish;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
24
test/sim_individual_test.cpp
Normal file
24
test/sim_individual_test.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#if defined(TEST_HEADER) && defined(TEST_CLASS)
|
||||||
|
|
||||||
|
#include <systemc.h>
|
||||||
|
#include <verilated.h>
|
||||||
|
|
||||||
|
#include TEST_HEADER
|
||||||
|
|
||||||
|
int sc_main(int argc, char* argv[]) {
|
||||||
|
TEST_CLASS* top = new TEST_CLASS{"top"};
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
sc_start(1, SC_NS);
|
||||||
|
while (!Verilated::gotFinish())
|
||||||
|
sc_start(1, SC_NS);
|
||||||
|
top->final();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int sc_main(int argc, char* argv[]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user