mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
123 lines
2.8 KiB
Systemverilog
123 lines
2.8 KiB
Systemverilog
//------------------------------------------------------------------------------
|
|
// 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
|
|
|