在复杂的数字系统设计中,不同模块往往需要不同频率或相位的时钟信号,这就不可避免地产生了跨时钟域(Clock Domain Crossing,CDC)问题。若处理不当,跨时钟域信号可能导致亚稳态现象,使系统出现不可预测的错误。Vivado 作为一款强大的 FPGA 开发工具,提供了多种方法来有效应对跨时钟域挑战。​

一、跨时钟域问题的根源​

        数字电路中,触发器在时钟信号的有效沿对输入数据进行采样并存储。当数据从一个时钟域传输到另一个时钟域时,如果目标时钟域的采样时刻与源时钟域的数据变化时刻不匹配,就可能导致触发器采样到处于不确定状态(亚稳态)的数据。例如,在一个包含高速数据处理模块和低速控制模块的系统中,高速模块产生的数据以较快的时钟速率变化,而低速控制模块以较慢的时钟速率采样这些数据,此时就容易出现跨时钟域问题。​

二、Vivado 中的跨时钟域处理方法​

(一)简单同步器​

        对于单比特信号的跨时钟域传输,简单同步器是一种常用的方法。它由至少两级 CE 端和 Reset/Clear 端接死的寄存器序列组成。在源时钟域,信号经过第一级寄存器后,其输出信号的稳定性得到提高;再经过第二级寄存器,进一步降低亚稳态传播到目标时钟域的概率。例如,在 Vivado 中使用 Verilog 语言实现简单同步器的代码如下:​

module simple_synchronizer (​

input wire source_clk,​

input wire target_clk,​

input wire rst_n,​

input wire source_signal,​

output reg target_signal​

);​

reg sync_signal1;​

reg sync_signal2;​

always @(posedge source_clk or negedge rst_n) begin​

if (!rst_n) begin​

sync_signal1 <= 1'b0;​

end else begin​

sync_signal1 <= source_signal;​

end​

end​

always @(posedge target_clk or negedge rst_n) begin​

if (!rst_n) begin​

sync_signal2 <= 1'b0;​

target_signal <= 1'b0;​

end else begin​

sync_signal2 <= sync_signal1;​

target_signal <= sync_signal2;​

end​

end​

endmodule​​

        为了进一步提高简单同步器的可靠性,在 Vivado 中可以使用 ASYNC_REG 约束,将用作简单同步器的多个寄存器放入同一个 SLICE,以减少走线延时的不一致性和不确定性,从而延长平均无故障时间(MTBF)。例如,在 XDC 约束文件中添加如下约束:​

set_property ASYNC_REG TRUE [get_cells {sync_signal1_reg sync_signal2_reg}]​

(二)握手电路​

        握手电路通过在源时钟域和目标时钟域之间添加额外的控制信号,确保数据传输的同步性。它包括请求信号(Request)和确认信号(Acknowledge)。当源时钟域有数据需要传输时,发送请求信号到目标时钟域;目标时钟域接收到请求信号后,采样数据并发送确认信号回源时钟域;源时钟域收到确认信号后,完成一次数据传输。这种方式虽然增加了控制逻辑的复杂度,但能有效避免亚稳态问题。以下是一个简单的握手电路的 Verilog 代码示例:​

module handshake_circuit (​

input wire source_clk,​

input wire target_clk,​

input wire rst_n,​

input wire [7:0] source_data,​

output reg [7:0] target_data,​

output reg request,​

input wire acknowledge​

);​

reg data_valid;​

always @(posedge source_clk or negedge rst_n) begin​

if (!rst_n) begin​

data_valid <= 1'b0;​

request <= 1'b0;​

end else if (!data_valid) begin​

data_valid <= 1'b1;​

request <= 1'b1;​

end else if (acknowledge) begin​

data_valid <= 1'b0;​

request <= 1'b0;​

end​

end​

always @(posedge target_clk or negedge rst_n) begin​

if (!rst_n) begin​

target_data <= 8'b0;​

end else if (request) begin​

target_data <= source_data;​

end​

end​

endmodule​

(三)FIFO 隔离​(最常使用的方法,使用一个异步fifo,通过控制读写时钟来解决跨时钟问题)

        在总线跨时钟域的设计中,异步 FIFO 是一种非常有效的隔离方法。它通过在两个时钟域之间建立一个数据缓存区,将数据从源时钟域写入 FIFO,再从目标时钟域读出,从而避免了跨时钟域的数据直接传输。根据 FIFO 的实现方式不同,在 Vivado 中需要添加不同的 XDC 约束。​

  1. 基于 BRAM 的 FIFO:许多 FPGA 内部的 FIFO 是用 BRAM 搭建的,所有控制逻辑都在 BRAM 内部,这种实现方式较为推荐。
  2. 带有格雷码控制的 FIFO:为了在亚稳态下做读写指针抽样也能正确判断空满状态,常使用带有格雷码控制的 FIFO。这种 FIFO 的计数器和读写指针等需要用 BRAM 外部的逻辑搭建,约束相对复杂。除了设置读写时钟为异步外,还需要考虑这些外部逻辑的约束。例如,对读写指针的同步过程进行约束,确保其在跨时钟域时的稳定性。​

(四)使用时钟使能信号​

        将控制信号当作时钟使能信号进行传递也是一种跨时钟域处理的方法。例如,对于单比特的控制信号,可以直接将其作为目标时钟域的使能信号,来控制目标时钟域对数据的采样时机。假设在源时钟域有一个控制信号 enable_source,要将其传递到目标时钟域来控制数据采样,在目标时钟域的代码可以如下实现:​

module enable_transfer (​

input wire source_clk,​

input wire target_clk,​

input wire rst_n,​

input wire enable_source,​

input wire [7:0] source_data,​

output reg [7:0] target_data​

);​

reg enable_sync;​

always @(posedge source_clk or negedge rst_n) begin​

if (!rst_n) begin​

enable_sync <= 1'b0;​

end else begin​

enable_sync <= enable_source;​

end​

end​

always @(posedge target_clk or negedge rst_n) begin​

if (!rst_n) begin​

target_data <= 8'b0;​

end else if (enable_sync) begin​

target_data <= source_data;​

end​

end​

endmodule​

三、在 Vivado 中分析跨时钟域路径​

在 Vivado 中,可以使用 report_clock_interaction 命令(GUI 支持)来鉴别和报告设计中所有的时钟关系,从而快速定位需要关注的跨时钟域路径。执行该命令后,会生成一个时钟关系表格,其中:​

  • “Common Primary Clock” 栏:显示为 “Yes” 表示源时钟和目标时钟拥有相同的来源,在 FPGA 内部共享部分时钟网络,这类路径相对安全;显示为 “No” 则表示不安全的跨时钟域路径。通过对该栏进行排序,可以快速鉴别出安全和不安全的 CDC 路径。​
  • “Inter - Clock Constraints” 栏:观察此栏内的内容,可判断已读入的 XDC 中是否对相应的跨时钟域路径进行了合理的约束。​
  • “Path Req (WNS)” 栏:对该栏由小到大进行排序,找到那些数值特别小(例如小于 100ps)或是显示为 “Unexpanded” 的跨时钟域路径。结合是否共享 “Common Primary Clock” 来鉴别此类路径,并作出合理的约束。数值小可能意味着该路径的时序紧张,需要进一步优化。​

四、跨时钟域处理的注意事项​

  1. 约束的准确性:在使用各种跨时钟域处理方法时,准确设置 XDC 约束至关重要。错误的约束可能导致 Vivado 对时钟关系的分析出现偏差,无法有效避免亚稳态问题。例如,在设置时钟分组约束时,要确保将正确的时钟划分到相应的组中。​
  1. 信号完整性:跨时钟域传输的信号,尤其是在高速设计中,要考虑信号完整性问题。过长的走线、不合理的布线等都可能导致信号失真,影响跨时钟域处理的效果。在布局布线时,应尽量缩短跨时钟域信号的传输路径,减少信号干扰。​
  1. 测试与验证:完成跨时钟域设计后,需要进行充分的测试与验证。通过仿真和实际硬件测试,检查跨时钟域处理是否正确,确保系统在各种情况下都能稳定运行。例如,在仿真时,可以设置不同的时钟相位关系、数据变化时机等,全面验证设计的可靠性。
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐