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