XPM_CDC简介

转:https://zhuanlan.zhihu.com/p/147058600

上一篇文章介绍了 单比特跨时钟域 的不同应用场景的区别(基于Xilinx Parameterized Macros),主要有:

  • 同步Reset (XPM_CDC_SYNC_RESET)
  • 异步Reset (XPM_CDC_ASYNC_RESET)
  • 电平信号 (XPM_CDC_SINGLE)
  • 脉冲信号 (XPM_CDC_PULSE)

这篇我们来看一下这几个Macro的具体设计细节和原理。我会基于Xilinx Guide的Introduction并结合 实际例化综合结果 来介绍。

同步Reset - XPM_CDC_SYNC_RESET

这个同步器用来同步 Reset信号 产生目标时钟域的 同步复位信号。产生的复位信号 Assert或Deassert 均与目标时钟同步。同步器所用的寄存器的级数是可以配置的,一般两级是足够了。图1是我例化 XPM_CDC_SYNC_RESET 的综合结果。

图1 - Synthesis Result of XPM_CDC_SYNC_RST

FDRE是Xilinx带同步复位功能的寄存器。图中可以看出,这就是一个很基础的两级寄存器同步器。不看源码的话也能反推出代码(systemverilog):

异步Reset - XPM_CDC_SYNC_RESET

这个同步器用来同步 Reset信号 产生目标时钟域的 异步复位信号。产生的复位信号 Assert时与目标时钟异步,Deassert 与目标时钟同步(避免亚稳态的产生)。图2是我例化 XPM_CDC_ASYNC_RESET 的综合结果。

图2 - Synthesis Result of XPM_CDC_ASYNC_RST

仔细对比的话,我们可以看出图2与图1的不同,主要有两点:

  • 图2用的寄存器是FDPE,这是Xilinx带异步复位功能的寄存器,而图1是FDRE,同步复位寄存器。
  • 图2的输入rst信号接的是寄存器的异步复位端PRE,第一级寄存器的数据输入端接地。而图1输入rst信号接的是寄存器的数据端D,复位输入端则接地。

同样的,我们也可以反推出代码:

电平信号 (XPM_CDC_SINGLE)

这个同步器用来同步一个 电平信号 到目标时钟域。由于电平信号会保持电平不变,我们不需要担心采不到正确的电平值,所以只需要两级寄存器同步器即可。综合结果也和我们预想的一致,如图3所示。可以看到,图3和图1的电路是一样的,代码自然也是一样的。

图3 - Synthesis Result of XPM_CDC_SINGLE

脉冲信号 (XPM_CDC_PULSE)

这个同步器的综合结果如图4所示。

图4 - Synthesis Result of XPM_CDC_PULSE

根据综合结果,我们可以反推一下这个同步器的设计原理。首先,我们发现中间例化了一个 XPM_CDC_SINGLE,而 XPM_CDC_SINGLE 是用来同步电平信号的同步器。也就是说,图4中的同步器先将输入的脉冲信号转化为了一个电平信号,电平信号被同步到目标时钟域后再被转回成脉冲信号输出,从而实现了一个脉冲信号的同步。那么问题来了,

  • 为什么要先把脉冲信号转成一个电平信号 ?

原因就是上一篇文章提到的,如果是快时钟域到慢时钟域,脉冲信号可能会被Miss掉。而转为电平信号则可以避免这种情况。

  • 如何将一个脉冲信号转成一个电平信号 ?

可以用 上升沿 检测(不管输入脉冲信号跨了几个周期都只可能有一次上升沿) + 异或逻辑 (产生电平信号)

  • 转为电平信号一定可以确保被 目标时钟 采到吗 ?

并不是。如果输入的两个脉冲信号间隔很小,那么转换成的连续两个电平信号会组合成一个“脉冲”信号,如图5所示,这个新的脉冲信号可能会被Miss掉,导致两个输入的脉冲信号都Miss掉。(根据评论区Vicky的意见添加修改)或者是这个新的脉冲信号只会被目的时钟采样一次,导致目的时钟域最终只有一个脉冲输出。

图5 - Two Consecutive Pulse Result In a New Pulse

因此,Xilinx Guide里面给出了两个连续的输入脉冲之间最小间隔的限制条件

2*(larger(src_clk period, dest_clk period))

满足这个限制条件后我们就可以确保每个输入的脉冲信号都会对应目标时钟域的一个输出脉冲信号。如果实际应用中无法满足这个条件,XPM_CDC_PULSE可能就直接无法使用了,可以考虑这个同步器+握手控制的方式。

  • 如何将电平信号转回到脉冲信号 ?

仍然可以用异或逻辑。

  • 8
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
xpm_cdc_array_single是Xilinx的一个函数,用于生成一个时钟域交叉域转换(CDC)单口RAM,其使用方法如下: ``` xpm_cdc_array_single #( .ADDR_WIDTH(ADDR_WIDTH), // 地址位宽 .DATA_WIDTH(DATA_WIDTH), // 数据位宽 .INIT_FILE(INIT_FILE), // 初始化文件名 .WRITE_MODE(WRITE_MODE), // RAM写模式 .READ_MODE(READ_MODE), // RAM读模式 .RAM_STYLE(RAM_STYLE), // RAM类型 .READ_LATENCY(READ_LATENCY), // 读取延迟 .WRITE_LATENCY(WRITE_LATENCY), // 写入延迟 .CLK_POLARITY(CLK_POLARITY), // 时钟极性 .ASYNC_READ(ASYNC_READ), // 异步读使能 .USE_MEM_INIT(USE_MEM_INIT), // 使用内存初始化 .MEMORY_INIT_FILE(MEMORY_INIT_FILE) // 内存初始化文件名 ) ( input wire CLK, // 时钟信号 input wire RST, // 复位信号 input wire CE, // 使能信号 input wire [ADDR_WIDTH-1:0] DINA, // 写入数据 input wire [ADDR_WIDTH-1:0] ADDRA, // 写入地址 output reg [DATA_WIDTH-1:0] DOUTB, // 读取数据 input wire [ADDR_WIDTH-1:0] ADDRB, // 读取地址 input wire WE, // 写使能信号 input wire [DATA_WIDTH-1:0] DATAB // 读取数据 ); ``` 其中,各个参数的含义如下: - `ADDR_WIDTH`:地址位宽 - `DATA_WIDTH`:数据位宽 - `INIT_FILE`:初始化文件名 - `WRITE_MODE`:RAM写模式 - `READ_MODE`:RAM读模式 - `RAM_STYLE`:RAM类型 - `READ_LATENCY`:读取延迟 - `WRITE_LATENCY`:写入延迟 - `CLK_POLARITY`:时钟极性 - `ASYNC_READ`:异步读使能 - `USE_MEM_INIT`:使用内存初始化 - `MEMORY_INIT_FILE`:内存初始化文件名 - `CLK`:时钟信号 - `RST`:复位信号 - `CE`:使能信号 - `DINA`:写入数据 - `ADDRA`:写入地址 - `DOUTB`:读取数据 - `ADDRB`:读取地址 - `WE`:写使能信号 - `DATAB`:读取数据 使用xpm_cdc_array_single生成的RAM是一个时钟域交叉域转换(CDC)单口RAM,可用于FPGA设计中的异步数据传输。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值