一个计算频率的模块

先上代码

复制代码
module _sync_reg #(
   parameter INIT         = 0,
   parameter ASYNC_RESET  = 0
) (
   input  clk,
   input  rst,
   input  in,
   output out
);

(* ASYNC_REG = "TRUE" *) reg sync1;
(* ASYNC_REG = "TRUE" *) reg sync2;

assign out = sync2;

generate
if (ASYNC_RESET) begin
  always @(posedge clk or posedge rst) begin
    if (rst) begin
      sync1 <= INIT;
      sync2 <= INIT;
    end else begin
      sync1 <= in;
      sync2 <= sync1;
    end
  end
end else begin
  always @(posedge clk) begin
    if (rst) begin
      sync1 <= INIT;
      sync2 <= INIT;
    end else begin
      sync1 <= in;
      sync2 <= sync1;
    end
  end
end
endgenerate

endmodule

/*
 clk_estimator #( .EST_BITS ( 24 ))  clk_estimator (
    .rst(),
    .clk(),
     .meas_clk(), 
    .cntr_data()
);
*/

module clk_estimator #(
    parameter FRQ  = 100*1000*1000     
)(
    input         rst,
    input         clk, 
    input         meas_clk, 
    output reg [32-1:0] dout ,
    output  reg  update     
);
  
reg [31:0] c;
reg f  = 0 ; 
wire of = c >=    (FRQ/20) -1  ;  
always @(posedge clk) begin
  if (rst  ) begin    c <= 0;    f<=0;   end 
  else if (of)begin  f<=~f;    c<=0;   end   
  else  begin  c <= c + 1 ;end
end

wire out_dclk;

_sync_reg  self_estim(
    .clk(meas_clk),
    .rst(rst),
    .in(f),
    .out(out_dclk)
); 

reg [32-1:0] cntr_clk;
reg [32-1:0] ref_cntr_data_r; 
reg prev_out_dclk;
reg update_w ; 


always @(posedge meas_clk) begin
  if (rst) begin
      update_w <=0;
    cntr_clk        <= 0;
    prev_out_dclk   <= 0;
    ref_cntr_data_r <= 0; 
  end else begin
    prev_out_dclk   <= out_dclk; 
    if (prev_out_dclk == 0 && out_dclk == 1'b1) begin
      cntr_clk        <= 0;
      ref_cntr_data_r <= cntr_clk;
      update_w <=1; 
    end else begin
      cntr_clk        <= cntr_clk + 1'b1;
      update_w <=0;
    end
  end
end


(* ASYNC_REG = "TRUE" *)  reg [4:0]  updater; always @ (posedge clk )  updater <= { updater[3:0], update_w };
(* ASYNC_REG = "TRUE" *)  reg[31:0] r; reg[31:0] rr,rrr,rrrr;

  always @ (posedge clk )  rrrr<=rrr;
  always @ (posedge clk )  rrr<=rr;
  always @ (posedge clk )  rr<=r;
  always @ (posedge clk )  r<=ref_cntr_data_r;
  
reg [31:0]watch_dog_cntr ;

wire update1=   updater[4:3] == 2'b01   ; 

always @ (posedge clk ) if ( update1 | rst )watch_dog_cntr<=0; else   watch_dog_cntr<= ( watch_dog_cntr>= FRQ/4 )?0: (watch_dog_cntr+1);
wire watch_dog_act =  watch_dog_cntr >= FRQ/4 ;

  always @ (posedge clk ) if (watch_dog_act) dout <= 0 ;else if (update1) dout<=  rrrr ;
  always @ (posedge clk )  update <= watch_dog_act ==1 ||   update1  ==1  ;
  
endmodule

当外部meas_clk有频率信号接入时,每1/10秒就会输出更新一下时钟计数,这里的计数是输入meas_clk的1/10。如果没有频率接入每1/4秒输出一下结果0。

原理是我们已知频率为FRQ的时钟clk每1/20秒翻转一次,这样得到的每次上升边缘就是1/0秒。被测试的时钟meas_clk在1/10秒内数数,数到到多少,之后再传到clk时钟域,输出出来。另外设置了1/4秒的看门狗,当时meas_clk丢失,超过1/4秒没有更新,就触犯看门狗电路自动更新输出0.

这个代码实验通过了,非常好用。可以在编译时候有跨时钟区域的警告,可以通过设置虚假路径来解决。

相关推荐
北京太速科技股份有限公司1 天前
太速科技-FMC144 -八路 250MSPS 14bit AD FMC子卡
fpga开发
不可思议迷宫2 天前
Verilog编程实现一个分秒计数器
单片机·嵌入式硬件·fpga开发
Terasic友晶科技2 天前
第3篇:Linux程序访问控制FPGA端LEDR<一>
fpga开发·嵌入式系统·de1-soc开发板
程序员JerrySUN2 天前
Linux UART 驱动开发全解析:从原理到实战
linux·运维·驱动开发
双料毒狼_s2 天前
【FPGA】状态机思想回顾流水灯
fpga开发
林政硕(Cohen0415)2 天前
Linux驱动开发进阶(三)- 热插拔机制
linux·驱动开发·热插拔
sukalot2 天前
Windows 图形显示驱动开发-WDDM 2.4功能-GPU 半虚拟化(十一)
windows·驱动开发
小麦嵌入式2 天前
Linux驱动开发实战(十一):GPIO子系统深度解析与RGB LED驱动实践
linux·c语言·驱动开发·stm32·嵌入式硬件·物联网·ubuntu
触角010100012 天前
STM32F103低功耗模式深度解析:从理论到应用实践(上) | 零基础入门STM32第九十二步
驱动开发·stm32·单片机·嵌入式硬件·物联网
双料毒狼_s2 天前
【FPGA实战】基于DE2-115实现数字秒表
fpga开发