一个计算频率的模块

先上代码

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.

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

相关推荐
周湘zx5 小时前
项目三:信号源的FPGA实现
fpga开发
9527华安6 小时前
FPGA多路MIPI转FPD-Link视频缩放拼接显示,基于IMX327+FPD953架构,提供2套工程源码和技术支持
fpga开发·架构·音视频
上理考研周导师6 小时前
【FPGA】ISE13.4操作手册,新建工程示例
fpga开发
技术小白爱FPGA9 小时前
Xilinx 平台 drp 动态调节 mmcm
fpga开发
北京太速科技股份有限公司12 小时前
太速科技-889-基于RFSOC XCZU49DR的 16T16R的软件无线电硬件
fpga开发
stm 学习ing13 小时前
HDLBits训练5
c语言·fpga开发·fpga·eda·hdlbits·pld·hdl语言
超能力MAX13 小时前
IIC驱动EEPROM
单片机·嵌入式硬件·fpga开发
吉大一菜鸡1 天前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
hhhhhhh_hhhhhh_1 天前
rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)
驱动开发