// Free-running ring oscillator built from LCELL buffers so synthesis keeps every stage. // Three evenly spaced taps are XORed into an "enhanced" output at three times the ring // frequency, which triples the chance that a sample lands on a jittery edge. module ring_osc #( parameter LENGTH = 12 // stages in the ring; exactly one of them inverts ) ( input wire enable, // low stops the ring (all stages settle high) output wire first_tap, output wire enhanced ); `ifdef SIM // Behavioural stand-in: independent taps toggling at random intervals, enough to // exercise the synchronous logic downstream. It has no physical meaning. reg [2:0] taps = 3'b000; always begin #(1 + {$random} % 7); if (enable) taps[{$random} % 3] = ~taps[{$random} % 3]; else taps = 3'b111; end assign first_tap = taps[0]; assign enhanced = ^taps; `else // No keep attribute here: each lcell is already one logic cell, and keep on these // nets makes Quartus insert a second cell per stage. wire [LENGTH-1:0] stage; lcell inverting_stage (.in(~(stage[LENGTH-1] & enable)), .out(stage[0])); genvar i; generate for (i = 1; i < LENGTH; i = i + 1) begin : delay_stage lcell buffer (.in(stage[i-1]), .out(stage[i])); end endgenerate (* keep *) wire tap_xor = stage[0] ^ stage[LENGTH/3] ^ stage[(2*LENGTH)/3]; assign first_tap = stage[0]; assign enhanced = tap_xor; `endif endmodule