strix/fpga/rtl/freq_counter.v

48 lines
1.5 KiB
Coq
Raw Normal View History

// 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