48 lines
1.5 KiB
Coq
48 lines
1.5 KiB
Coq
|
|
// Measures a ring frequency: an 8-bit prescaler clocked by the ring itself divides it by
|
||
|
|
// 256, and its top bit's rising edges are counted in the clk domain over a gate of
|
||
|
|
// 2^GATE_BITS clk cycles. frequency = count * 256 * f_clk / 2^GATE_BITS.
|
||
|
|
module freq_counter #(
|
||
|
|
parameter GATE_BITS = 24 // 2^24 cycles at 120 MHz = 140 ms
|
||
|
|
) (
|
||
|
|
input wire clk,
|
||
|
|
input wire reset,
|
||
|
|
input wire signal, // asynchronous signal to measure (used as a clock)
|
||
|
|
input wire start,
|
||
|
|
output reg busy,
|
||
|
|
output reg valid,
|
||
|
|
output reg [31:0] count
|
||
|
|
);
|
||
|
|
|
||
|
|
reg [7:0] prescaler = 8'd0;
|
||
|
|
always @(posedge signal) prescaler <= prescaler + 8'd1;
|
||
|
|
|
||
|
|
// The SDC file cuts timing from prescaler into this synchronizer.
|
||
|
|
reg [2:0] divided_history;
|
||
|
|
always @(posedge clk) divided_history <= {divided_history[1:0], prescaler[7]};
|
||
|
|
wire divided_rising = (divided_history[2:1] == 2'b01);
|
||
|
|
|
||
|
|
reg [GATE_BITS-1:0] gate;
|
||
|
|
reg [31:0] edges;
|
||
|
|
|
||
|
|
always @(posedge clk) begin
|
||
|
|
if (reset) begin
|
||
|
|
busy <= 1'b0;
|
||
|
|
valid <= 1'b0;
|
||
|
|
end else if (start) begin
|
||
|
|
busy <= 1'b1;
|
||
|
|
valid <= 1'b0;
|
||
|
|
gate <= {GATE_BITS{1'b0}};
|
||
|
|
edges <= 32'd0;
|
||
|
|
end else if (busy) begin
|
||
|
|
gate <= gate + 1'b1;
|
||
|
|
if (divided_rising) edges <= edges + 32'd1;
|
||
|
|
if (&gate) begin
|
||
|
|
busy <= 1'b0;
|
||
|
|
valid <= 1'b1;
|
||
|
|
count <= edges + divided_rising;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
endmodule
|