一个计算频率的模块

先上代码

复制代码
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.

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

相关推荐
凉、介5 分钟前
深入 LWIP:数据是如何被封装并发送出去的
网络·驱动开发·笔记·学习·嵌入式
爱吃汽的小橘12 小时前
PS-XADC 实验
fpga开发
阿拉斯攀登16 小时前
第 7 篇 安卓驱动开发的灵魂:字符设备驱动框架,从原理到最简实战
android·驱动开发·rk3568·嵌入式驱动·安卓驱动
阿拉斯攀登16 小时前
第 1 篇 入坑不亏!瑞芯微 RK 平台 + 安卓驱动开发,小白全维度扫盲
android·驱动开发·rk3568·嵌入式驱动
爱吃汽的小橘19 小时前
FPGA分频器
fpga开发
春日见2 天前
端到端大模型自动驾驶
java·开发语言·驱动开发·docker·自动驾驶·计算机外设
Lueeee.2 天前
Linux下的ULN2003驱动板与28BYJ-48步进电机驱动移植
linux·驱动开发
上班最快乐2 天前
基于FPGA的APS6404L-3SQR QSPI PSRAM驱动设计(2)
fpga开发
被遗忘的旋律.2 天前
Linux驱动开发笔记(二十六)——PWM(SG90驱动)
linux·驱动开发·笔记
FPGA-ADDA2 天前
第一篇:软件无线电(SDR)基础与FPGA的角色
fpga开发·fpga·数字电路·dsp·软件无线电