strix/fpga/rtl/ring_bank.v

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