rv32g-core

Pipelined, synthesizable, and fabricable RISC-V core in SystemVerilog+Yosys+OpenROAD
Log | Files | Refs | LICENSE

commit bc62a1834a9e97d3efbab4ac384379738544b6d9
parent a27f857278de6f860ba720e069848f206e54bd43
Author: Vineet Kumar <git@vineetk.net>
Date:   Tue, 14 Jul 2026 13:29:40 +0530

move $display() messages to tb

Diffstat:
Mrtl/rv32g_hart.sv | 35++++++-----------------------------
Mrtl/rv32g_pkg.sv | 3++-
Mrtl/tb_rv32g.sv | 28++++++++++++++++++++++++++--
3 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/rtl/rv32g_hart.sv b/rtl/rv32g_hart.sv @@ -79,8 +79,6 @@ module rv32g_hart end end always_ff @(posedge clk or negedge rstN) begin - $display("IF: pc: %h, next_pc: %h, imem_valid: %d, imem[%h]: %h, inst: %h", - ifid_reg.pc, next_pc, imem_valid, imem_addr, imem_data, ifid_reg.inst); if (!rstN) begin pc_reg <= BASE_ADDR; ifid_reg <= '0; @@ -102,8 +100,6 @@ module rv32g_hart .rd_num(dec_rd_num), .csr_addr(dec_csr_addr)); // ID/EX pipeline register always_ff @(posedge clk or negedge rstN) begin - $display("ID: ctrl: %h, imm: %h, rs1_val: %h, rs2_val: %h, rd_num: %d", - idex_reg.ctrl, idex_reg.imm, idex_reg.rs1_val, idex_reg.rs2_val, idex_reg.rd_num); if (!rstN) begin // NOP by default idex_reg <= '0; @@ -127,17 +123,11 @@ module rv32g_hart end end - always_ff @(posedge clk) begin - if (idex_reg.ctrl.exception != EXC_NONE) begin - // TODO handle exceptions. might need moving. - unique case (idex_reg.ctrl.exception) - EXC_NONE: ; - EXC_ILL_INST: $display("Exception: illegal instruction, inst: %h", ifid_reg.inst); - EXC_CALL: $display("Exception: ECALL"); - EXC_BKPT: $display("Exception: BREAK"); - endcase - end - end + // always_ff @(posedge clk) begin + // // TODO handle exceptions. might need moving. + // if (idex_reg.ctrl.exception != EXC_NONE) begin + // end + // end // TODO find out what else needs to be done in between stages like exceptions // =============== @@ -169,11 +159,6 @@ module rv32g_hart exmem_reg = '0; exmem_reg.pc = idex_reg.pc; end else begin - $display("EX: op: %h, op1src: %d, op2src: %d, branchop: %d, out: %h, branch_taken: %d, rs1_val: %h, rs2_val: %h", - idex_reg.ctrl.aluop, idex_reg.ctrl.aluop1src, idex_reg.ctrl.aluop2src, - idex_reg.ctrl.branchop, exmem_reg.alu_out, exmem_reg.branch_taken, - idex_reg.rs1_val, idex_reg.rs2_val); - exmem_reg.alu_out = ex_alu_out; exmem_reg.csr_out = ex_csr_out; exmem_reg.rs2_val = idex_reg.rs2_val; @@ -206,9 +191,6 @@ module rv32g_hart if (!rstN) begin memwb_reg = '0; end else begin - $display("MEM: memop: %h, dmem_addr: %h, dmem_rdata: %h, dmem_wdata: %h, dmem_we: %d, dmem_be: %b, mem_out: %h", - exmem_reg.memop, dmem_addr, dmem_rdata, dmem_wdata, dmem_we, dmem_be, memwb_reg.mem_out); - memwb_reg.alu_out = exmem_reg.alu_out; memwb_reg.mem_out = mem_mem_out; memwb_reg.csr_out = exmem_reg.csr_out; @@ -232,11 +214,6 @@ module rv32g_hart .imm(memwb_reg.imm), .alu_out(memwb_reg.alu_out), .mem_out(memwb_reg.mem_out)); - always_ff @(posedge clk) begin - $display("WB: wbsrc: %d, rd_num: %d, pc: %h, imm: %h, alu_out: %h, mem_out: %h", - memwb_reg.wbsrc, memwb_reg.rd_num, memwb_reg.pc, memwb_reg.imm, - memwb_reg.alu_out, memwb_reg.mem_out); - end // TODO move to writeback stage or as separate stage? always_comb begin @@ -256,6 +233,6 @@ module rv32g_hart end assign exception = (idex_reg.ctrl.exception != EXC_NONE) ? idex_reg.ctrl.exception : - (idex_reg.ctrl.csrop != CSR_NONE && csr_illegal) ? EXC_ILL_INST : EXC_NONE; + (idex_reg.ctrl.csrop != CSR_NONE && csr_illegal) ? EXC_ILL_CSR : EXC_NONE; endmodule: rv32g_hart diff --git a/rtl/rv32g_pkg.sv b/rtl/rv32g_pkg.sv @@ -278,8 +278,9 @@ package rv32g_pkg; // very rudimentary. privileged spec (chapter 3) defines this formally, but left to implementation // on unprivileged spec. - typedef enum logic [1:0] {EXC_NONE, + typedef enum logic [2:0] {EXC_NONE, EXC_ILL_INST, // illegal instruction + EXC_ILL_CSR, // illegal csr EXC_CALL, // ECALL EXC_BKPT // EBREAK } exception_t; diff --git a/rtl/tb_rv32g.sv b/rtl/tb_rv32g.sv @@ -82,9 +82,33 @@ module tb_rv32g parameter int MAX_CYCLES = 10000; always_ff @(posedge clk) begin + $display("IF: pc: %h, next_pc: %h, imem_valid: %d, imem[%h]: %h, inst: %h", + dut.ifid_reg.pc, dut.next_pc, dut.imem_valid, dut.imem_addr, dut.imem_data, dut.ifid_reg.inst); + $display("ID: ctrl: %h, imm: %h, rs1_val: %h, rs2_val: %h, rd_num: %d", + dut.idex_reg.ctrl, dut.idex_reg.imm, dut.idex_reg.rs1_val, dut.idex_reg.rs2_val, dut.idex_reg.rd_num); + $display("EX: op: %h, op1src: %d, op2src: %d, branchop: %d, out: %h, branch_taken: %d, rs1_val: %h, rs2_val: %h", + dut.idex_reg.ctrl.aluop, dut.idex_reg.ctrl.aluop1src, dut.idex_reg.ctrl.aluop2src, + dut.idex_reg.ctrl.branchop, dut.exmem_reg.alu_out, dut.exmem_reg.branch_taken, + dut.idex_reg.rs1_val, dut.idex_reg.rs2_val); + $display("MEM: memop: %h, dmem_addr: %h, dmem_rdata: %h, dmem_wdata: %h, dmem_we: %d, dmem_be: %b, mem_out: %h", + dut.exmem_reg.memop, dut.dmem_addr, dut.dmem_rdata, dut.dmem_wdata, dut.dmem_we, dut.dmem_be, dut.memwb_reg.mem_out); + $display("WB: wbsrc: %d, rd_num: %d, pc: %h, imm: %h, alu_out: %h, mem_out: %h", + dut.memwb_reg.wbsrc, dut.memwb_reg.rd_num, dut.memwb_reg.pc, dut.memwb_reg.imm, + dut.memwb_reg.alu_out, dut.memwb_reg.mem_out); + + if (dut.idex_reg.ctrl.exception != EXC_NONE) begin + unique case (dut.idex_reg.ctrl.exception) + EXC_NONE: ; + EXC_ILL_INST: $display("Exception: illegal instruction, inst: %h", dut.ifid_reg.inst); + EXC_ILL_CSR: $display("Exception: illegal csr, inst: %h, csrop: %d, csr_addr: %h", dut.ifid_reg.inst, dut.idex_reg.ctrl.csrop, dut.idex_reg.csr_addr); + EXC_CALL: $display("Exception: ECALL"); + EXC_BKPT: $display("Exception: BREAK"); + endcase + end + if (exception == EXC_ILL_INST && seen_first_real_inst) begin - $display("!!! Program terminated (exception ILL_INST at PC %h), inst: %h, csrop: %d, csr_ill_rd: %d, csr_ill_wr: %d !!!", - pc_out, dut.ifid_reg.inst, dut.idex_reg.ctrl.csrop, dut.u_csr.illegal_rd, dut.u_csr.illegal_wr); + $display("!!! Program terminated (exception ILL_INST at PC %h), inst: %h !!!", + pc_out, dut.ifid_reg.inst); $finish(); end