一个计算频率的模块

先上代码

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.

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

相关推荐
北城笑笑4 小时前
FPGA 14 ,硬件开发板分类详解,FPGA开发板与普通开发板烧录的区别
fpga开发·fpga
小灰灰的FPGA5 小时前
低速接口项目之串口Uart开发(七)——如何在FPGA项目中实现自适应波特率串口功能
fpga开发
fei_sun1 天前
【Verilog】第一章作业
fpga开发·verilog
深圳市雷龙发展有限公司longsto1 天前
基于FPGA(现场可编程门阵列)的SD NAND图片显示系统是一个复杂的项目,它涉及硬件设计、FPGA编程、SD卡接口、NAND闪存控制以及图像显示等多个方面
fpga开发
嵌入(师)1 天前
嵌入式驱动开发详解1(系统调用)
驱动开发
昵称p1 天前
杂项驱动开发
驱动开发·gpio子系统·杂项驱动开发
9527华安1 天前
FPGA实现PCIE3.0视频采集转10G万兆UDP网络输出,基于XDMA+GTH架构,提供工程源码和技术支持
网络·fpga开发·udp·音视频·xdma·pcie3.0·万兆网
able陈1 天前
为什么verilog中递归函数需要定义为automatic?
fpga开发
fei_sun1 天前
【Verilog】第二章作业
fpga开发·verilog