fpga系列 HDL:跨时钟域同步 双触发器同步器
- 跨时钟域的设计需要特别小心,以避免亚稳态问题。双触发器同步器(2-Flip-Flop Synchronizer) 是一种简单且广泛应用的 时钟域交叉(CDC) 同步方法,用于将一个时钟域中的信号同步到另一个时钟域中。它通过使用两个触发器级联,确保信号在跨越不同时钟域时,(以指数平方级别)降低因为时钟的不匹配导致不稳定或亚稳态(metastability)发生的概率。
双触发器同步器(Two-Flip-Flop Synchronizer)示例代码:
module nocdc (
input wire clk_dst, // 目标时钟域时钟
input wire async_signal, // 来自源时钟域的异步信号
input wire rst_n, // 异步复位信号,低电平有效
output reg sync_signal, // 同步后的信号
output reg [7:0] counter // 计数器输出
);
reg sync_ff1, sync_ff2;
// 使用双触发器进行同步
always @(posedge clk_dst or negedge rst_n) begin
if (!rst_n) begin
sync_ff1 <= 1'b0;
sync_ff2 <= 1'b0;
end else begin
sync_ff1 <= async_signal; // 第一阶段采样异步信号
sync_ff2 <= sync_ff1; // 第二阶段消除亚稳态
end
end
assign sync_signal = sync_ff2; // 输出同步后的信号
// 使用同步后的信号更新计数器
always @(posedge clk_dst or negedge rst_n) begin
if (!rst_n) begin
counter <= 8'b0;
end else if (sync_signal) begin
counter <= counter + 1'b1; // 增加计数器
end
end
endmodule
- 第一寄存器
sync_ff1
捕获来自源时钟域的信号,可能处于亚稳态。 - 第二寄存器
sync_ff2
采样sync_ff1
,将信号稳定到目标时钟域。
双触发器同步器的优缺点
优点:
- 简单高效:双触发器同步器结构简单,通常只需要两个 D 型触发器,因此在资源使用上非常高效。
- 低延迟:与其他更复杂的同步方法(如 FIFO)相比,双触发器同步器的延迟较低。
- 减少亚稳态的风险:通过两个触发器级联,可以有效降低亚稳态的发生概率,因为第二个触发器会提供额外的稳定化时间。
缺点:
- 仅适用于低频信号:双触发器同步器适用于频率差异较小的时钟域交叉。如果时钟域的频率差异过大,可能会导致信号丢失或同步失败。
- 无法处理高数据率:如果跨时钟域的数据速率较高,双触发器同步器可能无法有效同步所有数据。
- 可能的延迟:虽然延迟较小,但依然会引入一个时钟周期的延迟。
适用场景:
- 双触发器同步器特别适合同步 单比特控制信号 或 低速数据,例如用于处理外部输入的控制信号、状态标志或较慢的时钟信号。
- 在高数据率的应用中(如 SPI、I2C、UART 等接口),可能需要更复杂的同步方法,如 FIFO 缓存等。
应用实例:同步来自spi_slave的单个使能信号
- 使能信号SPI_OPEN_LOOP为非同步信号:
- scheduler的开环配置信号输入(SPI_OPEN_LOOP)来自spi_slave,scheduler实现如下:
// https://github.com/ChFrenkel/tinyODIN/blob/main/scheduler.v
// 一个调度器(Scheduler)模块,且相较于原始的ODIN调度器移除了旋转FIFO相关功能
// "scheduler.v" - Scheduler module, rotating FIFOs removed from the original ODIN scheduler
//
// Project: tinyODIN - A low-cost digital spiking neuromorphic processor adapted from ODIN.
//
// Author: C. Frenkel, Delft University of Technology
// Cite/paper: C. Frenkel, M. Lefebvre, J.-D. Legat and D. Bol, "A 0.086-mm² 12.7-pJ/SOP 64k-Synapse 256-Neuron Online-Learning
// Digital Spiking Neuromorphic Processor in 28-nm CMOS," IEEE Transactions on Biomedical Circuits and Systems,
// vol. 13, no. 1, pp. 145-158, 2019.
module scheduler #(
parameter N = 256,
parameter M = 8
)(
input wire CLK,
input wire RSTN,
input wire CTRL_SCHED_POP_N,
input wire [3:0] CTRL_SCHED_VIRTS,
input wire [7:0] CTRL_SCHED_ADDR,
input wire CTRL_SCHED_EVENT_IN,
input wire [M - 1:0] CTRL_NEURMEM_ADDR,
input wire NEUR_EVENT_OUT,
// 来自SPI配置寄存器的输入信号声明,此处接收SPI的开环配置信号,用于特定调度配置
input wire SPI_OPEN_LOOP,
output wire SCHED_EMPTY,
output wire SCHED_FULL,
output wire [11:0] SCHED_DATA_OUT
);
// 用于对SPI_OPEN_LOOP信号进行同步处理的寄存器声明(双同步寄存器)
reg SPI_OPEN_LOOP_sync_int, SPI_OPEN_LOOP_sync;
wire push_req_n;
wire empty_main;
wire full_main;
wire [11:0] data_out_main;
//----------------------------------------------------------------------------------
// SPI信号同步逻辑部分,采用同步屏障机制对SPI_OPEN_LOOP信号进行同步处理
// 确保该信号在时钟域内稳定可靠,避免亚稳态等问题,在复位(低电平有效)和时钟上升沿时进行操作
//----------------------------------------------------------------------------------
always @(posedge CLK, negedge RSTN) begin
if(~RSTN) begin
// 复位时将中间同步寄存器和最终同步寄存器都置为0
SPI_OPEN_LOOP_sync_int <= 1'b0;
SPI_OPEN_LOOP_sync <= 1'b0;
end
else begin
// 在正常时钟上升沿时,先将SPI_OPEN_LOOP信号同步到中间寄存器
SPI_OPEN_LOOP_sync_int <= SPI_OPEN_LOOP;
// 再将中间寄存器的值同步到最终同步寄存器,形成两级同步
SPI_OPEN_LOOP_sync <= SPI_OPEN_LOOP_sync_int;
end
end
fifo #(
.width(12),
.depth(128),
.depth_addr(7)
) fifo_spike_0 (
.clk(CLK),
.rst_n(RSTN),
.push_req_n(full_main | push_req_n),// 推送请求
.pop_req_n(empty_main | CTRL_SCHED_POP_N),// 弹出请求
// 根据不同条件组合数据输入到FIFO,若有事件输入则组合虚拟相关信息和地址信息作为输入数据,否则用神经元地址信息作为输入
.data_in(CTRL_SCHED_EVENT_IN? {CTRL_SCHED_VIRTS,CTRL_SCHED_ADDR} : {4'b0,CTRL_NEURMEM_ADDR}),
.empty(empty_main),
.full(full_main),
.data_out(data_out_main)
);
// 推送请求控制逻辑,根据SPI_OPEN_LOOP_sync信号以及神经元事件输出等情况来决定是否允许推送数据
// 当SPI_OPEN_LOOP_sync为低电平且有神经元事件输出,或者有控制器的事件输入时,允许推送数据(push_req_n为低电平)
assign push_req_n = ~((~SPI_OPEN_LOOP_sync & NEUR_EVENT_OUT) | CTRL_SCHED_EVENT_IN);
assign SCHED_DATA_OUT = data_out_main;
assign SCHED_EMPTY = empty_main;
assign SCHED_FULL = full_main;
endmodule
原文地址:https://blog.csdn.net/ResumeProject/article/details/144695677
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!