No submissions yet

Submit your solution to display here.

Please login/signup to submit your solution.

Testbench Code

`timescale 1ns/1ps

module tb_sr_latch_nor;
    // Inputs (1)
    reg S, R;
    // Outputs (2)
    wire Q, Qn;
    // Expected outputs (3) — prefixed "expected_"
    reg  expected_Q, expected_Qn;
    // Mismatch (4) — HIGH when outputs != expected
    wire mismatch;

    // Instantiate DUT
    sr_latch_nor dut(.S(S), .R(R), .Q(Q), .Qn(Qn));

    // Mismatch definition (ordered compare, 4-state aware)
    assign mismatch = ({Q, Qn} !== {expected_Q, expected_Qn});

    // Counters / limits
    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;

    // VCD selection counter
    integer vcd_count = 0;

    // Loop indices
    integer i, j;

    // VCD — start at #0; dump only selected signals in fixed order
    initial begin
        $dumpfile("tb_sr_latch_nor.vcd");
        // Order: 1) Inputs 2) Outputs 3) Expected 4) Mismatch
        $dumpvars(0,
            tb_sr_latch_nor.S,
            tb_sr_latch_nor.R,
            tb_sr_latch_nor.Q,
            tb_sr_latch_nor.Qn,
            tb_sr_latch_nor.expected_Q,
            tb_sr_latch_nor.expected_Qn,
            tb_sr_latch_nor.mismatch
        );
        $dumpoff;
    end

    // Golden next-state function
    function [1:0] next_state;
        input s_val, r_val;
        input cur_Q, cur_Qn;
        reg [1:0] nxt;
    begin
        nxt = {cur_Q, cur_Qn};
        if (s_val && r_val)       nxt = 2'b01; // deterministic reset
        else if (s_val && !r_val) nxt = 2'b10; // set
        else if (!s_val && r_val) nxt = 2'b01; // reset
        next_state = nxt;
    end
    endfunction

    // Named test case executor
    task apply_and_check;
        input [127:0] tc_name;
        input s_val, r_val;
        reg   [1:0]   nxt;
    begin
        if (vcd_count < VCD_MAX_CASES) $dumpon;

        S = s_val;
        R = r_val;
        nxt = next_state(s_val, r_val, expected_Q, expected_Qn);
        {expected_Q, expected_Qn} = nxt;

        #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) begin
                $display("[FAIL] %0s  S=%b R=%b  Q=%b Qn=%b  expected_Q=%b expected_Qn=%b  t=%0t",
                         tc_name, S, R, Q, Qn, expected_Q, expected_Qn, $time);
            end
        end

        if (vcd_count < VCD_MAX_CASES) begin
            vcd_count = vcd_count + 1;
            $dumpoff;
        end
    end
    endtask

    // Small “truth table” (single-step next-state from current state)
    task print_truth_table;
        reg curQ, curQn;
        reg [1:0] nxt;
        integer s, r;
    begin
        curQ  = expected_Q;
        curQn = expected_Qn;
        $display("Truth table (from current state Q=%b/Qn=%b):", curQ, curQn);
        $display(" S R | EXP_Q EXP_Qn");
        $display("--------------------");
        for (s=0; s<2; s=s+1) begin
            for (r=0; r<2; r=r+1) begin
                nxt = next_state(s[0], r[0], curQ, curQn);
                $display(" %0d %0d |   %0d     %0d", s, r, nxt[1], nxt[0]);
            end
        end
    end
    endtask

    initial begin
        // Establish known state via Reset then Hold
        {S, R} = 2'b01; {expected_Q, expected_Qn} = 2'b01; #1;
        {S, R} = 2'b00; #1;

        // Directed tests (meaningful names)
        apply_and_check("set",              1'b1, 1'b0);
        apply_and_check("hold_after_set",   1'b0, 1'b0);
        apply_and_check("reset",            1'b0, 1'b1);
        apply_and_check("hold_after_reset", 1'b0, 1'b0);
        apply_and_check("illegal_to_reset", 1'b1, 1'b1);
        apply_and_check("hold_after_illeg", 1'b0, 1'b0);
        apply_and_check("set_again",        1'b1, 1'b0);
        apply_and_check("final_hold",       1'b0, 1'b0);

        // Exhaustive two-step transitions (16 total), named by vectors
        for (i=0; i<4; i=i+1) begin
            apply_and_check({"prev_", 8'h30+i[7:0]}, i[1], i[0]);
            for (j=0; j<4; j=j+1) begin
                apply_and_check({"next_", 8'h30+j[7:0]}, j[1], j[0]);
            end
        end

        // Random stress (names “rand_XX”)
        for (i=0; i<100; i=i+1) begin
            apply_and_check({"rand_", i[7:0]}, $random, $random);
        end

        // Print compact truth table (small input space)
        print_truth_table();

        // Final 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");

        #2 $finish;
    end
endmodule