CounterTestbench

Modified

2025-11-11

Source: Lab4/Lab44/CounterTestbench.sv (modified 2025-11-10 08:50)

// testbench.sv - Testbench for CounterDisplay
// CounterTestbench.sv - TB for single-file CounterDisplay.sv
`timescale 1ns/1ps

module CounterTestbench;

  // DUT ports
  logic        clock;      // KEY0 (active-low button, but in sim we directly apply clock edges)
  logic        clear_n;    // KEY1, sync clear active-low
  logic [3:0]  addBy;      // SW3..SW0
  logic [6:0]  seg0;       // HEX0 (a..g), active-low

  // Visible internal "actual count value" for display purposes (inferring from seg0 is cumbersome)
  logic [3:0]  golden_cnt;

  // DUT - instantiate the top-level CounterDisplay module
  CounterDisplay dut (
    .clock(clock),
    .clear_n(clear_n),
    .addBy(addBy),
    .Seg0(seg0)
  ); 
  
  
  function automatic [3:0] seg_to_hex (input logic [6:0] s);
    case (s)
      7'b1000000: seg_to_hex = 4'h0;
      7'b1111001: seg_to_hex = 4'h1;
      7'b0100100: seg_to_hex = 4'h2;
      7'b0110000: seg_to_hex = 4'h3;
      7'b0011001: seg_to_hex = 4'h4;
      7'b0010010: seg_to_hex = 4'h5;
      7'b0000010: seg_to_hex = 4'h6;
      7'b1111000: seg_to_hex = 4'h7;
      7'b0000000: seg_to_hex = 4'h8;
      7'b0010000: seg_to_hex = 4'h9;
      7'b0001000: seg_to_hex = 4'hA;
      7'b0000011: seg_to_hex = 4'hB;
      7'b1000110: seg_to_hex = 4'hC;
      7'b0100001: seg_to_hex = 4'hD;
      7'b0000110: seg_to_hex = 4'hE;
      7'b0001110: seg_to_hex = 4'hF;
      default:     seg_to_hex = 4'hX;
    endcase
  endfunction

  // ---- Task: Simulate "pressing KEY0 once" to generate a rising edge (idle=1, press=0, release=1) ----
  task automatic press_clock();
    begin
      clock = 1'b0;   // Pull down to 0, equivalent to pressing
      #5;
      clock = 1'b1;   // Release, generating a rising edge; register samples at posedge
      #5;
    end
  endtask

  // ---- Task: Synchronous clear (active-low, needs to occur at clock rising edge) ----
  task automatic sync_clear();
    begin
      clear_n = 1'b0;  // Assert active-low
      // Clear is synchronous - give it one clock edge
      press_clock();
      clear_n = 1'b1;
      #5;
    end
  endtask

  // ---- Task: Run N steps and print/check ----
  task automatic run_steps(input [3:0] step, input int N);
    begin
      addBy = step;
      $display("---- addBy = 0x%0h, run %0d steps ----", step, N);
      repeat (N) begin
        press_clock();
        golden_cnt = (golden_cnt + step) & 4'hF;
        $display("%0t ns : count(hex from seg0) = %0h (golden=%0h)",
                 $time, seg_to_hex(seg0), golden_cnt);
      end
    end
  endtask

  // ---- Stimulus ----
  initial begin
    // Dump waveform for EPWave
    $dumpfile("dump.vcd");
    $dumpvars(0, CounterTestbench);
    
    // Default idle levels
    clock    = 1'b1;
    clear_n  = 1'b1;
    addBy    = 4'h0;
    golden_cnt = 4'h0;
    #10;

    // Synchronous clear
    sync_clear();

    // Lab specified 5 groups (0,1,7,8,F), each running 5 steps
    run_steps(4'h0, 5);
    run_steps(4'h1, 5);
    run_steps(4'h7, 5);
    run_steps(4'h8, 5);
    run_steps(4'hF, 5);

    $display("TB finished.");
    #20;
    $finish;
  end

endmodule