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