基于FPGA设计Verilog 跨时钟域传输:慢到快

理论上讲,快时钟域的信号总会采集到慢时钟域传输来的信号,如果存在异步可能会导致采样数据出错,所以需要进行同步处理。此类同步处理相对简单,一般采用延迟打拍法,或延迟采样法。

延迟打拍法

最常用的同步方法是双级触发器缓存法,俗称延迟打拍法。异步信号从一个时钟域进入另一个时钟域之前,将该信号用两级触发器连续缓存两次,可有效降低因为时序不满足而导致的亚稳态问题。电路示意图如下。

一般设计中使用两级触发器进行缓存即可满足设计时序需求。大量实验表明,三级触发器缓存可解决 99% 以上的此类异步时序问题。

两级触发器延迟打拍并检测信号上升沿的 Verilog 描述如下:

实例

module delay_clap(
    input       clk1,  //异步慢时钟
    input       sig1,  //异步信号

    input       rstn,  //复位信号
    input       clk2,  //目的快时钟域市政
    output      sig2); //快时钟域同步后的信号

   reg [2:0]    sig2_r ;   //3级缓存,前两级用于同步,后两节用于边沿检测
   always @(posedge clk2 or negedge rstn) begin
     if (!rstn) sig2_r  <= 3'b0 ;
     else       sig2_r  <= {sig2_r[1:0], sig1} ;  //缓存
   end
   assign sig2 = sig2_r[1] && !sig2_r[2] ; //上升沿检测

延迟采样法

此方法主要针对多位宽的数据传输。

例如当两个异步时钟频率比为 5 时,可以先用延迟打拍的方法对数据使能信号进行 2 级打拍缓存,然后再在快时钟域对慢时钟域的数据信号进行采集。

该方法的基本思想是保证信号被安全采集的时刻,而不用同步多位宽的数据信号,可节省部分硬件资源。

利用打拍的方法进行延迟采样的 Verilog 描述如下。

实例

//同步模块工作时钟为 100MHz 的模块
//异步数据对来自工作时钟为 20MHz 的模块
module delay_sample(
    input               rstn,
    input               clk1,
    input [31:0]        din,
    input               din_en,

    input               clk2,
    output [31:0]       dout,
    output              dout_en);

   //sync din_en
   reg [2:0]    din_en_r ;
   always @(posedge clk2 or negedge rstn) begin
     if (!rstn) din_en_r  <= 3'b0 ;
     else       din_en_r  <= {din_en_r[1:0], din_en} ;
   end
   wire din_en_pos = din_en_r[1] && !din_en_r[2] ;

   //sync data
   reg [31:0]           dout_r ;
   reg                  dout_en_r ;
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn)
        dout_r         <= 'b0 ;
      else if (din_en_pos)
        dout_r         <= din ;
   end
   //dout_en delay
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn)        dout_en_r      <= 1'b0 ;
      else              dout_en_r      <= din_en_pos ;
   end
   assign       dout    = dout_r ;
   assign       dout_en = dout_en_r ;

endmodule

该方法时序结果图如下所示。

显然,在 clk2 时钟域,t2 时刻对数据进行采样缓存比 t1 时刻要安全的多。

但如果慢时钟域没有数据使能信号 din_en, 或数据使能信号一直有效,此时在快时钟域对数据使能信号进行上升沿检测的方法将会失效。因为数据使能信号一直有效,除了第一个数据,快时钟域将无法检测到后继数据的传输时刻。

解决方法就是,在快时钟域对慢时钟信号的边沿进行检测。

如果两个时钟的频率相差较小,可能还需要对数据进行延迟缓存,以保证采集到的是当拍时钟的数据;如果两个时钟的频率相差较大,数据采样时刻可以通过计数的方法获得,而不用对数据进行缓存。

利用计数延迟采样的方法对慢时钟边沿进行检测的 Verilog 描述如下。

实例

//同步模块工作时钟为 100MHz 的模块
//异步数据对来自工作时钟为 999KHz 的模块
module delay_cnt_sample(
    input               rstn,
    input               clk1,
    input [31:0]        din,
    input               din_en,

    input               clk2,
    output [31:0]       dout,
    output              dout_en);

   //4级缓存:3级用于打拍同步,一级用于边沿检测
   reg [3:0]    edge_r ;
   always @(posedge clk2 or negedge rstn) begin
     if (!rstn) edge_r  <= 3'b0 ;
     else       edge_r  <= {edge_r[3:0], clk1} ;
   end
   wire edge_pos = edge_r[2] && !edge_r[3] ;

   //延迟计数器,检测到慢时钟上升沿时开始计数
   reg [5:0] cnt ;
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn)                cnt <= 6'h3f ;
      else if (edge_pos && din_en)
                                cnt <= 6'h0 ;
      else if (cnt != 6'h3f)    cnt <= cnt + 1'b1 ;
   end

   //数据同步
   reg [31:0]           dout_r ;
   reg                  dout_en_r ;
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn)
        dout_r         <= 'b0 ;
      else if (din_en && cnt == 47) //大约在慢时钟周期中间时刻采样
        dout_r         <= din ;
   end
   //数据使能信号较数据采样时刻延迟一个周期输出
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn)        dout_en_r      <= 1'b0 ;
      else if (din_en && cnt==48)
                        dout_en_r      <= 1'b1 ;
      else              dout_en_r      <= 1'b0 ;
   end
   assign       dout    = dout_r ;
   assign       dout_en = dout_en_r ;

endmodule

频率相差较大的数据同步采样结果图如下。

由图可知,快时钟采样时刻在慢时钟周期中央时刻左右,此时是非常安全的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. 解决亚稳态问题的方法有:加入异步复位电路、加入放电电路、使用同步复位电路、使用寄存器锁存、使用互锁电路等方法。 2. FPGA 可编程逻辑基于的可编程结构是基于查找表(Look-Up Table,LUT)和触发器(Flip-Flop)的。LUT 是一种能够进行布尔运算的逻辑门,可以实现任意的逻辑函数,而触发器可以存储数据并进行时序控制。FPGA 中的可编程逻辑单元(Configurable Logic Block,CLB)包含了多个 LUT 和触发器,这些 CLB 可以被互相连接,从而实现复杂的逻辑功能。 3. 在 Verilog 中,如果在时钟边沿触发器的输入端口上使用了非阻塞赋值(<=),可能会产生锁存器。因此,应该在时钟边沿触发器的输入端口上使用阻塞赋值(=)。 4. 跨时钟域的合理处理方式包括同步和异步两种方式。从时钟域到慢时钟域,应该使用同步方式,即通过两个时钟域之间的同步信号进行数据传输。从慢时钟域到时钟域,应该使用异步方式,即将数据先存储在 FIFO 缓冲区中,然后在时钟域中进行读取。对于单bit信号和多bit信号,处理方式大体相同,只是需要考虑到位宽的问题。 5. FPGA 和 C 语言之间的联系在于,FPGA 可以通过硬件描述语言(例如 Verilog 或 VHDL)进行编程,而 C 语言可以通过软件编程实现相似的功能。不同的是,FPGA 通常用于需要高性能、低功耗、并行处理的应用场景,而 C 语言则更适合于需要灵活性、可移植性和易维护性的应用场景。另外,Verilog 是一种硬件描述语言,用于描述数字电路,而 C 语言是一种通用编程语言,用于编写软件程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GJZGRB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值