//  *********************************************************************************************
//  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 Bomin Kim
//  Last Modified    : 23.Oct.2025  by Bomin Kim       [commit 2f8f03d]
//  -----
//  HISTORY          : Date         By         Comments
//                     -----------  ---------  -------------------------------------------------
//  *********************************************************************************************



`timescale 1ns/1ns

module reg_file_tb ();

  // Local Signals
  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;
  logic       reset;
  logic       clk;

  // Toplevel instance (DUT)
  reg_file u_reg_file (
      .Rs1(Rs1),
      .Rs2(Rs2),
      .Rd(Rd),
      .RRs1(RRs1),
      .RRs2(RRs2),
      .WRd(WRd),
      .WrReg(WrReg),
      .reset(reset),
      .clk(clk)
  );

  // Clock generation
  always #20 clk = ~clk;

  // Initialization and run simulation
  initial begin
    dumpWave("wave.vcd");

    // Initialize inputs
    clk = 0;
    Rs1 = 0; Rs2 = 0; Rd = 0;
    WRd = 0; WrReg = 0; // Read
    reset = 1;

    #50
    reset = 0;

    #50 // Write 0xDEADBEEF to reg21
    Rd = 5'd21;
    WrReg = 1; // Write
    WRd = 32'hDEADBEEF;
    #50; WrReg = 0;

    #50
    Rs1 = 5'd21; // read reg21 into RRs1
    Rs2 = 5'd0;

    #50 // Write 0x12345678 to reg5
    Rd = 5'd5;
    WrReg = 1; // Write
    WRd = 32'h12345678;
    #50; WrReg = 0;

    #50
    Rs1 = 5'd5; // read reg10 into RRs1

    #50
    Rs1 = 5'd0; // read zero register

    #50
    Rd = 5'd0; // attempt to write 0xCAFEBABE to zero register
    WRd = 32'hCAFEBABE;
    WrReg = 1; // Write
    #50; WrReg = 0;

    #50
    Rs1 = 5'd5; // Read from reg5
    #200

    $finish;
  end

  // 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, "reg_file_tb");
    $dumpvars(0, reg_file_tb);

    // Dump registers in wave file
    $display("\nTime =  %0dns \t  : Dumping Registers in wave file", $time);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[1]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[2]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[3]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[4]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[5]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[6]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[7]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[8]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[9]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[10]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[11]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[12]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[13]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[14]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[15]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[16]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[17]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[18]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[19]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[20]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[21]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[22]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[23]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[24]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[25]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[26]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[27]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[28]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[29]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[30]);
    $dumpvars(0, reg_file_tb.u_reg_file.registers[31]);
  endtask: dumpWave

endmodule
