1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-14 06:42:54 +08:00

Added freq_meter module

This commit is contained in:
Konstantin Pavlov 2023-12-15 00:13:23 +03:00
parent aec03d4507
commit 4eae34a978

122
freq_meter.sv Normal file
View File

@ -0,0 +1,122 @@
//------------------------------------------------------------------------------
// freq_meter.sv
// published as part of https://github.com/pConst/basic_verilog
// Konstantin Pavlov, pavlovconst@gmail.com
//------------------------------------------------------------------------------
// INFO ------------------------------------------------------------------------
// frequency meter counts how many periods of test clock happen within
// a given large time base.
// Frequency value in MHz is proportional to system clock as readout/timebase
//
/* --- INSTANTIATION TEMPLATE BEGIN ---
freq_meter fm1 (
.clk( clk ), // 62.5 MHz expected
.nrst( nrst ),
.test_clk( ),
.test_ena( ),
.readout( )
);
--- INSTANTIATION TEMPLATE END ---*/
module freq_meter (
input clk, // system clock, 62.5 MHz expected
input nrst, // reset (inversed)
input test_clk, // signal to count
input test_ena, // enable counting signal (in test_clk domain)
output [31:0] readout = '0 // number of test_clk complete cycles per
); // 1073741,824 mks time base
logic [31:0] clk_div;
clk_divider #(
.WIDTH( 32 )
) sys_cd (
.clk( clk ),
.nrst( nrst ),
.ena( 1'b1 ),
.out( )
);
// synchronizing into test frequency time domain
logic start_new_count;
delay #(
.LENGTH( 2 ),
.WIDTH( 1 )
) sstart_new_count_d_SYNC_ATTR (
.clk( test_clk ),
.nrst( 1'b1 ),
.ena( 1'b1 ),
.in( clk_div[15] ), // defines the timebase
.out( start_new_count )
);
// detecting rising edge of start condition
logic start_new_count_rise;
edge_detect start_new_count_ed (
.clk( test_clk ),
.nrst( 1'b1 ),
.in( start_new_count ),
.rising( start_new_count_rise ),
.falling( ),
.both( )
);
logic [31:0] cntr_tc = 31'b1;
logic [31:0] readout_tc = '0;
logic readout_tc_valid = 1'b0;
always_ff @(posedge test_clk) begin
if( start_new_count_rise ) begin
// every counter refreshes approx. once in a second and holds a value of
// test freq complete periods over 1073741,824 mks
readout_tc[31:0] <= cntr_tc[31:0];
readout_tc_valid <= 1'b1;
cntr_tc[31:0] <= 1;
end else if( test_ena ) begin
readout_tc_valid <= 1'b0;
cntr_tc[31:0] <= cntr_tc[31:0] + 1'b1;
end
end
// synchronizing back into clk time domain
logic readout_valid;
cdc_strobe readout_valid_tc_cdc (
.arst( 1'b0 ),
.clk1( test_clk ),
.nrst1( 1'b1 ),
.strb1( readout_tc_valid ),
.clk2( clk ),
.nrst2( nrst ),
.strb2( readout_valid )
);
always_ff @(posedge clk) begin
if( ~nrst ) begin
readout[31:0] <= '0;
end else begin
if( readout_valid ) begin
readout[31:0] <= readout_tc[31:0];
end
end
end
endmodule