DfT/riscv_rtl/hw/dv/rtl/decoder_tb.sv
2026-05-29 10:19:13 +02:00

151 lines
6.7 KiB
Systemverilog

// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Hussein Elzomor
// Last Modified : 23.Oct.2025 by Hussein Elzomor [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
`timescale 1ns/1ns
module decoder_tb ();
// local Parameters
localparam MEM_SIZE = 37;
localparam REG_FILE_SIZE = 32;
// local signals
logic clk;
int counter;
logic[31:0] mem [MEM_SIZE-1:0];
logic[31:0] regFile [REG_FILE_SIZE-1:0];
// PC
logic[31:0] CurrentPC;
logic[31:0] JumpOrBranchPC;
logic JumpOrBranch;
logic[31:0] NextPC;
// Memory
logic[31:0] DAddr;
logic[31:0] WData;
logic[31:0] RData;
logic[31:0] Instruction;
logic WrMem;
logic[1:0] DWidth;
// Register File;
logic[4:0] Rs1;
logic[4:0] Rs2;
logic[4:0] Rd;
logic[31:0] RRs1;
logic[31:0] RRs2;
logic[31:0] WRd;
logic WrReg;
// Protection
logic Illegal;
// Toplevel instance (DUT)
decoder u_decoder (
// PC
.CurrentPC(CurrentPC),
.JumpOrBranchPC(JumpOrBranchPC),
.JumpOrBranch(JumpOrBranch),
// Memory
.DAddr(DAddr),
.WData(WData),
.RData(RData),
.Instruction(Instruction),
.WrMem(WrMem),
.DWidth(DWidth),
// Register File
.Rs1(Rs1),
.Rs2(Rs2),
.Rd(Rd),
.RRs1(RRs1),
.RRs2(RRs2),
.WRd(WRd),
.WrReg(WrReg),
// Protection
.Illegal(Illegal)
);
// Clock generation
always begin
clk = ~clk; #1;
end
// Load a new instruction every cycle
always_ff @(posedge clk) begin: increment_instruction_and_print_info
if (counter < MEM_SIZE) begin
if (counter > 0) printInfo();
Instruction = mem[counter++];
end
end
// Return the value of the RegFile
always_comb begin: reg_file_assignment
RRs1 = regFile[Rs1];
RRs2 = regFile[Rs2];
end
// Initialize and run simulation
initial begin
dumpWave("wave.vcd");
loadMem("decoder.hex");
clk = 1;
counter = 0;
CurrentPC = 32'hdeadbeef;
RData = 32'hbeefdead;
for(int i=0; i<REG_FILE_SIZE; i++) begin
regFile[i] = i;
end
while (counter < MEM_SIZE) #1;
printInfo();
#1 $finish;
end
// Functions
// Wave Dump Helper Task
task dumpWave(string fileName);
// Open wave file and dump all signals (2D arrays not included)
$display("\nTime = %0dns \t : Opening wave file '%s'", $time, fileName);
$dumpfile(fileName);
$display("Time = %0dns \t : Dumping all %s signals in wave file (2D arrays not included)", $time, "decoder_tb");
$dumpvars(0, decoder_tb);
endtask: dumpWave
// Load hex file into memory
task loadMem (string fileName);
$display("\nTime = %0dns \t : Loading '%s' into Memory", $time, fileName);
$readmemh(fileName, mem);
endtask: loadMem
// Print decoder signals
task printInfo();
$displayh("\n(cycle %0d) Decoder (I/O) \tDecoder (Internal Signals) \tALU" , counter );
$displayh(" -------------------------- \t--------------------------------------------- \t---------------------" );
$displayh(" CurrentPC : 0x%h OpCode : 0b%b aluOp : 0b%b" , CurrentPC , u_decoder.theOp , u_decoder.aluOp );
$displayh(" JumpOrBranchPC: 0x%h theFunct3: 0b%b aluNegAr : 0b%b" , JumpOrBranchPC, u_decoder.theFunct3, u_decoder.aluNegAr );
$displayh(" JumpOrBranch : 0b%b \ttheFunct7: 0b%b aluBypass: 0b%b", JumpOrBranch , u_decoder.theFunct7, u_decoder.aluBypass);
$displayh(" DAddr : 0x%h i_imm : 0b%b op1 : 0x%h" , DAddr , u_decoder.i_imm , u_decoder.op1 );
$displayh(" WData : 0x%h s_imm : 0b%b op2 : 0x%h" , WData , u_decoder.s_imm , u_decoder.op2 );
$displayh(" RData : 0x%h b_imm : 0b%b result : 0x%h" , RData , u_decoder.b_imm , u_decoder.result );
$displayh(" Instruction : 0x%h u_imm : 0b%b eqFlag : 0b%b" , Instruction , u_decoder.u_imm , u_decoder.eqFlag );
$displayh(" WrMem : 0b%b \tj_imm : 0b%b" , WrMem , u_decoder.j_imm );
$displayh(" DWidth : 0b%b" , DWidth );
$displayh(" Rs1 : %0d " , Rs1 );
$displayh(" Rs2 : %0d " , Rs2 );
$displayh(" Rd : 0x%h" , Rd );
$displayh(" RRs1 : %0d " , RRs1 );
$displayh(" RRs2 : %0d " , RRs2 );
$displayh(" WRd : 0x%h" , WRd );
$displayh(" WrReg : 0b%b" , WrReg );
$displayh(" Illegal : 0b%b" , Illegal );
endtask: printInfo
endmodule