No submissions yet

Submit your solution to display here.

Please login/signup to submit your solution.

Testbench Code

`timescale 1ns/1ps
module tb_led_blinker;
  reg clk;
  reg rst;

  wire led;
  wire expected_led;
  wire mismatch;

  localparam integer TB_COUNTER_WIDTH = 2;
  localparam integer TB_TOGGLE_EVERY  = 3;

  led_blinker #(
    .COUNTER_WIDTH(TB_COUNTER_WIDTH),
    .TOGGLE_EVERY(TB_TOGGLE_EVERY)
  ) dut (
    .clk(clk), .rst(rst), .led(led)
  );

  reg [TB_COUNTER_WIDTH-1:0] exp_cnt;
  reg                        exp_led_q;
  assign expected_led = exp_led_q;

  always @(posedge clk) begin
    if (rst) begin
      exp_led_q <= 1'b0;
      exp_cnt   <= {TB_COUNTER_WIDTH{1'b0}};
    end else begin
      if (exp_cnt == TB_TOGGLE_EVERY-1) begin
        exp_led_q <= ~exp_led_q;
        exp_cnt   <= {TB_COUNTER_WIDTH{1'b0}};
      end else begin
        exp_cnt   <= exp_cnt + {{(TB_COUNTER_WIDTH-1){1'b0}},1'b1};
      end
    end
  end

  assign mismatch = (led !== expected_led);

  initial begin
    clk = 1'b0;
    forever #5 clk = ~clk;
  end

  initial begin
    @(posedge clk);
    $dumpfile("tb_led_blinker.vcd");
    $dumpvars(0,
      clk, rst,            // 1) Inputs
      led,                 // 2) Outputs
      expected_led,        // 3) Expected Outputs
      mismatch             // 4) Mismatch
    );
  end

  task apply_cycles;
    input integer n; integer i;
    begin for (i=0;i<n;i=i+1) @(posedge clk); end
  endtask

  integer TOTAL_TEST_CASES, TOTAL_PASSED_TEST_CASES, TOTAL_FAILED_TEST_CASES;

  task run_window;
    input integer cycles;
    input [8*48-1:0] name;
    integer i; reg case_failed;
    begin
      case_failed = 0;
      for (i=0; i<cycles; i=i+1) begin
        @(posedge clk);
        if (mismatch) case_failed = 1;
      end
      $display("CASE=%s : %s", name, case_failed ? "MISMATCH" : "OK");
      TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
      if (!case_failed) TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
      else TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
      apply_cycles(1);
    end
  endtask

  initial begin
    rst       = 1'b1;
    exp_cnt   = {TB_COUNTER_WIDTH{1'b0}};
    exp_led_q = 1'b0;

    apply_cycles(4);
    @(negedge clk) rst = 1'b0;

    TOTAL_TEST_CASES = 0; TOTAL_PASSED_TEST_CASES = 0; TOTAL_FAILED_TEST_CASES = 0;

    run_window(TB_TOGGLE_EVERY-1, "no_toggle_before_first");
    run_window(1,                  "toggle_at_first_count");
    run_window(TB_TOGGLE_EVERY,    "next_toggle_after_interval");

    @(negedge clk) rst = 1'b1;
    apply_cycles(2);
    @(negedge clk) rst = 1'b0;
    run_window(TB_TOGGLE_EVERY,    "post_reset_first_toggle");

    $display("TOTAL_TEST_CASES=%0d",        TOTAL_TEST_CASES);
    $display("TOTAL_PASSED_TEST_CASES=%0d", TOTAL_PASSED_TEST_CASES);
    $display("TOTAL_FAILED_TEST_CASES=%0d", TOTAL_FAILED_TEST_CASES);
    $display("ALL_TEST_CASES_PASSED=%s",    (TOTAL_FAILED_TEST_CASES==0) ? "true" : "false");

    $finish;
  end
endmodule