Search code examples
verilogtest-bench

Use testbench to check module but output does not change when I use other input


I wrote simple code to check if the module function is correct or not.

I tried to input 4 different inputs to check the module's output, but the output is always the first input's result. I have no idea why it is happened.

The following is my module:

module encoder (
input [3:0] in,
output reg [2:0] pos  );
always @(*) begin
    casez (in)
        4'bzzz1: pos = 1;
        4'bzz1z: pos = 2;
        4'bz1zz: pos = 3;
        4'b1zzz: pos = 4;
        default: pos = 0;
    endcase
end
endmodule

I use the following testbench:

module  main();
reg [3:0] in;
wire [2:0] pos;

encoder e(in,pos);

initial begin

#5 in = 4'bzzz1;
#5 in = 4'bzz1z;
#5 in = 4'bz1zz;
#5 in = 4'b1zzz;
#20;
$finish;
end

initial $monitor($time,"in=%b, pos=%b",in ,pos);

endmodule

But, pos always prints 001 when I simulate it.

The following is what I expect it to print:

0 in=XXXX, pos=XXX
5 in=zzz1, pos=001
5 in=zz1z, pos=010
5 in=z1zz, pos=011
5 in=1zzz, pos=100

May someone tell me where I am wrong?


Solution

  • When I run your code, I get this output:

                   0in=xxxx, pos=xxx
                   5in=zzz1, pos=001
                  10in=zz1z, pos=001
                  15in=z1zz, pos=001
                  20in=1zzz, pos=001
    

    pos is always 1 because the 1st case item always matches your input value (in). This is due to the z bits in your input and the z bits in your case items.

    Refer to IEEE Std 1800-2017, section 12.5.1 Case statement with do-not-cares:

    Do-not-care values ( z values for casez , z and x values for casex ) in any bit of either the case_expression or the case_items shall be treated as do-not-care conditions during the comparison, and that bit position shall not be considered.

    The case statement starts by checking the case_expression (in) against the 1st case_item, which is 4'bzzz1. For the comparison, since bit 0 of the case_item is 1, the comparison will always match no matter what the value of in[0] is. No other case_item comparisons are ever done.

    If I change casez to case, then I get the expected output:

                   0in=xxxx, pos=xxx
                   5in=zzz1, pos=001
                  10in=zz1z, pos=010
                  15in=z1zz, pos=011
                  20in=1zzz, pos=100
    

    However, I don't think this is what you want. It is not customary to drive inputs with z bits. It is more customary to drive known values. This should work better for you:

    module encoder (
        input [3:0] in,
        output reg [2:0] pos
    );
    
        always @(*) begin
            casez (in)
                4'b???1: pos = 1;
                4'b??1?: pos = 2;
                4'b?1??: pos = 3;
                4'b1???: pos = 4;
                default: pos = 0;
            endcase
        end
    endmodule
    
    module main;
        reg  [3:0] in;
        wire [2:0] pos;
    
        encoder e (in, pos);
    
        initial begin
            $monitor($time,, "in=%b, pos=%d", in, pos);
            repeat (30) #5 in = $random;
            #20 $finish;
        end
    endmodule
    

    Prints:

                   0 in=xxxx, pos=x
                   5 in=0100, pos=3
                  10 in=0001, pos=1
                  15 in=1001, pos=1
                  20 in=0011, pos=1
                  25 in=1101, pos=1
                  35 in=0101, pos=1
                  40 in=0010, pos=2
                  45 in=0001, pos=1
                  50 in=1101, pos=1
                  55 in=0110, pos=2
                  60 in=1101, pos=1
                  70 in=1100, pos=3
                  75 in=1001, pos=1
                  80 in=0110, pos=2
                  85 in=0101, pos=1
                  90 in=1010, pos=2
                  95 in=0101, pos=1
                 100 in=0111, pos=1
                 105 in=0010, pos=2
                 110 in=1111, pos=1
                 115 in=0010, pos=2
                 120 in=1110, pos=2
                 125 in=1000, pos=4
                 130 in=0101, pos=1
                 135 in=1100, pos=3
                 140 in=1101, pos=1
                 150 in=0101, pos=1
    

    In the casez case items, it is more common to use ? instead of z, although either will work.