Search code examples
undefinedverilogsystem-verilogicarus

Ring oscillator in Verilog/SystemVerilog - supressing undefined states


It is quite straightforward to write ring oscillator in Verilog. It is also known that in reality regardless of initial state it will work reliably in real hardware, both in FPGA and ASIC form (if it's not optimized away).

But Verilog model without reset circuit (which is not needed in real implementation) will not work, as it will be plagued by undefined states.

Is it possible to suppress undefined states and make it work reliably in Verilog without making more complicated physical implementation (i.e. without adding reset)? I am simulating in Icarus Verilog, and silicon implementation is openlane.

Here I am trying to use SystemVerilog bit type and presetting initial value - but it all does not work. I still have rotating X states in simulation. Shifter[] has 1's - to make sure it's not optimized away.

wire bit c1_1 = 0;
wire bit c1_2 = 0;
wire bit c1_3 = 0;
assign #10 c1_1 = c1_3 ^ shifter[0];
assign #11 c1_2 = c1_1 ^ shifter[1];
assign #12 c1_3 = c1_2 ^ shifter[2];

Solution

  • In verilog the statement like wire bit c1_1 = 0; is equivalent to

    wire bit c1_1;
    assign c1_1 = 0;
    

    so, essentially you are driving c1_1 with two drivers, which causes the value 'x' being assign to it if the values are different.

    Also, the driver you created is definitely not synthesizable due to use of delays. You should employ a clock instead. But... for non-synthesizable code you can easily switch to registers and use an initial block, something like the following:

      reg r1, r2, r3;
      wire c1_1, c1_2, c1_3;
      
      initial begin
        r3 = 0; // initialize r3, assuming that shifter becomes non-x until first #10
        forever begin
          #10 r1 = r3 ^ shifter[0];
          #11 r2 = r1 ^ shifter[1];
          #12 r3 = r2 ^ shifter[2];
        end
      end
      
      assign c1_1 = r1, c1_2 = r2, c1_3 = r3;
    

    assuming that shifter is not 'x', at time 10, it should generate non-'x' values.