一个计算频率的模块

先上代码

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

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

相关推荐
我送炭你添花8 小时前
电子世界的奇妙冒险:从一个电阻开始(系列目录)
人工智能·单片机·嵌入式硬件·fpga开发
知识充实人生10 小时前
FPGA设计杂谈之九:HRIO/HPIO/HDIO
fpga开发·xilinx·hr i/o·hp i/o·hd i/o·io类型
代码游侠10 小时前
复习——Linux设备驱动开发笔记
linux·arm开发·驱动开发·笔记·嵌入式硬件·架构
maverick_11118 小时前
【FPGA】 在Verilog中,! 和 ~ 的区别
fpga开发
A星空1231 天前
一、Linux嵌入式的I2C驱动开发
linux·c++·驱动开发·i2c
春日见1 天前
车辆动力学:前后轮车轴
java·开发语言·驱动开发·docker·计算机外设
黄埔数据分析2 天前
QDMA把描述符当数据搬移, 不用desc engine
fpga开发
Forsete2 天前
LINUX驱动开发#9——定时器
linux·驱动开发·单片机
南檐巷上学2 天前
基于FPGA的正弦信号发生器、滤波器的设计(DAC输出点数受限条件下的完整正弦波产生器)
fpga开发·数字信号处理·dsp·dds
JMchen1232 天前
AI编程与软件工程的学科融合:构建新一代智能驱动开发方法学
驱动开发·python·软件工程·ai编程