一个频率估计的模块

这是一个根据现有始终估计输入数值的频率,基本原理是数1秒时间,作为计数区间,统计被测频率的计数。之后穿越时钟域输出。

代码写好了 还没有进行仿真和实际运行,应该没啥问题了。

 

module clk_estimator #( 
	parameter REF_FRQ = 100*1000*1000 
)(
    input         rst,
    input         clk,

    input         meas_clk,
    output [31:0] cntr_data,
    output [31:0] seconds ,
	output reg update ,
);



reg [31:0]  c ;
wire c_of = c == REF_FRQ /2 -1  ; 
always@(posedge clk )if (rst)  c<=0 ;else c <= ( c_of ) ? 0: c+1 ;
reg div_gate ;always@(posedge clk )if ( c_of ) div_gate <= ~ div_gate ;

wire out_dclk;
//sync_reg  
clk_estimator_sync_reg self_estim(
    .clk( meas_clk ),
    .rst( rst ),
    .in( div_gate ),
    .out( out_dclk)
);

reg [31:0] cntr_clk;
reg [31:0] ref_cntr_data_r;
reg [31:0]  evnts;
assign seconds = evnts ;
reg prev_out_dclk;
reg updater ;
always @(posedge meas_clk) begin
  if (rst) begin
    cntr_clk        <= 0;
    prev_out_dclk   <= 0;
    ref_cntr_data_r <= 0;
    evnts           <= 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;
      evnts           <= evnts + 1'b1;
	  updater <=1;
    end else begin
	updater <=0; 
      cntr_clk        <= cntr_clk + 1'b1;
    end
  end
end
 
// Self clock estimation
//assign cntr_datar =  ref_cntr_data_r[27:0] ;


 one_entry_fifo_1 one_entry_fifo  #(.dw(128) )(
     .rd_clk(clk ), 
	 .wr_clk(meas_clk), 
	 .rd_rst(0),
	 .wr_rst(0),
	 .we( updater &(~full ) ),
	 .re(  ~empty ),
     .d ( { evnts, ref_cntr_data_r  }),
	 .reset_value(),
     .q ({  seconds , cntr_data}),
     .empty() , 
	 .full(full ) 
    );
	
	 always @ (posedge clk ) update <= ~empty ;

endmodule




 
	
module one_entry_fifo_1 #(parameter dw=16 )(
        input	rd_clk, wr_clk, rd_rst,wr_rst,we,re,
        input	[dw-1:0]	d ,reset_value,
        output	reg [dw-1:0]	q ,
        output	 reg  empty , full 
    );
    //synopsys sync_set_reset "rd_rst_n,wr_rst_n"
wire legal_wr  =  we  &(~full);
wire legal_rd  =  re & (~empty) ;
reg wr_ptr ,rd_ptr ;// only one bit !
reg wr_ptr_r,wr_ptr_rr; 
reg rd_ptr_r,rd_ptr_rr; 


always @(posedge rd_clk)wr_ptr_r <=wr_ptr;
always @(posedge rd_clk)wr_ptr_rr <=wr_ptr_r; 

always @(posedge wr_clk)rd_ptr_r <= rd_ptr;
always @(posedge wr_clk)rd_ptr_rr <= rd_ptr_r; 

always @(posedge rd_clk)if( wr_ptr_rr == rd_ptr ) empty<=1;else empty <= legal_rd ; 
always @(posedge wr_clk)if( rd_ptr_rr != wr_ptr ) full<=1 ;else full <= legal_wr ; 

always @(posedge rd_clk)if (rd_rst)  rd_ptr <= 0;else  if ( legal_rd ) rd_ptr <= ~ rd_ptr ;
always @(posedge wr_clk)if (wr_rst)  wr_ptr <= 0;else  if ( legal_wr ) wr_ptr <= ~ wr_ptr ;

reg [dw-1:0] buff ;  always @(posedge wr_clk)if ( legal_wr ) buff <= d ;
always @(posedge rd_clk)if ( rd_rst ) q <= reset_value ;else if ( legal_rd ) q <= buff; 


endmodule
 








//
// Copyright (c) 2016-2020 Fairwaves, Inc.
// SPDX-License-Identifier: CERN-OHL-W-2.0
//

module clk_estimator_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

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值