36 lines
1.3 KiB
Verilog
36 lines
1.3 KiB
Verilog
// 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
|