Testbench Code
`timescale 1ns/1ps
module tb_d_latch_en_sync_reset;
// 1) Inputs
reg EN, RST, D;
// 2) Outputs
wire Q;
// 3) Expected outputs
reg expected_Q;
// 4) Mismatch
wire mismatch;
d_latch_en_sync_reset dut(.EN(EN), .RST(RST), .D(D), .Q(Q));
assign mismatch = (Q !== expected_Q);
integer TOTAL_TEST_CASES = 0;
integer TOTAL_PASSED_TEST_CASES = 0;
integer TOTAL_FAILED_TEST_CASES = 0;
integer VCD_MAX_CASES = 32;
integer ERROR_MAX_CASES = 32;
integer i, j;
initial begin
$dumpfile("tb_d_latch_en_sync_reset.vcd");
$dumpvars(0,
tb_d_latch_en_sync_reset.EN,
tb_d_latch_en_sync_reset.RST,
tb_d_latch_en_sync_reset.D,
tb_d_latch_en_sync_reset.Q,
tb_d_latch_en_sync_reset.expected_Q,
tb_d_latch_en_sync_reset.mismatch
);
$dumpon;
end
function next_q;
input en_v, rst_v, d_v, cur_q;
reg n;
begin
n = cur_q;
if (en_v) begin
if (rst_v) n = 1'b0;
else n = d_v;
end
next_q = n;
end
endfunction
task apply_and_check;
input [127:0] name;
input en_v, rst_v, d_v;
reg n;
begin
EN = en_v; RST = rst_v; D = d_v;
n = next_q(en_v, rst_v, d_v, expected_Q);
expected_Q = n;
#1;
TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
if (!mismatch) begin
TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
end else begin
TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
if (TOTAL_FAILED_TEST_CASES <= ERROR_MAX_CASES)
$display("[FAIL] %0s EN=%b RST=%b D=%b Q=%b expected_Q=%b t=%0t",
name, EN, RST, D, Q, expected_Q, $time);
end
if (TOTAL_TEST_CASES == VCD_MAX_CASES) $dumpoff;
end
endtask
task print_truth_table;
integer e,r,dv;
reg curQ, nxt;
begin
curQ = expected_Q;
$display(" EN RST D | EXP_Q");
$display("-----------------");
for (e=0;e<2;e=e+1)
for (r=0;r<2;r=r+1)
for (dv=0;dv<2;dv=dv+1) begin
nxt = next_q(e[0], r[0], dv[0], curQ);
$display(" %0d %0d %0d | %0d", e, r, dv, nxt);
end
end
endtask
initial begin
EN=1'b1; RST=1'b1; D=1'b1; expected_Q=1'b0; #1;
EN=1'b1; RST=1'b0; D=1'b0; #1;
apply_and_check("reset_enabled" , 1'b1, 1'b1, 1'b1);
apply_and_check("capture_one" , 1'b1, 1'b0, 1'b1);
apply_and_check("disabled_rst" , 1'b0, 1'b1, 1'b0);
apply_and_check("disabled_hold" , 1'b0, 1'b0, 1'b1);
apply_and_check("reset_again" , 1'b1, 1'b1, 1'b0);
apply_and_check("capture_zero" , 1'b1, 1'b0, 1'b0);
for (i=0;i<8;i=i+1) begin
apply_and_check("prev_vec", i[2], i[1], i[0]);
for (j=0;j<8;j=j+1)
apply_and_check("next_vec", j[2], j[1], j[0]);
end
for (i=0;i<100;i=i+1)
apply_and_check("rand", $random, $random, $random);
print_truth_table();
$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");
#2 $finish;
end
endmodule