RISC_V_LAB hinzugefügt
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
// *********************************************************************************************
|
||||
// Description : Verilator simulation harness
|
||||
// Project Version : v1.0
|
||||
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
|
||||
// -----
|
||||
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
|
||||
// Created : 12.Aug.2025 by Marcus Bednara
|
||||
// Last Modified : 15.Oct.2025 by Hussein Elzomor [commit d0452cd]
|
||||
// -----
|
||||
// HISTORY : Date By Comments
|
||||
// ----------- --------- -------------------------------------------------
|
||||
// 15.Oct.2025 H.Elzomor Renamed file and module from soc_harness to cpu_harness
|
||||
// 15.Oct.2025 H.Elzomor Added getMem function, setMem task and printMem task
|
||||
// *********************************************************************************************
|
||||
|
||||
|
||||
|
||||
timeunit 1ps;
|
||||
timeprecision 1ps;
|
||||
|
||||
module cpu_harness;
|
||||
|
||||
// local signals
|
||||
logic clk,
|
||||
rst;
|
||||
|
||||
logic [7:0] led;
|
||||
|
||||
logic [6:0] btn;
|
||||
|
||||
|
||||
// toplevel instance (DUT)
|
||||
|
||||
cpu u_cpu (
|
||||
.led (led),
|
||||
.btn ({btn[6:1], rst}),
|
||||
.clk_25mhz (clk)
|
||||
); // u_cpu
|
||||
|
||||
|
||||
`ifdef VERILATOR
|
||||
|
||||
// Declare all functions with DPI-C interface to make them accessible from the C++ testbench
|
||||
|
||||
export "DPI-C" task setClk;
|
||||
export "DPI-C" task enable;
|
||||
export "DPI-C" task loadRAM;
|
||||
// export "DPI-C" task dumpSRAM;
|
||||
export "DPI-C" task setInitial;
|
||||
export "DPI-C" function getLed;
|
||||
export "DPI-C" task setBtn;
|
||||
export "DPI-C" task setReset;
|
||||
export "DPI-C" function getMem;
|
||||
export "DPI-C" task setMem;
|
||||
export "DPI-C" task printMem;
|
||||
export "DPI-C" function getReg;
|
||||
export "DPI-C" task printReg;
|
||||
|
||||
|
||||
// Clocking is controlled from C++ testbench
|
||||
task setClk (input logic val);
|
||||
clk = val;
|
||||
endtask: setClk
|
||||
|
||||
`else
|
||||
|
||||
// If not using verilator, generate clock here
|
||||
|
||||
const realtime clk_PERIOD = 1.0ns;
|
||||
|
||||
|
||||
initial begin: clock_driver
|
||||
clk = '1;
|
||||
forever begin
|
||||
#(clk_PERIOD/2.0);
|
||||
clk <= ~clk;
|
||||
end
|
||||
end: clock_driver
|
||||
|
||||
task wait_clk_cycles(int unsigned n);
|
||||
repeat(n) @(posedge clk);
|
||||
endtask
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
// Remaining tasks are identical for Verilator and other simulators
|
||||
|
||||
|
||||
|
||||
task loadRAM (input string fileName);
|
||||
$display ("Initializing SRAM memory from %s", fileName);
|
||||
$readmemh(fileName, u_cpu.theMem.RAM);
|
||||
endtask: loadRAM
|
||||
|
||||
|
||||
/* Some helper stuff */
|
||||
|
||||
task enable(int val);
|
||||
// nothing to do, we have no fetch enable in this design
|
||||
endtask: enable
|
||||
|
||||
task setInitial();
|
||||
btn = 7'b0;
|
||||
rst = 'b0;
|
||||
endtask: setInitial
|
||||
|
||||
function int getLed;
|
||||
getLed = {24'b0, led};
|
||||
endfunction: getLed
|
||||
|
||||
task setBtn(int val);
|
||||
btn[6:1] = val[5:0];
|
||||
endtask: setBtn
|
||||
|
||||
task setReset (input int val);
|
||||
rst = (val==1);
|
||||
endtask: setReset
|
||||
|
||||
function int getMem(int location);
|
||||
getMem = u_cpu.theMem.RAM[location];
|
||||
endfunction: getMem
|
||||
|
||||
task setMem(int location, int value);
|
||||
u_cpu.theMem.RAM[location] = value;
|
||||
endtask: setMem
|
||||
|
||||
task printMem (int location, string prog);
|
||||
case (prog)
|
||||
"fibonacci" :$display("Value at RAM[%0d]: 0x%h : %0d", location, getMem(location), getMem(location));
|
||||
"helloWorld" :$display("Value at RAM[%0d]: 0x%h : %s" , location, getMem(location), getMem(location));
|
||||
default :$display("Value at RAM[%0d]: 0x%h : %0d", location, getMem(location), getMem(location));
|
||||
endcase
|
||||
endtask: printMem
|
||||
|
||||
function int getReg(int location);
|
||||
getReg = u_cpu.theRegisters.registers[location];
|
||||
endfunction: getReg
|
||||
|
||||
task printReg (int location, string prog);
|
||||
case (prog)
|
||||
"primeNumber" :$display("Time =%5dns \t : Register [%0d] updated - Finding the prime factors of %0d", $time, location, getReg(location));
|
||||
"primeFactors":$display("Time =%5dns \t : Register [%0d] updated - %0d is a prime factor", $time, location, getReg(location));
|
||||
default :$display("Time =%5dns \t : Value at Reg[%0d]: 0x%h", $time, location, getReg(location));
|
||||
endcase
|
||||
endtask: printReg
|
||||
|
||||
endmodule: cpu_harness
|
||||
@@ -0,0 +1,173 @@
|
||||
// *********************************************************************************************
|
||||
// Description : Verilator simulation harness
|
||||
// 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 : 15.Oct.2025 by Hussein Elzomor
|
||||
// -----
|
||||
// HISTORY : Date By Comments
|
||||
// ----------- --------- -------------------------------------------------
|
||||
// *********************************************************************************************
|
||||
|
||||
|
||||
|
||||
timeunit 1ps;
|
||||
timeprecision 1ps;
|
||||
|
||||
module decoder_harness;
|
||||
// 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)
|
||||
); // u_decoder
|
||||
|
||||
|
||||
// Special Verilator specific tasks
|
||||
`ifdef VERILATOR
|
||||
|
||||
// Declare all functions with DPI-C interface to make them accessible from the C++ testbench
|
||||
// Setters
|
||||
export "DPI-C" task setClk;
|
||||
export "DPI-C" task enable;
|
||||
export "DPI-C" task loadRAM;
|
||||
export "DPI-C" task setInitial;
|
||||
export "DPI-C" task printInfo;
|
||||
|
||||
// Clocking is controlled from C++ testbench
|
||||
task setClk (input logic val);
|
||||
clk = val;
|
||||
endtask: setClk
|
||||
|
||||
`else
|
||||
|
||||
// If not using verilator, generate clock here
|
||||
const realtime clk_PERIOD = 1.0ns;
|
||||
|
||||
initial begin: clock_driver
|
||||
clk = '1;
|
||||
forever begin
|
||||
#(clk_PERIOD/2.0);
|
||||
clk <= ~clk;
|
||||
end
|
||||
end: clock_driver
|
||||
|
||||
task wait_clk_cycles(int unsigned n);
|
||||
repeat(n) @(posedge clk);
|
||||
endtask
|
||||
|
||||
`endif
|
||||
|
||||
// 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
|
||||
|
||||
// Remaining tasks are identical for Verilator and other simulators
|
||||
task enable(int val);
|
||||
// nothing to do, we have no fetch enable in this design
|
||||
endtask: enable
|
||||
|
||||
// Load data into memory
|
||||
task loadRAM (input string fileName);
|
||||
$display ("Initializing SRAM memory from %s", fileName);
|
||||
$readmemh(fileName, mem);
|
||||
endtask: loadRAM
|
||||
|
||||
// Set initial values
|
||||
task setInitial();
|
||||
Instruction = mem[0];
|
||||
counter = 0;
|
||||
CurrentPC = 32'hdeadbeef;
|
||||
RData = 32'hbeefdead;
|
||||
for(int i=0; i<REG_FILE_SIZE; i++) begin
|
||||
regFile[i] = i;
|
||||
end
|
||||
endtask: setInitial
|
||||
|
||||
// Print decoder signals
|
||||
task printInfo();
|
||||
$displayh("(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 );
|
||||
$displayh("");
|
||||
endtask: printInfo
|
||||
|
||||
endmodule: decoder_harness
|
||||
Reference in New Issue
Block a user