// A bank of ring oscillators. Every ring's single tap and enhanced output is synchronized // into the clk domain separately, so all combining happens after sampling. Ring lengths // cycle through 9, 12 and 15 stages so neighbouring rings run at different frequencies. module ring_bank #( parameter RINGS = 16 ) ( input wire clk, input wire enable, output wire [RINGS-1:0] enhanced, // synchronized enhanced outputs output wire [RINGS-1:0] first_tap, // synchronized single taps output wire [RINGS-1:0] raw_tap // unsynchronized single taps, for frequency counting ); wire [RINGS-1:0] ring_enhanced; genvar i; generate for (i = 0; i < RINGS; i = i + 1) begin : ring ring_osc #(.LENGTH(9 + 3 * (i % 3))) osc ( .enable(enable), .first_tap(raw_tap[i]), .enhanced(ring_enhanced[i]) ); end endgenerate // sample_raw catches the asynchronous ring signals and may go metastable; // sample_sync resolves it. The SDC file cuts timing into sample_raw. reg [2*RINGS-1:0] sample_raw, sample_sync; always @(posedge clk) begin sample_raw <= {raw_tap, ring_enhanced}; sample_sync <= sample_raw; end assign enhanced = sample_sync[RINGS-1:0]; assign first_tap = sample_sync[2*RINGS-1:RINGS]; endmodule