Search code examples
veriloghdl

Why output is in unknown state?


I want to make a serial comparator using a dff with async reset base on this circuit with continuous assignment. but output will come in unknown (x) state I don't know why. I checked every wire and assigned each of them an expression

dff code (verilog):

module comparator (input a, input b, input reset, input clk, output [1:0] o);

wire q0_p, q0_n, q1_p, q1_n, d0, d1;
wire s0, r0, w01, w02, s1, r1, w11, w12;

assign d0 = (q1_n & q0_p) | (q0_p & ~a & b) | (q1_n & ~a & b);
assign d1 = (q1_p & q0_n) | (q0_n & a & ~b) | (q1_p & a & ~b); 

assign w01 = ~(w02 & s0);
assign s0 = ~(w01 & reset & clk);
assign r0 = ~(s0 & clk & w02);
assign w02 = ~(r0 & d0 & reset);
assign q0_p = ~(s0 & q0_n);
assign q0_n = ~(q0_p & r0 & reset);

assign w11 = ~(w12 & s1);
assign s1 = ~(w11 & reset & clk);
assign r1 = ~(s1 & clk & w12);
assign w12 = ~(r1 & d1 & reset);
assign q1_p = ~(s1 & q1_n);
assign q1_n = ~(q1_p & r1 & reset);

assign o[0] = q0_p;
assign o[1] = q1_p;

endmodule

testbench:

module test();

reg a, b, reset, clk = 0;
wire [1:0] o;

comparator cmp(a, b, reset, clk, o);

always #1 clk <= ~clk;

initial begin
  $monitor("%b    %b    %b", a, b, o);

  reset = 0;
  reset = 1;

  // a = 1110, b = 1011
  #1 a = 1; b = 1;
  #1 a = 1; b = 0;
  #1 a = 1; b = 1;
  #1 a = 0; b = 1;

  $finish();
end

endmodule

output:

1    1    xx
1    0    xx
1    1    xx
0    1    xx

Solution

  • if 'D' is in 'x' state, as soon as you deassert reset, the outputs will become 'x' again. You need to set a known value to 'D' before deassert. Also, you need a delay between assert and deassert of reset.

    For example,

    initial begin
      $monitor("%b    %b    %b", a, b, o);
    
      reset = 0;
      #1
      a = 0; b = 0;
      reset = 1;
    
      ...