module frequency_measure (
input wire sys_clk ,
input wire sys_rst_n ,
input wire test_clk ,
output reg [19:00] frequency
); // 输出信号,应该在sys_clk时钟域下
// 频率,单位是 Khz 0Khz ~ 50_000Khz // 最高50Mhz
parameter TIME_250MS = 24'd12_500_000 ; // 0.25秒
parameter FS = 27'd100_000_000 ; // 100Mhz
// 获取 X
reg [30:00] cnt_gate_s ; // 1.25秒计时器,在sys_clk下。
reg gate_s ; // 1秒钟的闸门信号,在sys_clk下。
reg gate_a ; // 闸门信号的同步信号,在test_clk下。
reg [25:00] cnt_test_clk ; // 对gate_a 计数,在test_clk下。
reg gate_a_reg_test ; // 对gate_a 打拍,在test_clk下。
(* keep *) wire test_clk_gate_nege ; // 闸门信号的下降沿检测,用于计数器的最终值采集。
reg [25:00] cnt_test_clk_reg ; // 计数器的最终值采集.
// 获取 Y
wire stand_clk ; // 100Mhz标准时钟,通过pll产生。
wire stand_locked ;
reg [26:00] cnt_stand_clk_gate_a ; // 1秒种的闸门信号gate_a内,在100Mhz下的计数。
reg stand_clk_gate_a_reg ; // 在stand_clk下,对gate_a打拍。
(* keep *) wire stand_clk_gate_nege ; // 闸门信号的下降沿检测,用于计数器的最终值采集。
reg [26:00] cnt_stand_clk_reg ; // 对cnt_stand_clk_gate_a 最终值采样。
// 计算标志
reg calc_flag ; // test_clk_gate_nege == 1'b1 在 test_clk下
// reg [30:00] cnt_gate_s ; // 1.25秒计时器,在sys_clk下。
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
cnt_gate_s <= 31'd0 ;
end else begin
if(cnt_gate_s == TIME_250MS * 6 - 1'b1) begin
cnt_gate_s <= 31'd0 ;
end else begin
cnt_gate_s <= cnt_gate_s + 1'b1 ;
end
end
end
// reg gate_s ; // 1秒钟的闸门信号,在sys_clk下。
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
gate_s <= 1'b0 ;
end else begin
if(((cnt_gate_s >= 0) && (cnt_gate_s <= TIME_250MS - 1'b1)) ||
((cnt_gate_s >= TIME_250MS * 5) && (cnt_gate_s <= TIME_250MS * 6 - 1'b1))) begin
gate_s <= 1'b0 ;
end else begin
if((cnt_gate_s >= TIME_250MS) && (cnt_gate_s <= TIME_250MS * 5 - 1'b1)) begin
gate_s <= 1'b1 ;
end else begin
gate_s <= gate_s ;
end
end
end
end
// reg gate_a ; // 闸门信号的同步信号,在test_clk下。
always @(posedge test_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
gate_a <= 1'b0 ;
end else begin
gate_a <= gate_s ;
// if(gate_s == 1'b1) begin
// gate_a <= 1'b1 ;
// end else begin
// gate_a <= 1'b0 ;
// end
end
end
// reg [25:00] cnt_test_clk ; // 对gate_a 计数,在test_clk下。
always @(posedge test_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
cnt_test_clk <= 26'd0 ;
end else begin
if(gate_a == 1'b1) begin
cnt_test_clk <= cnt_test_clk +1'b1 ;
end else begin
cnt_test_clk <= 26'd0 ;
end
end
end
// reg gate_a_reg_test ; // 对gate_a 打拍,在test_clk下。
always @(posedge test_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
gate_a_reg_test <= 1'b0 ;
end else begin
gate_a_reg_test <= gate_a ;
end
end
// wire test_clk_gate_nege ; // 闸门信号的下降沿检测。
assign test_clk_gate_nege = (gate_a == 1'b0 && gate_a_reg_test == 1'b1) ? 1'b1 : 1'b0 ;
// reg [25:00] cnt_test_clk_reg ; // 计数器的最终值采集.
always @(posedge test_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
cnt_test_clk_reg <= 26'd0 ;
end else begin
if(test_clk_gate_nege == 1'b1) begin
cnt_test_clk_reg <= cnt_test_clk ;
end else begin
cnt_test_clk_reg <= cnt_test_clk_reg ;
end
end
end
// 产生标准时钟
// wire stand_clk ; // 100Mhz标准时钟,通过pll产生。
pll_100mhz pll_100mhz_inst (
.areset ( ~sys_rst_n ),
.inclk0 ( sys_clk ),
.c0 ( stand_clk ),
.locked ( stand_locked )
);
// reg [26:00] cnt_stand_clk_gate_a ; // 1秒种的闸门信号gate_a内,在100Mhz下的计数。
always @(posedge stand_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
cnt_stand_clk_gate_a <= 26'd0 ;
end else begin
if(gate_a == 1'b1) begin
cnt_stand_clk_gate_a <= cnt_stand_clk_gate_a + 1'b1 ;
end else begin
cnt_stand_clk_gate_a <= 37'd0 ;
end
end
end
// reg stand_clk_gate_a_reg ; // 在stand_clk下,对gate_a打拍。
always @(posedge stand_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
stand_clk_gate_a_reg <= 1'b0 ;
end else begin
stand_clk_gate_a_reg <= gate_a ;
end
end
// wire stand_clk_gate_nege ; // 闸门信号的下降沿检测。
assign stand_clk_gate_nege = (gate_a == 1'b0) && (stand_clk_gate_a_reg == 1'b1) ? 1'b1 : 1'b0 ;
// reg [26:00] cnt_stand_clk_reg ; // 对cnt_stand_clk_gate_a 最终值采样。
always @(posedge stand_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
cnt_stand_clk_reg <= 26'd0 ;
end else begin
if(stand_clk_gate_nege == 1'b1) begin
cnt_stand_clk_reg <= cnt_stand_clk_gate_a ;
end else begin
cnt_stand_clk_reg <= cnt_stand_clk_reg ;
end
end
end
// 计算标志
// reg calc_flag ; // test_clk_gate_nege == 1'b1 在 test_clk下
always @(posedge test_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
calc_flag <= 1'b0 ;
end else begin
if(test_clk_gate_nege == 1'b1) begin
calc_flag <= 1'b1 ;
end else begin
calc_flag <= 1'b0 ;
end
end
end
// out signal
// [19:00] frequency
always @(posedge test_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
frequency <= 20'd0 ;
end else begin
if(calc_flag == 1'b1) begin
frequency <= ((cnt_test_clk_reg / 1000 ) * (FS / cnt_stand_clk_reg));
// frequency <= (cnt_test_clk_reg * FS ) / (cnt_stand_clk_reg * 1000) ; 会出错
end else begin
frequency <= frequency ;
end
end
end
endmodule
module top(
input wire sys_clk ,
input wire sys_rst_n ,
input wire test_clk ,
output wire test_clk_out,
output wire ds ,
output wire oe ,
output wire shcp ,
output wire stcp
);
// 例化间连线
wire [19:00] frequency_w ;
wire locked_sig ;
wire [05:00] point ;
assign point = 6'b001000 ;
wire sign ;
assign sign = 1'b0 ;
wire seg_en ;
assign seg_en = 1'b1 ;
// frequency_measure
frequency_measure frequency_measure_insert (
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.test_clk ( test_clk ) ,
.frequency ( frequency_w )
);
// 输出待测频率
pll_32mhz pll_32mhz_inst (
.areset ( ~sys_rst_n ) ,
.inclk0 ( sys_clk ) ,
.c0 ( test_clk_out ) ,
.locked ( locked_sig )
);
// 数码管静态显示模块
seg_595_dynamic seg_595_dynamic_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.data ( frequency_w ) ,
.point ( point ) ,
.sign ( sign ) ,
.seg_en ( seg_en ) ,
.ds ( ds ) ,
.oe ( oe ) ,
.shcp ( shcp ) ,
.stcp ( stcp )
);
endmodule
数码管模块,就是之前工程里的。
`timescale 1ns/1ns
module test_frequency_measure();
reg sys_clk ;
reg sys_rst_n ;
wire test_clk ;
wire locked_sig ;
wire [19:00] frequency ;
defparam frequency_measure_insert.TIME_250MS = 1250 ; // 0.25秒
defparam frequency_measure_insert.FS = 1000000 ; // 100Mhz
// Instantiation
pll_32mhz pll_32mhz_inst (
.areset ( ~sys_rst_n ),
.inclk0 ( sys_clk ),
.c0 ( test_clk ),
.locked ( locked_sig )
);
frequency_measure frequency_measure_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.test_clk ( test_clk ) ,
.frequency ( frequency )
);
parameter CYCLE = 20 ;
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( 210 ) ;
sys_rst_n <= 1'b0 ;
#( 10 ) ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( CYCLE * 1000 ) ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule
`timescale 1ns/1ns
module test_top();
reg sys_clk ;
reg sys_rst_n ;
wire test_clk ; // 有pll32mhz产生。
wire test_clk_out;
wire ds ;
wire oe ;
wire shcp ;
wire stcp ;
wire locked_sig ;
defparam top_insert.frequency_measure_insert.TIME_250MS = 1250 ; // 0.25秒
defparam top_insert.frequency_measure_insert.FS = 1000000 ; // 100Mhz
// Instantiation
pll_32mhz pll_32mhz_inst_test (
.areset ( ~sys_rst_n ),
.inclk0 ( sys_clk ),
.c0 ( test_clk ),
.locked ( locked_sig )
);
top top_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.test_clk ( test_clk ) ,
.test_clk_out ( test_clk_out ) ,
.ds ( ds ) ,
.oe ( oe ) ,
.shcp ( shcp ) ,
.stcp ( stcp )
);
parameter CYCLE = 20 ;
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( 210 ) ;
sys_rst_n <= 1'b0 ;
#( 10 ) ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( CYCLE * 1000 ) ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule