FPGA跨时钟域设计的一点总结

本文探讨了在数字电路设计中跨时钟域的问题,包括亚稳态现象的解释,多时钟设计的命名规则与模块划分策略,以及不同时钟域之间的数据同步方法。此外,还详细介绍了快时钟域到慢时钟域的数据同步技巧,并提供了多种信号传递的解决方案。

1. 亚稳态的概念说明

是指触发器无法在某个规定时间段内达到一个可确认的状态。当一个触发器进入亚稳态引时,既无法预测该单元的输出电平,也无法预测何时输出才能稳定在某个正确的电平上。在这个稳定期间,触发器输出一些中间级电平,或者可能处于振荡状态,并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。

 

同步系统中,如果触发器的setup time / hold time不满足,就可能产生亚稳态,此时触发器输出端Q在有效时钟沿之后比较长的一段时间处于不确定的状态,在这段时间里Q端毛刺、振荡、固定的某一电压值,而不是等于数据输入端D的值。这段时间称为决断时间(resolution time)。经过resolution time之后Q端将稳定到0或1上,但是究竟是0还是1,是随机的,与输入没有必然的关系。

 

在跨时钟域的设计中,由于时钟的不同步,及其容易产生亚稳态。

 

常用的同步方法是使用两级寄存器来进行同步:

 

2. 多时钟设计的命名规则

不同时钟域的时钟和模块以及模块输入输出信号命名,应当加上适当的前缀以区分。如控制部分uclk,视频处理部分vclk,NVM接口部分mclk。这样既便于区分,也便于在后端做时序约束和分析时的处理(比如某些命令的批量处理,set_false_path -from { u* })。

 

3. 多时钟设计的模块划分

将整体的多时钟设计分割成多个单个独立时钟的功能模块和负责模块间同步的同步模块,这样非常利于后端的时序分析,程序结构也更加清晰。

 

4. 快时钟域到慢时钟域的同步

常见问题:快时钟域的信号持续时间太短,慢时钟域采不到

 

解决方法1: 将快时钟域传递的信号持续时间延长,使其大于慢时钟域的一个时钟周期。

 

解决方法2:使用握手信号(反馈信号)

 

5. 跨时钟域传递多个相关信号(如enable和load信号)

5.1 问题1: 传递两个同时需要的信号(b_load和b_en)

 

解决方法:只传递一个信号(b_lden)

 

5.2 问题2:传递两个前后顺序控制的信号(ben1和ben2)

 

解决方法:只传递一个信号(ben1)

 

5.3 问题3:传递两个编码控制信号(bdec[0]和bdec[1])

 

解决方法1:产生一个ready信号(bden_n)来指示数据的有效性

 

解决方法2:使用one-hot key信号结合状态机来处理接收到的信号

Note

 

6. 数据的同步

There are far too many opportunities for multi-bit data changes to be incorrectly sampled using synchronizers.

 

6.1 握手信号(但是要牺牲一定的时间)

Data can be passed between clock domains using two or three handshake control signals, depending on the application and the paranoia of the design engineer. The biggest disadvantage to using handshaking is the latency required to pass and recognize all of the handshaking signals for each data word that is transferred.

 

For many open-ended data-passing applications, a simple two-line handshaking sequence is sufficient. The sender places data onto a data bus and then synchronizes a "data_valid" signal to the receiving clock domain. When the "data_valid" signal is recognized in the new clock domain, the receiver clocks the data into a register in the new clock domain (the data should have been stable for at least two rising clock edges in the sending clock domain) and then passes an "acknowledge" signal through a synchronizer to the sender. When the sender recognizes the synchronized "acknowledge" signal, the sender can change the value being driven onto the data bus.

 

Under some circumstances, it might be useful to use a third control signal, "ready", sent through a synchronizer from the receiver to the sender to indicate that the receiver is indeed "ready" to receive data. The "ready" signal should not be asserted while the "data_valid" signal is true. When the "data_valid" signal is de-asserted, a "ready" signal can be passed to the sender. Of course, with the added handshake signal comes the penalty of longer latency to synchronize and recognize the third control signal.

 

6.2 FIFO

One of the most popular methods of passing data between clock domains is to use a FIFO.A dual port memory is used for the FIFO storage. One port is controlled by the sender which puts data into the memory as fast a one data word (or one data bit for serial applications) per write clock. The other port is controlled by the receiver, which pulls data out of memory one data word per read clock. Two control signals are used to indicate if the FIFO is empty, full or partially fullTwo additional control signals are frequently used to indicate if the FIFO is almost full or almost empty.

 

In theory, placing data into a shared memory with one clock and removing the data from the shared memory with another clock seems like an easy and ideal solution to passing data between clock domains. For the most part it is, but generating accurate full and empty flags can be challenging.

 

 

==============================================================

附录(相关设计技巧):

1. 慢时钟域到快时钟域的同步及上升(下降)沿检测电路

同步和上升沿检测电路:(注意输入B是被反向过的)

 

时序图

代码实现为:先将发送时钟域过来的信号用寄存器打两拍,然后将输出信号A和再打一拍的反向信号B相与(如果是下降沿检测,则将输出信号A反向和再打一拍的同向信号B相与)。

 

拓展:如果将先将发送时钟域过来的信号用寄存器打两拍,然后将输出信号A和再打一拍的信号B相一或,就得到的是上升沿和下降沿都检测的逻辑。

 

2. 脉冲检测(将脉冲信号转换为电平信号,pulse-toggle-circuit)

基本电路为:

 

时序图:

 

代码实现为:

always@(posedge clk1 or negedge nrst)

begin

if(!nrst)

Q <= 0;

else 

Q <= D;

end

 

assign D = Data ? Q_bar : Q;

 

拓展:。。。

 

3. 完整握手流程

完整握手流程为:

 

时序图:

 

代码实现为:

 

 

4. 部分握手流程I(完整握手流程的简化版) 

部分握手流程I为:

 

时序图:

 

说明:省去了完整握手流程里面的最后一步,也就是ACK信号自动会把自己de-assert,而不是要等检测到REQ信号de-assert之后了。

 

In the first partial handshake scheme, Circuit A asserts its request signal and the Circuit B acknowledges it with a single clock-wide pulse. In this case, Circuit B does not care when Circuit A drops its request signal. However, to make this technique work, Circuit A must drop its request signal for at least one clock cycle otherwise Circuit B cannot distinguish between the previous and the new request.(A发出的REQ信号必须至少无效持续一个时钟周期,否则B无法辨别两个响铃的REQ信号)

 

With this handshake, Circuit B uses a level synchronizer for the request signal and Circuit A uses a pulse synchronizer for the acknowledge signal. In this handshake protocol the acknowledge pulses only occur when Circuit B detects the request signal. This allows Circuit A to control the spacing of the pulses into the synchronizer by controlling the timing of its request signal.

 

5. 部分握手流程II(完整握手流程的简化版)

部分握手流程II为:

 

时序图:

 

说明:省去了完整握手流程里面的最后两步,两个信号在assert保持一段时间以后都是自动de-assert,不在相互检测。

 

In this second partial handshake scheme, Circuit A asserts it request with a single clock-wide pulse and Circuit B acknowledges it with a single clock-wide pulse. In this case, both circuits need to save state to indicate that the request is pending.

 

This type of handshake uses pulse synchronizers but if one circuit has a clock that is twice as fast as the other, that circuit can use an edge-detect synchronizer instead. (如果有一个时钟域的时钟比另外一个时钟域的时钟快两倍以上,则可以使用边沿检测同步电路来代替握手电路)

 

6. Basic Data Path Design

基本电路为:

 

时序图:

 

 

说明:A design using full handshake signaling has a large window of time for the receiving circuit to sample the signal bus and is not very efficient. The same design can use a partial handshake instead of the full handshake to speed up the transfer.

### FPGA时钟域交叉解决方案 在FPGA设计中,时钟域交叉(Clock Domain Crossing, CDC)是一个常见的挑战。当信号从一个时钟域传输到另一个时钟域时,可能会由于异步操作而导致亚稳态问题[^1]。为了有效解决这一问题,通常采用以下几种方法: #### 1. 双缓冲机制 双缓冲是最常用的CDC解决方案之一。通过引入两个寄存器级联来捕获来自源时钟域的数据,并将其传递给目标时钟域。这种方法能够显著降低亚稳态的概率,因为即使第一个寄存器进入亚稳态,第二个寄存器也有足够的时间恢复稳定状态。 ```verilog always @(posedge clk_dest or posedge reset) begin if (reset) begin reg_stage_1 <= 1'b0; reg_stage_2 <= 1'b0; end else begin reg_stage_1 <= data_in_from_src_clk; reg_stage_2 <= reg_stage_1; end end ``` 此代码片段展示了如何利用两级触发器实现跨时钟域的安全数据传输[^2]。 --- ### 流水线并行化设计的最佳实践 流水线技术是提高吞吐量的关键手段,在FPGA设计中尤为重要。以下是几个关于流水线并行化的最佳实践建议: #### 1. 阶段划分合理化 将复杂计算分解成多个简单的子任务,每一步都由独立的硬件资源完成。这种分层结构不仅有助于减少单一时钟周期内的延迟需求,还能充分利用现代FPGA内部丰富的逻辑单元和布线资源。 例如,在乘法运算过程中,可以将输入准备、部分积生成以及最终累加三个主要步骤分别映射至不同的管道阶段[^1]。 #### 2. 数据依赖分析与消除瓶颈 仔细审查算法流程图中的任何潜在阻塞点——特别是那些涉及反馈回路或者条件分支判断的地方。如果可能的话,则应尝试重构这些区域以便允许更多的并发执行路径存在;否则就需要增加额外存储元件作为临时缓存区以缓解压力。 对于某些特定应用场景下的特殊要求而言(比如实时视频编码解码),还应该考虑加入专门定制的功能模块进一步加速整个系统的响应速度同时保持较低功耗水平。 #### 3. 使用分布式内存架构 相比于集中式的RAM块访问方式来说,分布在整个芯片表面之上的小型SRAM阵列往往能提供更快捷高效的局部读写服务。因此,在规划大型项目初期就应该充分考虑到这一点并将相应组件布置得更加靠近实际使用者端口附近从而缩短关键路径长度进而提升整体性能表现。 ```verilog // 示例:简单流水线设计 module pipeline_example ( input wire clk, input wire rst_n, input wire [7:0] a, output reg [15:0] result ); reg [7:0] stage_a; reg [15:0] stage_b; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin stage_a <= 8'd0; stage_b <= 16'd0; result <= 16'd0; end else begin stage_a <= a; // Stage 1: Input capture stage_b <= {stage_a, stage_a}; // Stage 2: Processing result <= stage_b * stage_a; // Final Output Calculation end end endmodule ``` 上述Verilog代码展示了一个基础版本的三阶流水线结构实例[^2]。 --- ### 总结 综上所述,针对FPGA中的时钟域交叉问题可以通过同步电路如双缓冲方案加以规避;而在追求更高效率方面则应当遵循良好的流水线设计理念来进行布局安排调整工作负载分配策略等等措施相结合才能达到最优效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值