1

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?

toolic
  • 57,801
  • 17
  • 75
  • 117
余昌翰
  • 63
  • 1
  • 7

1 Answers1

0

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.

toolic
  • 57,801
  • 17
  • 75
  • 117