No submissions yet

Submit your solution to display here.

Please login/signup to submit your solution.

Testbench Code

// tb_rise_pulse.v
`timescale 1ns/1ps
module tb_rise_pulse;
  // -------------------------
  // Inputs
  // -------------------------
  reg clk;
  reg rst;
  reg sig_in;

  // -------------------------
  // Outputs (DUT)
  // -------------------------
  wire pulse;

  // -------------------------
  // Expected outputs (golden)
  // -------------------------
  wire expected_pulse;

  // -------------------------
  // Mismatch
  // -------------------------
  wire mismatch;

  // DUT
  rise_pulse dut(.clk(clk), .rst(rst), .sig_in(sig_in), .pulse(pulse));

  // Golden model: same equations as DUT, evaluated on posedge clk
  reg exp_prev, exp_pulse_q;
  assign expected_pulse = exp_pulse_q;

  always @(posedge clk) begin
    exp_pulse_q <= rst ? 1'b0 : ((~exp_prev) & sig_in);
    exp_prev    <= rst ? 1'b0 : sig_in;
  end

  assign mismatch = (pulse !== expected_pulse);

  // -------------------------
  // Clock (10 ns period)
  // -------------------------
  initial begin
    clk = 1'b0;
    forever #5 clk = ~clk;
  end

  // -------------------------
  // VCD: ONLY inputs, outputs, expected, mismatch (in order)
  // -------------------------
  initial begin
    $dumpfile("tb_rise_pulse.vcd");
    $dumpvars(0,
      clk, rst, sig_in,     // 1) Inputs
      pulse,                // 2) Outputs
      expected_pulse,       // 3) Expected Outputs
      mismatch              // 4) Mismatch
    );
  end

  // -------------------------
  // Helpers
  // -------------------------
  task apply_cycles;
    input integer n;
    begin
      repeat (n) @(posedge clk);
    end
  endtask

  // Change input away from posedge to avoid races
  task set_sig_in;
    input val;
    begin
      @(negedge clk); sig_in = val;
    end
  endtask

  // Create a glitch fully between two posedges (should be ignored)
  task short_glitch_between_edges;
    begin
      // assume we are somewhere after a posedge
      #1  sig_in = 1'b1;   // go high briefly
      #3  sig_in = 1'b0;   // back low well before next posedge
    end
  endtask

  // -------------------------
  // Accounting & checker
  // -------------------------
  integer TOTAL_TEST_CASES, TOTAL_PASSED_TEST_CASES, TOTAL_FAILED_TEST_CASES;
  reg [8*48-1:0] TC_NAME;

  task check_case;
    input [8*48-1:0] name;
    begin
      TC_NAME = name;
      #1; // sample after last posedge activity
      $display("CASE=%s : sig_in=%0b | pulse=%0b expected_pulse=%0b %s",
               TC_NAME, sig_in, pulse, expected_pulse,
               mismatch ? "MISMATCH" : "OK");
      TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
      if (!mismatch) TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
      else begin
        TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
        $display("  FAILED INPUTS: sig_in=%0b | EXPECTED: expected_pulse=%0b",
                 sig_in, expected_pulse);
      end
      apply_cycles(1); // spacing on waveform
    end
  endtask

  // -------------------------
  // Stimulus (≤ 10 selected scenarios)
  // -------------------------
  initial begin
    TOTAL_TEST_CASES = 0; TOTAL_PASSED_TEST_CASES = 0; TOTAL_FAILED_TEST_CASES = 0;

    // Power-on reset
    rst = 1'b1; sig_in = 1'b0; apply_cycles(1);
    rst = 1'b0; apply_cycles(1);
    check_case("after_reset_no_pulse");

    // 1) Idle low → no pulse
    set_sig_in(1'b0); apply_cycles(2);
    check_case("idle_low_no_pulse");

    // 2) Rising edge → exactly one pulse
    set_sig_in(1'b1); apply_cycles(1);     // posedge sees 0->1
    check_case("rising_edge_single_pulse");

    // 3) Hold high → no extra pulses
    apply_cycles(3);
    check_case("hold_high_no_extra_pulse");

    // 4) Falling edge → no pulse
    set_sig_in(1'b0); apply_cycles(1);
    check_case("falling_edge_no_pulse");

    // 5) Another rising edge → another single pulse
    set_sig_in(1'b1); apply_cycles(1);
    check_case("second_rising_edge_pulse");

    // 6) Short glitch fully between posedges → ignored
    set_sig_in(1'b0); // ensure low
    @(negedge clk);
    short_glitch_between_edges(); // high then low before next posedge
    @(posedge clk);
    check_case("short_glitch_ignored");

    // 7) Rapid toggling every cycle → pulses on every 0->1 sample
    set_sig_in(1'b0); apply_cycles(1);
    set_sig_in(1'b1); apply_cycles(1); check_case("toggle_0_to_1_pulse");
    set_sig_in(1'b0); apply_cycles(1); check_case("toggle_1_to_0_no_pulse");
    set_sig_in(1'b1); apply_cycles(1); check_case("toggle_again_pulse");

    // 8) Synchronous reset during run → clears pulse/state
    rst = 1'b1; apply_cycles(1);
    rst = 1'b0; apply_cycles(1);
    check_case("sync_reset_clears_state");

    // Summary
    $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