From bd2f58d5f6e6f19f93fe44195851dbff3e9e25ea Mon Sep 17 00:00:00 2001 From: Mario Romero Date: Sun, 26 Feb 2023 20:26:11 -0300 Subject: [PATCH] Change name scheme and add tests --- cmake/utils.cmake | 38 ++---- fw/test/CMakeLists.txt | 16 ++- fw/test/core.s | 28 ++++ fw/test/{imm/main.s => imm.s} | 0 fw/test/{itype/main.s => itype.s} | 0 fw/test/{rtype/main.s => rtype.s} | 0 rtl/ALU.sv | 49 ------- rtl/ALUDecoder.sv | 65 ---------- rtl/DataMemory.sv | 28 ---- rtl/InstructionMemory.sv | 19 --- rtl/MainDecoder.sv | 93 -------------- rtl/RV32IDefs.sv | 22 ---- rtl/SingleCycleCPU.sv | 115 ----------------- rtl/alu.sv | 48 +++++++ rtl/alu_decoder.sv | 65 ++++++++++ ...CacheController.sv => cache_controller.sv} | 0 rtl/{CacheMemory.sv => cache_memory.sv} | 2 +- rtl/{ControlUnit.sv => control_unit.sv} | 8 +- rtl/data_memory.sv | 22 ++++ rtl/data_memory_if.sv | 18 +++ rtl/{HazardUnit.sv => hazard_unit.sv} | 0 rtl/{ImmExtend.sv => imm_extend.sv} | 2 +- rtl/instr_memory.sv | 18 +++ rtl/{JumpControl.sv => jump_control.sv} | 10 +- rtl/main_decoder.sv | 93 ++++++++++++++ ...ntrolUnit.sv => pipelined_control_unit.sv} | 0 rtl/{PipelinedCPU.sv => pipelined_cpu.sv} | 0 ...PriorityEncoder.sv => priority_encoder.sv} | 2 +- rtl/{RegisterFile.sv => register_file.sv} | 27 ++-- rtl/{RotateCRU.sv => rotate_cru.sv} | 0 rtl/rv32i_defs.sv | 31 +++++ rtl/single_cycle_datapath.sv | 121 ++++++++++++++++++ ...TwoWayLRUCache.sv => two_way_lru_cache.sv} | 0 rtl/{TwoWayLRUCRU.sv => two_way_lru_cru.sv} | 0 test/CMakeLists.txt | 94 ++++++++------ test/Test_ALU.sv | 43 ------- test/Test_CPU.sv | 12 -- test/Test_CacheMemory.sv | 26 ---- test/Test_DataMemory.sv | 57 --------- test/Test_InstrMemory.sv | 21 --- test/Test_PriorityEncoder.sv | 24 ---- test/Test_RegisterFile.sv | 77 ----------- test/test_alu.sv | 70 ++++++++++ test/test_cache_memory.sv | 29 +++++ test/test_data_memory.sv | 65 ++++++++++ .../{Test_ImmExtend.sv => test_imm_extend.sv} | 4 +- test/test_instr_memory.sv | 69 ++++++++++ test/test_priority_encoder.sv | 34 +++++ test/test_register_file.sv | 95 ++++++++++++++ test/test_single_cycle_core.sv | 30 +++++ ...yLRUCache.sv => test_two_way_lru_cache.sv} | 0 51 files changed, 934 insertions(+), 756 deletions(-) create mode 100644 fw/test/core.s rename fw/test/{imm/main.s => imm.s} (100%) rename fw/test/{itype/main.s => itype.s} (100%) rename fw/test/{rtype/main.s => rtype.s} (100%) delete mode 100644 rtl/ALU.sv delete mode 100644 rtl/ALUDecoder.sv delete mode 100644 rtl/DataMemory.sv delete mode 100644 rtl/InstructionMemory.sv delete mode 100644 rtl/MainDecoder.sv delete mode 100644 rtl/RV32IDefs.sv delete mode 100644 rtl/SingleCycleCPU.sv create mode 100644 rtl/alu.sv create mode 100644 rtl/alu_decoder.sv rename rtl/{CacheController.sv => cache_controller.sv} (100%) rename rtl/{CacheMemory.sv => cache_memory.sv} (95%) rename rtl/{ControlUnit.sv => control_unit.sv} (84%) create mode 100644 rtl/data_memory.sv create mode 100644 rtl/data_memory_if.sv rename rtl/{HazardUnit.sv => hazard_unit.sv} (100%) rename rtl/{ImmExtend.sv => imm_extend.sv} (93%) create mode 100644 rtl/instr_memory.sv rename rtl/{JumpControl.sv => jump_control.sv} (70%) create mode 100644 rtl/main_decoder.sv rename rtl/{PipelinedControlUnit.sv => pipelined_control_unit.sv} (100%) rename rtl/{PipelinedCPU.sv => pipelined_cpu.sv} (100%) rename rtl/{PriorityEncoder.sv => priority_encoder.sv} (93%) rename rtl/{RegisterFile.sv => register_file.sv} (50%) rename rtl/{RotateCRU.sv => rotate_cru.sv} (100%) create mode 100644 rtl/rv32i_defs.sv create mode 100644 rtl/single_cycle_datapath.sv rename rtl/{TwoWayLRUCache.sv => two_way_lru_cache.sv} (100%) rename rtl/{TwoWayLRUCRU.sv => two_way_lru_cru.sv} (100%) delete mode 100644 test/Test_ALU.sv delete mode 100644 test/Test_CPU.sv delete mode 100644 test/Test_CacheMemory.sv delete mode 100644 test/Test_DataMemory.sv delete mode 100644 test/Test_InstrMemory.sv delete mode 100644 test/Test_PriorityEncoder.sv delete mode 100644 test/Test_RegisterFile.sv create mode 100644 test/test_alu.sv create mode 100644 test/test_cache_memory.sv create mode 100644 test/test_data_memory.sv rename test/{Test_ImmExtend.sv => test_imm_extend.sv} (92%) create mode 100644 test/test_instr_memory.sv create mode 100644 test/test_priority_encoder.sv create mode 100644 test/test_register_file.sv create mode 100644 test/test_single_cycle_core.sv rename test/{Test_TwoWayLRUCache.sv => test_two_way_lru_cache.sv} (100%) diff --git a/cmake/utils.cmake b/cmake/utils.cmake index 674a8d3..24a7a7e 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -33,37 +33,23 @@ endfunction() function(rvscc_add_test) cmake_parse_arguments(TEST "" - "NAME" - "TOP" + "NAME;TOP" "SOURCES" ${ARGN} ) - message("Adding test ${TEST_NAME}") set(TEST_TARGET_NAME test-${TEST_NAME}) - add_executable(${TEST_TARGET_NAME} sim_individual_test.cpp) - 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 - ) - endif() - 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) + add_executable(${TEST_TARGET_NAME} sim_main.cpp) + message(${TEST_TOP}) + verilate(${TEST_TARGET_NAME} + SOURCES ${TEST_SOURCES} + PREFIX verilator_${TEST_TOP} + TOP_MODULE ${TEST_TOP} + TRACE + VERILATOR_ARGS --timing --assert + ) target_compile_definitions(${TEST_TARGET_NAME} PRIVATE - TEST_HEADER="V${TEST_TOP_MODULE_NAME}.h" - TEST_CLASS=V${TEST_TOP_MODULE_NAME} + TEST_HEADER="verilator_${TEST_TOP}.h" + TEST_CLASS=verilator_${TEST_TOP} ) add_test(NAME ${TEST_TARGET_NAME} COMMAND ${TEST_TARGET_NAME}) endfunction() diff --git a/fw/test/CMakeLists.txt b/fw/test/CMakeLists.txt index 5336a81..c158a88 100644 --- a/fw/test/CMakeLists.txt +++ b/fw/test/CMakeLists.txt @@ -5,16 +5,18 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/utils.cmake) option(DISSASEMBLY "Enable dissasembly" OFF) -list(APPEND TEST_SUBDIRS - itype - rtype - imm +list(APPEND TEST_FILES + itype.s + rtype.s + imm.s + core.s ) -foreach(TEST_SUBDIR IN LISTS TEST_SUBDIRS) - set(TEST_TARGET "test-${TEST_SUBDIR}") +foreach(TEST_FILE IN LISTS TEST_FILES) + get_filename_component(TEST_FILENAME ${TEST_FILE} NAME_WE) + set(TEST_TARGET "test-${TEST_FILENAME}") - add_executable(${TEST_TARGET} ${TEST_SUBDIR}/main.s) + add_executable(${TEST_TARGET} ${TEST_FILENAME}.s) target_compile_options(${TEST_TARGET} PRIVATE -march=rv32id diff --git a/fw/test/core.s b/fw/test/core.s new file mode 100644 index 0000000..1aae359 --- /dev/null +++ b/fw/test/core.s @@ -0,0 +1,28 @@ +.section .text +.global main + +main: + addi x2, x0, 5 # x2 = 5 + addi x3, x0, 12 # x3 = 12 + addi x7, x3, -9 # x7 = (12 - 9) = 3 + or x4, x7, x2 # x4 = (3 OR 5) = 7 + and x5, x3, x4 # x5 = (12 AND 7) = 4 + add x5, x5, x4 # x5 = 4 + 7 = 11 + beq x5, x7, end # shouldn't be taken + slt x4, x3, x4 # x4 = (12 < 7) = 0 + beq x4, x0, around # should be taken + addi x5, x0, 0 # shouldn't execute +around: + slt x4, x7, x2 # x4 = (3 < 5) = 1 + add x7, x4, x5 # x7 = (1 + 11) = 12 + sub x7, x7, x2 # x7 = (12 - 5) = 7 + sw x7, 84(x3) # [96] = 7 + lw x2, 96(x0) # x2 = [96] = 7 + add x9, x2, x5 # x9 = (7 + 11) = 18 + jal x3, end # jump to end, x3 = 0x44 + addi x2, x0, 1 # shouldn't execute +end: + add x2, x2, x9 # x2 = (7 + 18) = 25 + sw x2, 0x20(x3) # [100] = 25 +done: + beq x2, x2, done # infinite loop diff --git a/fw/test/imm/main.s b/fw/test/imm.s similarity index 100% rename from fw/test/imm/main.s rename to fw/test/imm.s diff --git a/fw/test/itype/main.s b/fw/test/itype.s similarity index 100% rename from fw/test/itype/main.s rename to fw/test/itype.s diff --git a/fw/test/rtype/main.s b/fw/test/rtype.s similarity index 100% rename from fw/test/rtype/main.s rename to fw/test/rtype.s diff --git a/rtl/ALU.sv b/rtl/ALU.sv deleted file mode 100644 index 0dc933b..0000000 --- a/rtl/ALU.sv +++ /dev/null @@ -1,49 +0,0 @@ -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 alu_opcode operation, - output logic [N-1:0] result, - output logic [ 3:0] status -); - logic n, z, c, v; - always_comb begin - 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 - 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 - OR: begin // Or - result = a | b; - c = 'b0; - v = 'b0; - end - AND: begin // And - result = a & b; - c = 'b0; - v = 'b0; - end - SLT: begin // Set less than - result = {31'd0, a < b}; - c = 'b0; - v = 'b0; - end - default: begin - result = 'dx; - c = 1'bx; - v = 1'bx; - end - endcase - n = result[N-1]; - z = (result == '0); - status = {n, z, c, v}; - end -endmodule diff --git a/rtl/ALUDecoder.sv b/rtl/ALUDecoder.sv deleted file mode 100644 index 7471d44..0000000 --- a/rtl/ALUDecoder.sv +++ /dev/null @@ -1,65 +0,0 @@ -`timescale 1ns / 1ps - -module ALUDecoder ( - input logic opcode_5, - input logic [2:0] funct_3, - input logic funct_7_5, - input logic [1:0] alu_op, - output logic [2:0] alu_ctrl, - output logic branch_neg -); - always_comb begin - casex ({ - alu_op, funct_3, opcode_5, funct_7_5 - }) - 'b00xxxxx: begin - alu_ctrl = 'b000; // lw sw - branch_neg = 'dx; - end - 'b01000xx: begin - alu_ctrl = 'b001; // beq - branch_neg = 1; - end - 'b01100xx: begin - alu_ctrl = 'b101; // blt - branch_neg = 0; - end - 'b01101xx: begin - alu_ctrl = 'b101; // bge - branch_neg = 1; - end - 'b1000000: begin - alu_ctrl = 'b000; // add - branch_neg = 'dx; - end - 'b1000001: begin - alu_ctrl = 'b000; // add - branch_neg = 'dx; - end - 'b1000010: begin - alu_ctrl = 'b000; // add - branch_neg = 'dx; - end - 'b1000011: begin - alu_ctrl = 'b001; // sub - branch_neg = 'dx; - end - 'b10010xx: begin - alu_ctrl = 'b101; // slt - branch_neg = 'dx; - end - 'b10110xx: begin - alu_ctrl = 'b000; // or - branch_neg = 'dx; - end - 'b10111xx: begin - alu_ctrl = 'b000; // and - branch_neg = 'dx; - end - default: begin - alu_ctrl = 'dx; - branch_neg = 'dx; - end - endcase - end -endmodule diff --git a/rtl/DataMemory.sv b/rtl/DataMemory.sv deleted file mode 100644 index 6d99ed4..0000000 --- a/rtl/DataMemory.sv +++ /dev/null @@ -1,28 +0,0 @@ -`timescale 1ns / 1ps - -module DataMemory #( -parameter int N = 32, -parameter int SIZE = 32, -parameter int BYTE_WIDTH = 8)( - input logic clk, rst, - input logic[N-1:0] addr, - input logic write_enable, - input logic[N-1:0] write_data, - output logic[N-1:0] read_data -); - logic[SIZE*BYTE_WIDTH-1:0][BYTE_WIDTH-1:0] mem; - - assign read_data = {mem[addr + 'd0], - mem[addr + 'd1], - mem[addr + 'd2], - mem[addr + 'd3]}; - always_ff @(posedge clk) begin - if (rst) - mem <= '{default: '0}; - else if (write_enable) - {mem[addr + 'd0], - mem[addr + 'd1], - mem[addr + 'd2], - mem[addr + 'd3]} <= write_data; - end -endmodule diff --git a/rtl/InstructionMemory.sv b/rtl/InstructionMemory.sv deleted file mode 100644 index ac39b8c..0000000 --- a/rtl/InstructionMemory.sv +++ /dev/null @@ -1,19 +0,0 @@ -`timescale 1ns / 1ps - -// N = Bit width -module InstructionMemory #( - parameter int N = 32, - parameter int N_INSTR = 32, - parameter int BYTE_WIDTH = 8 -) ( - input logic [N-1:0] addr, - output logic [N-1:0] instr -); - logic [BYTE_WIDTH-1:0] mem[N_INSTR*BYTE_WIDTH-1:0]; - - always_comb begin - instr = {mem[addr+'d0], mem[addr+'d1], mem[addr+'d2], mem[addr+'d3]}; - end - - initial $readmemh("sandbox.mem", mem); -endmodule diff --git a/rtl/MainDecoder.sv b/rtl/MainDecoder.sv deleted file mode 100644 index 37cbdd0..0000000 --- a/rtl/MainDecoder.sv +++ /dev/null @@ -1,93 +0,0 @@ -`timescale 1ns / 1ps - -import rv32i_defs::*; - -module MainDecoder( - input logic[6:0] opcode, - output logic branch, - output logic jump, - output logic[1:0] result_src, - output logic mem_write, - output logic alu_src, - output logic[1:0] imm_src, - output logic reg_write, - output logic[1:0] alu_op -); - - opcode_fmt opcode_enum; - assign opcode_enum = opcode_fmt'(opcode); - always_comb begin - case(opcode) - LOAD: begin // lw - reg_write = 1; - imm_src = 'b00; - alu_src = 1; - mem_write = 0; - result_src = 'b01; - branch = 0; - alu_op = 'b00; - jump = 0; - end - STORE: begin // sw - reg_write = 0; - imm_src = 'b01; - alu_src = 1; - mem_write = 1; - result_src = 'bx0; // xx? - branch = 0; - alu_op = 'b00; - jump = 0; - end - REG_OPERATION: begin // r-type - reg_write = 1; - imm_src = 'bxx; - alu_src = 0; - mem_write = 0; - result_src = 'b00; - branch = 0; - alu_op = 'b10; - jump = 0; - end - BRANCH: begin // b-type - reg_write = 0; - imm_src = 'b10; - alu_src = 0; - mem_write = 0; - result_src = 'bxx; - branch = 1; - alu_op = 'b01; - jump = 0; - end - IMM_OPERATION: begin // i-type - reg_write = 1; - imm_src = 'b00; - alu_src = 1; - mem_write = 0; - result_src = 'b00; - branch = 0; - alu_op = 'b10; - jump = 0; - end - JAL: begin // jal - reg_write = 1; - imm_src = 'b11; - alu_src = 'bx; - mem_write = 0; - result_src = 'b10; - branch = 0; - alu_op = 'bxx; - jump = 1; - end - default: begin - reg_write = 'b0; - imm_src = 'bxx; - alu_src = 'bx; - mem_write = 'b0; - result_src = 'b00; - branch = 'b0; - alu_op = 'bx; - jump = 'b0; - end - endcase - end -endmodule diff --git a/rtl/RV32IDefs.sv b/rtl/RV32IDefs.sv deleted file mode 100644 index 6f61c68..0000000 --- a/rtl/RV32IDefs.sv +++ /dev/null @@ -1,22 +0,0 @@ -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, - IMM_OPERATION = 'b0010011, - LOAD = 'b0000011, - STORE = 'b0100011, - BRANCH = 'b1100011, - JAL = 'b1101111, - JALR = 'b1100111, - LUI = 'b0110111, - AUIPC = 'b0010111} opcode_fmt; -endpackage \ No newline at end of file diff --git a/rtl/SingleCycleCPU.sv b/rtl/SingleCycleCPU.sv deleted file mode 100644 index da7c10f..0000000 --- a/rtl/SingleCycleCPU.sv +++ /dev/null @@ -1,115 +0,0 @@ -`timescale 1ns / 1ps - -module SingleCycleCPU( - input logic clk, reset -); - logic[31:0] pc, pc_next; - logic[31:0] imm_ext; - logic[31:0] pc_target; - assign pc_target = imm_ext + pc; - - always_comb begin - case(pc_src) - 'd0: pc_next = pc + 'd4; - 'd1: pc_next = pc_target; - endcase - end - - always_ff @(posedge clk) begin - if(reset) - pc <= 'b0; - else - pc <= pc_next; - end - - logic[31:0] instr; - InstructionMemory #(.N(32)) instruction_memory(pc, instr); - - logic reg_write; - logic[31:0] read_data_1, read_data_2; - logic[31:0] result; - RegisterFile #(.N_REG_ADDR(5), .N_DATA(32)) register_file( - clk, - reset, - instr[19:15], - instr[24:20], - instr[11:7], - reg_write, - result, - read_data_1, - read_data_2 - ); - - logic[1:0] result_src; - logic[1:0] imm_src; - logic[2:0] alu_ctrl; - logic alu_status_zero; - ControlUnit control_unit( - instr[6:0], - instr[14:12], - instr[31:25], - result_src, - mem_write, - alu_ctrl, - alu_src, - imm_src, - reg_write, - jump, - branch, - branch_alu_neg - ); - - JumpControl jump_control( - jump, - branch, - branch_alu_neg, - alu_status_zero, - pc_src); - - Extend imm_extend( - imm_src[1:0], - instr[31:7], - imm_ext[31:0] - ); - - //logic[31:0] src_a = read_data_1; - logic[31:0] src_b; - always_comb begin - case(alu_src) - 'd0: src_b = read_data_2; - 'd1: src_b = imm_ext; - endcase - end - - logic[31:0] alu_result; - logic[3:0] alu_status; - assign alu_status_zero = alu_status[2]; - ALU alu( - read_data_1, - src_b, - alu_ctrl, - alu_result, - alu_status - ); - - logic[31:0] write_data; - assign write_data = read_data_2; - logic[31:0] data_mem_read_data; - DataMemory data_memory( - clk, - reset, - alu_result, - mem_write, - write_data, - data_mem_read_data - ); - - always_comb begin - case(result_src) - 'b00: result = alu_result; - 'b01: result = data_mem_read_data; - 'b10: result = pc + 'd4; - 'b11: result = 'dx; - endcase - end -endmodule diff --git a/rtl/alu.sv b/rtl/alu.sv new file mode 100644 index 0000000..ca50fe2 --- /dev/null +++ b/rtl/alu.sv @@ -0,0 +1,48 @@ +import rv32i_defs::*; + +module alu ( + input logic [OperandSize-1:0] a, + input logic [OperandSize-1:0] b, + input alu_opcode_t operation, + output logic [OperandSize-1:0] result, + output logic [3:0] status +); + logic n, z, c, v; + always_comb begin + case (operation) + SUM: begin + {c, result} = a + b; + v = (result[OperandSize-1] & !a[OperandSize-1] & !b[OperandSize-1]) | + (!result[OperandSize-1] & a[OperandSize-1] & b[OperandSize-1]); + end + SUB: begin + {c, result} = a - b; + v = (result[OperandSize-1] & !a[OperandSize-1] & !b[OperandSize-1]) | + (!result[OperandSize-1] & a[OperandSize-1] & !b[OperandSize-1]); + end + OR: begin + result = a | b; + c = 'b0; + v = 'b0; + end + AND: begin + result = a & b; + c = 'b0; + v = 'b0; + end + SLT: begin + result = {31'd0, a < b}; + c = 'b0; + v = 'b0; + end + default: begin + result = 'dx; + c = 1'bx; + v = 1'bx; + end + endcase + n = result[OperandSize-1]; + z = (result == '0); + status = {n, z, c, v}; + end +endmodule diff --git a/rtl/alu_decoder.sv b/rtl/alu_decoder.sv new file mode 100644 index 0000000..310eabd --- /dev/null +++ b/rtl/alu_decoder.sv @@ -0,0 +1,65 @@ +`timescale 1ns / 1ps + +module alu_decoder( + input logic opcode_5, + input logic [2:0] funct_3, + input logic funct_7_5, + input logic [1:0] alu_op, + output logic [2:0] alu_ctrl, + output logic branch_neg +); + always_comb begin + casez ({ + alu_op, funct_3, opcode_5, funct_7_5 + }) + 'b00?????: begin + alu_ctrl = 3'b000; // lw sw + branch_neg = 1'dx; + end + 'b01000??: begin + alu_ctrl = 3'b001; // beq + branch_neg = 1'd1; + end + 'b01100??: begin + alu_ctrl = 3'b101; // blt + branch_neg = 1'd0; + end + 'b01101??: begin + alu_ctrl = 3'b101; // bge + branch_neg = 1'd1; + end + 'b1000000: begin + alu_ctrl = 3'b000; // add + branch_neg = 1'dx; + end + 'b1000001: begin + alu_ctrl = 3'b000; // add + branch_neg = 1'dx; + end + 'b1000010: begin + alu_ctrl = 3'b000; // add + branch_neg = 1'dx; + end + 'b1000011: begin + alu_ctrl = 3'b001; // sub + branch_neg = 1'dx; + end + 'b10010??: begin + alu_ctrl = 3'b101; // slt + branch_neg = 1'dx; + end + 'b10110??: begin + alu_ctrl = 3'b000; // or + branch_neg = 1'dx; + end + 'b10111??: begin + alu_ctrl = 3'b000; // and + branch_neg = 1'dx; + end + default: begin + alu_ctrl = 3'bxxx; + branch_neg = 1'dx; + end + endcase + end +endmodule diff --git a/rtl/CacheController.sv b/rtl/cache_controller.sv similarity index 100% rename from rtl/CacheController.sv rename to rtl/cache_controller.sv diff --git a/rtl/CacheMemory.sv b/rtl/cache_memory.sv similarity index 95% rename from rtl/CacheMemory.sv rename to rtl/cache_memory.sv index 4da5205..b70e35a 100644 --- a/rtl/CacheMemory.sv +++ b/rtl/cache_memory.sv @@ -1,6 +1,6 @@ `timescale 1ns / 1ps -module CacheMemory #( +module cache_memory #( parameter int ADDR_SIZE = 32, parameter int NUM_SETS = 16, parameter int NUM_WAYS = 4, diff --git a/rtl/ControlUnit.sv b/rtl/control_unit.sv similarity index 84% rename from rtl/ControlUnit.sv rename to rtl/control_unit.sv index e155fff..7a4b636 100644 --- a/rtl/ControlUnit.sv +++ b/rtl/control_unit.sv @@ -2,7 +2,7 @@ import rv32i_defs::*; -module ControlUnit ( +module control_unit ( input logic [6:0] opcode, input logic [2:0] funct_3, input logic [6:0] funct_7, @@ -14,10 +14,10 @@ module ControlUnit ( output logic reg_write, output logic jump, output logic branch, - branch_alu_neg + output logic branch_alu_neg ); logic [1:0] alu_op; - MainDecoder main_decoder ( + main_decoder main_decoder ( .opcode(opcode), .branch(branch), .jump(jump), @@ -29,7 +29,7 @@ module ControlUnit ( .alu_op(alu_op) ); - ALUDecoder alu_decoder ( + alu_decoder alu_decoder ( .opcode_5(opcode[5]), .funct_3(funct_3), .funct_7_5(funct_7[5]), diff --git a/rtl/data_memory.sv b/rtl/data_memory.sv new file mode 100644 index 0000000..65ad6e1 --- /dev/null +++ b/rtl/data_memory.sv @@ -0,0 +1,22 @@ +import rv32i_defs::*; + +module data_memory #( + parameter int BLOCK_SIZE = 8, + parameter int NUM_BLOCKS = 32 +) ( + data_memory_if.ram mem_if +); + logic [NUM_BLOCKS-1:0][BLOCK_SIZE-1:0] mem; + + assign mem_if.read_data = { + mem[mem_if.addr+'d3], mem[mem_if.addr+'d2], mem[mem_if.addr+'d1], mem[mem_if.addr+'d0] + }; + always_ff @(posedge mem_if.clk) begin + if (mem_if.rst) mem <= '{default: '0}; + else if (mem_if.write_enable) + {mem[mem_if.addr+'d3], + mem[mem_if.addr+'d2], + mem[mem_if.addr+'d1], + mem[mem_if.addr+'d0]} <= mem_if.write_data; + end +endmodule diff --git a/rtl/data_memory_if.sv b/rtl/data_memory_if.sv new file mode 100644 index 0000000..ef73d45 --- /dev/null +++ b/rtl/data_memory_if.sv @@ -0,0 +1,18 @@ +interface data_memory_if #( + parameter int ADDR_SIZE = 32, + parameter int DATA_SIZE = 32 +) ( + input logic clk, + input logic rst +); + logic [ADDR_SIZE-1:0] addr; + logic write_enable; + logic [DATA_SIZE-1:0] write_data; + logic [DATA_SIZE-1:0] read_data; + logic valid; + logic ready; + + modport datapath(input read_data, output addr, write_enable, write_data); + modport ram(input clk, rst, addr, write_enable, write_data, output read_data); +endinterface + diff --git a/rtl/HazardUnit.sv b/rtl/hazard_unit.sv similarity index 100% rename from rtl/HazardUnit.sv rename to rtl/hazard_unit.sv diff --git a/rtl/ImmExtend.sv b/rtl/imm_extend.sv similarity index 93% rename from rtl/ImmExtend.sv rename to rtl/imm_extend.sv index 880b76b..b2d128c 100644 --- a/rtl/ImmExtend.sv +++ b/rtl/imm_extend.sv @@ -1,6 +1,6 @@ `timescale 1ns / 1ps -module ImmExtend ( +module imm_extend ( input logic [ 1:0] imm_src, input logic [31:7] instr, output logic [31:0] imm_ext diff --git a/rtl/instr_memory.sv b/rtl/instr_memory.sv new file mode 100644 index 0000000..35a8e5c --- /dev/null +++ b/rtl/instr_memory.sv @@ -0,0 +1,18 @@ +import rv32i_defs::*; + +module instr_memory #( + parameter int N_INSTR = 32, + parameter string FILE_PATH = "" +) ( + input logic [$clog2(N_INSTR * 4)-1:0] addr, + output logic [InstructionSize-1:0] instr +); + // Number of bits referenced with one address + localparam int BlockSize = 8; + localparam int NumBlocks = N_INSTR * 4; + logic [BlockSize-1:0] mem[NumBlocks]; + + assign instr = {mem[addr+'d0], mem[addr+'d1], mem[addr+'d2], mem[addr+'d3]}; + + initial $readmemh(FILE_PATH, mem); +endmodule diff --git a/rtl/JumpControl.sv b/rtl/jump_control.sv similarity index 70% rename from rtl/JumpControl.sv rename to rtl/jump_control.sv index 3ec3beb..fe4e3f3 100644 --- a/rtl/JumpControl.sv +++ b/rtl/jump_control.sv @@ -1,10 +1,10 @@ `timescale 1ns / 1ps -module JumpControl ( +module jump_control ( input logic jump, - branch, - branch_alu_neg, - zero, + input logic branch, + input logic branch_alu_neg, + input logic zero, output logic pc_src ); logic alu_result, branch_result; @@ -14,7 +14,7 @@ module JumpControl ( case (branch_alu_neg) 'd0: branch_result = alu_result; 'd1: branch_result = !alu_result; - default: branch_result = 'dx; + default: branch_result = 1'dx; endcase end diff --git a/rtl/main_decoder.sv b/rtl/main_decoder.sv new file mode 100644 index 0000000..192d4b2 --- /dev/null +++ b/rtl/main_decoder.sv @@ -0,0 +1,93 @@ +`timescale 1ns / 1ps + +import rv32i_defs::*; + +module main_decoder ( + input logic [6:0] opcode, + output logic branch, + output logic jump, + output logic [1:0] result_src, + output logic mem_write, + output logic alu_src, + output logic [1:0] imm_src, + output logic reg_write, + output logic [1:0] alu_op +); + + opcode_fmt_t opcode_enum; + assign opcode_enum = opcode_fmt_t'(opcode); + always_comb begin + case (opcode) + LOAD: begin // lw + reg_write = 1; + imm_src = 'b00; + alu_src = 1; + mem_write = 0; + result_src = 'b01; + branch = 0; + alu_op = 'b00; + jump = 0; + end + STORE: begin // sw + reg_write = 0; + imm_src = 'b01; + alu_src = 1; + mem_write = 1; + result_src = 2'bx0; // xx? + branch = 0; + alu_op = 'b00; + jump = 0; + end + REG_OPERATION: begin // r-type + reg_write = 1; + imm_src = 2'bxx; + alu_src = 0; + mem_write = 0; + result_src = 'b00; + branch = 0; + alu_op = 'b10; + jump = 0; + end + BRANCH: begin // b-type + reg_write = 0; + imm_src = 'b10; + alu_src = 0; + mem_write = 0; + result_src = 2'bxx; + branch = 1; + alu_op = 'b01; + jump = 0; + end + IMM_OPERATION: begin // i-type + reg_write = 1; + imm_src = 'b00; + alu_src = 1; + mem_write = 0; + result_src = 'b00; + branch = 0; + alu_op = 'b10; + jump = 0; + end + JAL: begin // jal + reg_write = 1; + imm_src = 'b11; + alu_src = 1'bx; + mem_write = 0; + result_src = 'b10; + branch = 0; + alu_op = 2'bxx; + jump = 1; + end + default: begin + reg_write = 'b0; + imm_src = 2'bxx; + alu_src = 1'bx; + mem_write = 'b0; + result_src = 'b00; + branch = 'b0; + alu_op = 2'bxx; + jump = 'b0; + end + endcase + end +endmodule diff --git a/rtl/PipelinedControlUnit.sv b/rtl/pipelined_control_unit.sv similarity index 100% rename from rtl/PipelinedControlUnit.sv rename to rtl/pipelined_control_unit.sv diff --git a/rtl/PipelinedCPU.sv b/rtl/pipelined_cpu.sv similarity index 100% rename from rtl/PipelinedCPU.sv rename to rtl/pipelined_cpu.sv diff --git a/rtl/PriorityEncoder.sv b/rtl/priority_encoder.sv similarity index 93% rename from rtl/PriorityEncoder.sv rename to rtl/priority_encoder.sv index 16e3a40..06effb6 100644 --- a/rtl/PriorityEncoder.sv +++ b/rtl/priority_encoder.sv @@ -1,7 +1,7 @@ `timescale 1ns / 1ps // 2**N to N Priority encoder -module PriorityEncoder #( +module priority_encoder #( parameter int N = 4 ) ( input logic [2**N - 1:0] data_in, diff --git a/rtl/RegisterFile.sv b/rtl/register_file.sv similarity index 50% rename from rtl/RegisterFile.sv rename to rtl/register_file.sv index 809aa9e..8fb39c4 100644 --- a/rtl/RegisterFile.sv +++ b/rtl/register_file.sv @@ -1,23 +1,18 @@ -`timescale 1ns / 1ps +import rv32i_defs::*; -// N = Bit width -module RegisterFile #( - parameter int N_REG_ADDR = 5, - parameter int N_REG = 32, - parameter int N_DATA = 32 -) ( +module register_file ( input logic clk, - rst, - input logic [N_REG_ADDR-1:0] addr_1, - addr_2, - addr_3, + input logic rst, + input logic [RegisterSize-1:0] addr_1, + input logic [RegisterSize-1:0] addr_2, + input logic [RegisterSize-1:0] addr_3, input logic write_enable_3, - input logic [N_DATA-1:0] write_data_3, - output logic [N_DATA-1:0] read_data_1, - read_data_2 + input logic [OperandSize-1:0] write_data_3, + output logic [OperandSize-1:0] read_data_1, + output logic [OperandSize-1:0] read_data_2 ); - logic [N_DATA-1:0] mem [N_REG-1:1]; - logic [N_DATA-1:0] zero; + logic [OperandSize-1:0] mem [NumRegisters-1:1]; + logic [OperandSize-1:0] zero; always_comb begin zero = 'd0; diff --git a/rtl/RotateCRU.sv b/rtl/rotate_cru.sv similarity index 100% rename from rtl/RotateCRU.sv rename to rtl/rotate_cru.sv diff --git a/rtl/rv32i_defs.sv b/rtl/rv32i_defs.sv new file mode 100644 index 0000000..dac7ee4 --- /dev/null +++ b/rtl/rv32i_defs.sv @@ -0,0 +1,31 @@ +`timescale 1ns / 1ps + +package rv32i_defs; + // Sizes in bits + localparam int OperandSize = 32; + localparam int InstructionSize = 32; + localparam int NumRegisters = 32; + localparam int RegisterSize = $clog2(NumRegisters); + + typedef enum logic [2:0] { + SUM = 'b000, + SUB = 'b001, + OR = 'b011, + AND = 'b010, + SLT = 'b101 + } alu_opcode_t; + + typedef enum logic [6:0] { + STALL = 'b0000000, + REG_OPERATION = 'b0110011, + IMM_OPERATION = 'b0010011, + LOAD = 'b0000011, + STORE = 'b0100011, + BRANCH = 'b1100011, + JAL = 'b1101111, + JALR = 'b1100111, + LUI = 'b0110111, + AUIPC = 'b0010111 + } opcode_fmt_t; + +endpackage diff --git a/rtl/single_cycle_datapath.sv b/rtl/single_cycle_datapath.sv new file mode 100644 index 0000000..33268d2 --- /dev/null +++ b/rtl/single_cycle_datapath.sv @@ -0,0 +1,121 @@ +`timescale 1ns / 1ps + +import rv32i_defs::*; + +module single_cycle_datapath ( + input logic clk, + input logic rst, + data_memory_if.datapath mem_if +); + logic [InstructionSize-1:0] pc, pc_next; + logic [OperandSize-1:0] imm_ext; + logic [InstructionSize-1:0] pc_target; + assign pc_target = imm_ext + pc; + + logic pc_src; + always_comb begin + case (pc_src) + 'd0: pc_next = pc + 'd4; + 'd1: pc_next = pc_target; + default: pc_next = 'dx; + endcase + end + + always_ff @(posedge clk) begin + if (rst) pc <= 'b0; + else pc <= pc_next; + end + + logic [InstructionSize-1:0] instr; + instr_memory #( + .N_INSTR(32) + ) instr_memory ( + .addr (7'(pc)), + .instr(instr) + ); + + logic reg_write; + logic [OperandSize-1:0] read_data_1, read_data_2; + logic [OperandSize-1:0] result; + register_file register_file ( + .clk(clk), + .rst(rst), + .addr_1(instr[19:15]), + .addr_2(instr[24:20]), + .addr_3(instr[11:7]), + .write_enable_3(reg_write), + .write_data_3(result), + .read_data_1(read_data_1), + .read_data_2(read_data_2) + ); + + logic [1:0] result_src; + logic [1:0] imm_src; + logic [2:0] alu_ctrl; + logic alu_src; + logic alu_status_zero; + logic jump; + logic branch; + logic branch_alu_neg; + control_unit control_unit ( + .opcode(instr[6:0]), + .funct_3(instr[14:12]), + .funct_7(instr[31:25]), + .result_src(result_src), + .mem_write(mem_if.write_enable), + .alu_ctrl(alu_ctrl), + .alu_src(alu_src), + .imm_src(imm_src), + .reg_write(reg_write), + .jump(jump), + .branch(branch), + .branch_alu_neg(branch_alu_neg) + ); + + jump_control jump_control ( + .jump(jump), + .branch(branch), + .branch_alu_neg(branch_alu_neg), + .zero(alu_status_zero), + .pc_src(pc_src) + ); + + imm_extend imm_extend ( + .imm_src(imm_src[1:0]), + .instr (instr[31:7]), + .imm_ext(imm_ext[31:0]) + ); + + logic [OperandSize-1:0] src_b; + always_comb begin + case (alu_src) + 'd0: src_b = read_data_2; + 'd1: src_b = imm_ext; + default: src_b = 'dx; + endcase + end + + logic [OperandSize-1:0] alu_result; + logic [3:0] alu_status; + assign alu_status_zero = alu_status[2]; + alu alu ( + .a(read_data_1), + .b(src_b), + .operation(alu_ctrl), + .result(alu_result), + .status(alu_status) + ); + + assign mem_if.write_data = read_data_2; + assign mem_if.addr = alu_result; + + always_comb begin + case (result_src) + 'b00: result = alu_result; + 'b01: result = mem_if.read_data; + 'b10: result = pc + 'd4; + 'b11: result = 'dx; + default: result = 'dx; + endcase + end +endmodule diff --git a/rtl/TwoWayLRUCache.sv b/rtl/two_way_lru_cache.sv similarity index 100% rename from rtl/TwoWayLRUCache.sv rename to rtl/two_way_lru_cache.sv diff --git a/rtl/TwoWayLRUCRU.sv b/rtl/two_way_lru_cru.sv similarity index 100% rename from rtl/TwoWayLRUCRU.sv rename to rtl/two_way_lru_cru.sv diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0d69a7d..8257935 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,4 @@ -cmake_minimum_required(VERSION 3.10) - -project(rvscc-tests CXX) +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/utils.cmake) find_package(verilator HINTS $ENV{VERILATOR_ROOT}) if (NOT verilator_FOUND) @@ -12,55 +10,67 @@ find_package(Threads REQUIRED) find_package(SystemCLanguage QUIET) -function(rvscc_add_test) - cmake_parse_arguments(TEST - "" - "NAME" - "SOURCES" - ${ARGN} - ) - set(TEST_TARGET_NAME test-${TEST_NAME}) - add_executable(${TEST_TARGET_NAME} sim_main.cpp) - verilate(${TEST_TARGET_NAME} - SOURCES ${TEST_SOURCES} - TRACE - VERILATOR_ARGS --timing --assert - ) - 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() - 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 + TOP test_alu + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/alu.sv + ${CMAKE_CURRENT_SOURCE_DIR}/test_alu.sv ) -rvscc_add_test(NAME priority-encoder - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_PriorityEncoder.sv - ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/PriorityEncoder.sv +rvscc_add_test( + NAME priority-encoder + TOP test_priority_encoder + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/priority_encoder.sv + ${CMAKE_CURRENT_SOURCE_DIR}/test_priority_encoder.sv ) -rvscc_add_test(NAME data-memory - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_DataMemory.sv - ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/DataMemory.sv +rvscc_add_test( + NAME data-memory + TOP test_data_memory + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/data_memory_if.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/data_memory.sv + ${CMAKE_CURRENT_SOURCE_DIR}/test_data_memory.sv ) -rvscc_add_test(NAME imm-extend - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test_ImmExtend.sv - ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/ImmExtend.sv +rvscc_add_test( + NAME imm-extend + TOP test_imm_extend + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/imm_extend.sv + ${CMAKE_CURRENT_SOURCE_DIR}/test_imm_extend.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 + TOP test_register_file + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/register_file.sv + ${CMAKE_CURRENT_SOURCE_DIR}/test_register_file.sv +) + +rvscc_add_test( + NAME instruction_memory + TOP test_instr_memory + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/instr_memory.sv + ${CMAKE_CURRENT_SOURCE_DIR}/test_instr_memory.sv +) + +rvscc_add_test( + NAME single-cycle-core + TOP test_single_cycle_core + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/single_cycle_datapath.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/data_memory_if.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/data_memory.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/instr_memory.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/jump_control.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/control_unit.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/alu_decoder.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/main_decoder.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/register_file.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/imm_extend.sv + ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/alu.sv + ${CMAKE_CURRENT_SOURCE_DIR}/test_single_cycle_core.sv ) diff --git a/test/Test_ALU.sv b/test/Test_ALU.sv deleted file mode 100644 index b028d23..0000000 --- a/test/Test_ALU.sv +++ /dev/null @@ -1,43 +0,0 @@ -import rv32i_defs::alu_opcode; - -module Test_ALU (); - logic [31:0] a, b; - alu_opcode operation; - logic [31:0] result; - logic [ 3:0] status; - ALU alu ( - .a(a), - .b(b), - .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; - - 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; - operation = SUM; - #1; - assert(result == a + b) else $error("Failed in operation: %d + %d", a, b); - end - $finish; - end -endmodule diff --git a/test/Test_CPU.sv b/test/Test_CPU.sv deleted file mode 100644 index 3634f92..0000000 --- a/test/Test_CPU.sv +++ /dev/null @@ -1,12 +0,0 @@ -`timescale 1ns / 1ps -module Test_CPU(); - logic clk, reset; - CPU cpu(clk, reset); - always #10 clk = ~clk; - initial begin - clk = 0; - reset = 1; - #100 - reset = 0; - end -endmodule diff --git a/test/Test_CacheMemory.sv b/test/Test_CacheMemory.sv deleted file mode 100644 index 56f84f0..0000000 --- a/test/Test_CacheMemory.sv +++ /dev/null @@ -1,26 +0,0 @@ -`timescale 1ns / 1ps - -module Test_CacheMemory(); - - -logic[31:0] addr, write_data, read_data; -logic clk, rst, write_enable; - -CacheMemory cache_memory(clk, rst, addr, write_enable, write_data, read_data); - -always #5 clk = ~clk; - -initial begin - clk = 0; - rst = 1; - write_enable = 0; - #25 - rst = 0; - addr = 'd7; - write_enable = 1; - write_data = 'd10; - #25 - write_enable = 0; -end - -endmodule diff --git a/test/Test_DataMemory.sv b/test/Test_DataMemory.sv deleted file mode 100644 index 0c40b96..0000000 --- a/test/Test_DataMemory.sv +++ /dev/null @@ -1,57 +0,0 @@ -`timescale 1ns / 1ps - -module Test_DataMemory (); - logic clk, rst; - logic [31:0] addr; - logic write_enable; - logic [31:0] write_data; - logic [31:0] read_data; - - localparam int MemorySize = 16; - DataMemory #( - .SIZE(MemorySize) - ) DUT ( - .clk(clk), - .rst(rst), - .addr(addr), - .write_enable(write_enable), - .write_data(write_data), - .read_data(read_data) - ); - - always #1 clk = ~clk; - - localparam int MemoryWriteRange = 16; - - logic [MemoryWriteRange:0][31:0] write_values; - int start_addr; - initial begin - // Reset - clk = 0; - rst = 1; - write_enable = 0; - #4; - rst = 0; - #1; - // Write to a range of values in memory - write_enable = 1; - start_addr = $urandom_range(15); - for (int i = 0; i < MemoryWriteRange; i++) begin - addr = start_addr + i*4; - write_values[i] = $urandom(); - write_data = write_values[i]; - #2; - end - // Read and compare the same range of values - write_enable = 0; - #4; - for (int i = 0; i < MemoryWriteRange; i++) begin - addr = start_addr + i*4; - #1; - assert (read_data == write_values[i]) - else $error("Read failed at address %h", addr); - #1; - end - $finish; - end -endmodule diff --git a/test/Test_InstrMemory.sv b/test/Test_InstrMemory.sv deleted file mode 100644 index 8676a0c..0000000 --- a/test/Test_InstrMemory.sv +++ /dev/null @@ -1,21 +0,0 @@ -`timescale 1ns / 1ps - -module Test_InstrMemory(); - logic[31:0] addr; - logic[31:0] instr; - - InstructionMemory instruction_memory( - .addr(addr), - .instr(instr) - ); - - initial begin - addr='d1; - #20 - addr='d11; - #20 - addr='d12; - #20 - addr='d13; - end -endmodule diff --git a/test/Test_PriorityEncoder.sv b/test/Test_PriorityEncoder.sv deleted file mode 100644 index 561e72d..0000000 --- a/test/Test_PriorityEncoder.sv +++ /dev/null @@ -1,24 +0,0 @@ -`timescale 1ns / 1ps - -module Test_PriorityEncoder(); - logic[7:0] data_in; - logic[2:0] data_out; - logic valid; - PriorityEncoder#(.N(3)) encoder( - .data_in(data_in), - .data_out(data_out), - .valid(valid) - ); - initial begin - data_in = 'b00000001; - for (int i = 0; i < 8; i++) begin - #1 assert (data_out == i[2:0] && valid == 1) else $error("Failed one-hot to index check at iteration %0d, %d", i, data_out); - data_in = data_in << 'd1; - end - data_in = 'b00101111; - #1 assert (data_out == 'd5) else $error("Incorrect result with input %b", data_in); - data_in = 'b10101010; - #1 assert (data_out == 'd7) else $error("Incorrect result with input %b", data_in); - $finish; - end -endmodule diff --git a/test/Test_RegisterFile.sv b/test/Test_RegisterFile.sv deleted file mode 100644 index dde9112..0000000 --- a/test/Test_RegisterFile.sv +++ /dev/null @@ -1,77 +0,0 @@ -`timescale 1ns / 1ps - -module Test_RegisterFile(); - logic clk, rst; - logic[4:0] addr_1, addr_2, addr_3; - logic write_enable_3; - logic[31:0] write_data_3; - - logic[31:0] read_data_1, read_data_2; - - RegisterFile register_file( - clk, - rst, - addr_1, - addr_2, - addr_3, - write_enable_3, - write_data_3, - read_data_1, - read_data_2 - ); - - 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; - write_enable_3 = 0; - #4; - rst = 0; - #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 diff --git a/test/test_alu.sv b/test/test_alu.sv new file mode 100644 index 0000000..eb82436 --- /dev/null +++ b/test/test_alu.sv @@ -0,0 +1,70 @@ +import rv32i_defs::*; + +module test_alu (); + logic [31:0] a, b; + alu_opcode_t operation; + logic [31:0] result; + logic [3:0] status; + + alu DUT ( + .a(a), + .b(b), + .operation(operation), + .result(result), + .status(status) + ); + + localparam int RandomSumIterations = 32; + + task static operation_test(input logic [31:0] a_value, input logic [31:0] b_value, + input alu_opcode_t 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", + operation.name(), + a, + b, + result, + "(n: %0b, z: %0b, c: %0b, v: %0b) (expected %4b)", + status[3], + status[2], + status[1], + status[0], + expected_status + ); + endtask + + initial begin + $dumpfile("dump.vcd"); + $dumpvars; + + 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 = $urandom; + b = $urandom; + operation = SUM; + #1; + assert (result == a + b) + else $error("Failed in operation: %d + %d", a, b); + end + $finish; + end +endmodule diff --git a/test/test_cache_memory.sv b/test/test_cache_memory.sv new file mode 100644 index 0000000..3be7d26 --- /dev/null +++ b/test/test_cache_memory.sv @@ -0,0 +1,29 @@ +`timescale 1ns / 1ps + +module test_cache_memory (); + + logic [31:0] addr, write_data, read_data; + logic clk, rst, write_enable; + + CacheMemory cache_memory ( + .clk(clk), + .rst(rst), + write_enable, + write_data, + read_data + ); + + always #5 clk = ~clk; + + initial begin + clk = 0; + rst = 1; + write_enable = 0; + #25 rst = 0; + addr = 'd7; + write_enable = 1; + write_data = 'd10; + #25 write_enable = 0; + end + +endmodule diff --git a/test/test_data_memory.sv b/test/test_data_memory.sv new file mode 100644 index 0000000..98de58d --- /dev/null +++ b/test/test_data_memory.sv @@ -0,0 +1,65 @@ +`timescale 1ns / 1ps + +import rv32i_defs::*; + +module test_data_memory (); + localparam int NumInstr = 64; + // Each block is a byte + localparam int MemoryBlockSize = 8; + // Each instruction address have 4 bytes + localparam int NumMemoryBlocks = NumInstr * 4; + localparam int AddrSize = $clog2(NumMemoryBlocks); + + logic clk, rst; + data_memory_if #( + .ADDR_SIZE(AddrSize), + .DATA_SIZE(OperandSize) + ) mem_if ( + .clk(clk), + .rst(rst) + ); + + data_memory #( + .BLOCK_SIZE(MemoryBlockSize), + .NUM_BLOCKS(NumMemoryBlocks) + ) dut ( + .mem_if(mem_if) + ); + + always #1 clk = ~clk; + + localparam int MemoryWriteRange = 16; + logic [MemoryWriteRange-1:0][OperandSize-1:0] write_values; + int start_addr; + + initial begin + // Reset + clk = 0; + rst = 1; + mem_if.write_enable = 0; + #4; + rst = 0; + #1; + // Write to a range of values in memory + mem_if.write_enable = 1; + start_addr = $urandom; + for (int i = 0; i < MemoryWriteRange; i++) begin + mem_if.addr = AddrSize'(start_addr + i * 4); + write_values[i] = $urandom; + mem_if.write_data = write_values[i]; + #2; + end + // Read and compare the same range of values + mem_if.write_enable = 0; + #4; + for (int i = 0; i < MemoryWriteRange; i++) begin + $display(start_addr, i, AddrSize); + mem_if.addr = AddrSize'(start_addr + i * 4); + #1; + assert (mem_if.read_data == write_values[i]) + else $error("Read failed at address %h", mem_if.addr); + #1; + end + $finish; + end +endmodule diff --git a/test/Test_ImmExtend.sv b/test/test_imm_extend.sv similarity index 92% rename from test/Test_ImmExtend.sv rename to test/test_imm_extend.sv index 44e49f6..415985c 100644 --- a/test/Test_ImmExtend.sv +++ b/test/test_imm_extend.sv @@ -1,11 +1,11 @@ `timescale 1ns / 1ps -module Test_ImmExtend (); +module test_imm_extend(); logic [ 1:0] imm_src; logic [31:0] instr; logic [31:0] imm_ext; - ImmExtend DUT ( + imm_extend DUT ( .imm_src(imm_src), .instr (instr[31:7]), .imm_ext(imm_ext) diff --git a/test/test_instr_memory.sv b/test/test_instr_memory.sv new file mode 100644 index 0000000..be9a523 --- /dev/null +++ b/test/test_instr_memory.sv @@ -0,0 +1,69 @@ +`timescale 1ns / 1ps + +import rv32i_defs::*; + +module test_instr_memory (); + localparam string Path = "../fw/test/test-core.mem"; + localparam int NumInstr = 32; + localparam int NumBlocks = NumInstr * 4; + localparam int AddrSize = $clog2(NumBlocks); + + logic [AddrSize-1:0] addr; + logic [InstructionSize-1:0] instr; + + instr_memory #( + .N_INSTR (NumInstr), + .FILE_PATH(Path) + ) instruction_memory ( + .addr (addr), + .instr(instr) + ); + + const + int + assert_instr_mem[21] = { + 'h00500113, + 'h00C00193, + 'hFF718393, + 'h0023E233, + 'h0041F2B3, + 'h004282B3, + 'h02728863, + 'h0041A233, + 'h00020463, + 'h00000293, + 'h0023A233, + 'h005203B3, + 'h402383B3, + 'h0471AA23, + 'h06002103, + 'h005104B3, + 'h008001EF, + 'h00100113, + 'h00910133, + 'h0221A023, + 'h00210063 + }; + + initial begin + addr = 'd0; + #1 + assert (!$isunknown(instr)) + else $error("Instruction memory not loaded"); + #1; + foreach (assert_instr_mem[i]) begin + $display(i); + addr = AddrSize'(i * 4); + #1 + assert (instr == assert_instr_mem[i]) + else + $error( + "Instruction %h at address %h does not match the expected intruction %h", + instr, + addr, + assert_instr_mem[i] + ); + end + $finish; + end +endmodule diff --git a/test/test_priority_encoder.sv b/test/test_priority_encoder.sv new file mode 100644 index 0000000..baf8027 --- /dev/null +++ b/test/test_priority_encoder.sv @@ -0,0 +1,34 @@ +`timescale 1ns / 1ps + +module test_priority_encoder(); + logic [7:0] data_in; + logic [2:0] data_out; + logic valid; + + priority_encoder #( + .N(3) + ) encoder ( + .data_in(data_in), + .data_out(data_out), + .valid(valid) + ); + + initial begin + data_in = 'b00000001; + for (int i = 0; i < 8; i++) begin + #1 + assert (data_out == i[2:0] && valid == 1) + else $error("Failed one-hot to index check at iteration %0d, %d", i, data_out); + data_in = data_in << 'd1; + end + data_in = 'b00101111; + #1 + assert (data_out == 'd5) + else $error("Incorrect result with input %b", data_in); + data_in = 'b10101010; + #1 + assert (data_out == 'd7) + else $error("Incorrect result with input %b", data_in); + $finish; + end +endmodule diff --git a/test/test_register_file.sv b/test/test_register_file.sv new file mode 100644 index 0000000..391d543 --- /dev/null +++ b/test/test_register_file.sv @@ -0,0 +1,95 @@ +`timescale 1ns / 1ps + +import rv32i_defs::*; + +module test_register_file (); + logic clk, rst; + logic [RegisterSize-1:0] addr_1, addr_2, addr_3; + logic write_enable_3; + logic [OperandSize-1:0] write_data_3; + logic [OperandSize-1:0] read_data_1, read_data_2; + + register_file DUT ( + .clk(clk), + .rst(rst), + .addr_1(addr_1), + .addr_2(addr_2), + .addr_3(addr_3), + .write_enable_3(write_enable_3), + .write_data_3(write_data_3), + .read_data_1(read_data_1), + .read_data_2(read_data_2) + ); + + always #1 clk = ~clk; + + logic [NumRegisters-1:0][OperandSize-1:0] write_values; + + initial begin + $dumpfile("regfile.vcd"); + $dumpvars; + // Reset + clk = 0; + rst = 1; + write_enable_3 = 0; + #4; + rst = 0; + #1; + // Write to all registers + write_enable_3 = 1; + for (int i = 0; i < NumRegisters; i++) begin + addr_1 = 5'($urandom); + addr_2 = 5'($urandom); + addr_3 = i[4:0]; + write_values[i] = $urandom; + write_data_3 = write_values[i]; + $display("%h", 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 < NumRegisters; i++) begin + addr_1 = i[4:0]; + addr_2 = 5'($urandom); + addr_3 = 5'($urandom); + #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 < NumRegisters; i++) begin + addr_1 = 5'($urandom); + addr_2 = i[4:0]; + addr_3 = 5'($urandom); + #2; + if (i == 0) begin + assert (read_data_2 == 'd0) + else $error("Read failed at register x0 using addr_2, value should stay at 0"); + end else begin + assert (read_data_2 == write_values[i]) + else + $error( + "Read failed at register x%h using addr_2 %d, %d", + addr_2, + read_data_2, + write_values[i] + ); + end + end + $finish; + end +endmodule diff --git a/test/test_single_cycle_core.sv b/test/test_single_cycle_core.sv new file mode 100644 index 0000000..f3f9ebe --- /dev/null +++ b/test/test_single_cycle_core.sv @@ -0,0 +1,30 @@ +`timescale 1ns / 1ps + +module test_single_cycle_core (); + logic clk, rst; + always #1 clk = ~clk; + + single_cycle_datapath dut ( + .clk(clk), + .rst(rst), + .mem_if(mem_if.datapath) + ); + + data_memory_if mem_if ( + .clk(clk), + .rst(rst) + ); + + data_memory mem (.mem_if(mem_if.ram)); + + initial begin + $dumpfile("single_cycle.vcd"); + $dumpvars(1, dut); + clk = 0; + rst = 1; + #4; + rst = 0; + #100; + $finish; + end +endmodule diff --git a/test/Test_TwoWayLRUCache.sv b/test/test_two_way_lru_cache.sv similarity index 100% rename from test/Test_TwoWayLRUCache.sv rename to test/test_two_way_lru_cache.sv