目錄
- **雙觸發(fā)器同步器(Two-Flip-Flop Synchronizer)示例代碼**:
- 雙觸發(fā)器同步器的優(yōu)缺點
-
- 應用實例:同步來自spi_slave的單個使能信號
- 跨時鐘域的設計需要特別小心,以避免亞穩(wěn)態(tài)問題。雙觸發(fā)器同步器(2-Flip-Flop Synchronizer) 是一種簡單且廣泛應用的 時鐘域交叉(CDC) 同步方法,用于將一個時鐘域中的信號同步到另一個時鐘域中。它通過使用兩個觸發(fā)器級聯(lián),確保信號在跨越不同時鐘域時,(以指數(shù)平方級別)降低因為時鐘的不匹配導致不穩(wěn)定或亞穩(wěn)態(tài)(metastability)發(fā)生的概率。

雙觸發(fā)器同步器(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 // 計數(shù)器輸出
);reg sync_ff1, sync_ff2;// 使用雙觸發(fā)器進行同步always @(posedge clk_dst or negedge rst_n) beginif (!rst_n) beginsync_ff1 <= 1'b0;sync_ff2 <= 1'b0;end else beginsync_ff1 <= async_signal; // 第一階段采樣異步信號sync_ff2 <= sync_ff1; // 第二階段消除亞穩(wěn)態(tài)endendassign sync_signal = sync_ff2; // 輸出同步后的信號// 使用同步后的信號更新計數(shù)器always @(posedge clk_dst or negedge rst_n) beginif (!rst_n) begincounter <= 8'b0;end else if (sync_signal) begincounter <= counter + 1'b1; // 增加計數(shù)器endendendmodule
- 第一寄存器
sync_ff1
捕獲來自源時鐘域的信號,可能處于亞穩(wěn)態(tài)。 - 第二寄存器
sync_ff2
采樣 sync_ff1
,將信號穩(wěn)定到目標時鐘域。
雙觸發(fā)器同步器的優(yōu)缺點
優(yōu)點:
- 簡單高效:雙觸發(fā)器同步器結構簡單,通常只需要兩個 D 型觸發(fā)器,因此在資源使用上非常高效。
- 低延遲:與其他更復雜的同步方法(如 FIFO)相比,雙觸發(fā)器同步器的延遲較低。
- 減少亞穩(wěn)態(tài)的風險:通過兩個觸發(fā)器級聯(lián),可以有效降低亞穩(wěn)態(tài)的發(fā)生概率,因為第二個觸發(fā)器會提供額外的穩(wěn)定化時間。
缺點:
- 僅適用于低頻信號:雙觸發(fā)器同步器適用于頻率差異較小的時鐘域交叉。如果時鐘域的頻率差異過大,可能會導致信號丟失或同步失敗。
- 無法處理高數(shù)據(jù)率:如果跨時鐘域的數(shù)據(jù)速率較高,雙觸發(fā)器同步器可能無法有效同步所有數(shù)據(jù)。
- 可能的延遲:雖然延遲較小,但依然會引入一個時鐘周期的延遲。
適用場景:
- 雙觸發(fā)器同步器特別適合同步 單比特控制信號 或 低速數(shù)據(jù),例如用于處理外部輸入的控制信號、狀態(tài)標志或較慢的時鐘信號。
- 在高數(shù)據(jù)率的應用中(如 SPI、I2C、UART 等接口),可能需要更復雜的同步方法,如 FIFO 緩存等。
應用實例:同步來自spi_slave的單個使能信號
- 使能信號SPI_OPEN_LOOP為非同步信號:

- scheduler的開環(huán)配置信號輸入(SPI_OPEN_LOOP)來自spi_slave,scheduler實現(xiàn)如下:
// https://github.com/ChFrenkel/tinyODIN/blob/main/scheduler.v
// 一個調(diào)度器(Scheduler)模塊,且相較于原始的ODIN調(diào)度器移除了旋轉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-mm2 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的開環(huán)配置信號,用于特定調(diào)度配置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信號進行同步處理// 確保該信號在時鐘域內(nèi)穩(wěn)定可靠,避免亞穩(wěn)態(tài)等問題,在復位(低電平有效)和時鐘上升沿時進行操作//----------------------------------------------------------------------------------always @(posedge CLK, negedge RSTN) beginif(~RSTN) begin// 復位時將中間同步寄存器和最終同步寄存器都置為0SPI_OPEN_LOOP_sync_int <= 1'b0;SPI_OPEN_LOOP_sync <= 1'b0;endelse begin// 在正常時鐘上升沿時,先將SPI_OPEN_LOOP信號同步到中間寄存器SPI_OPEN_LOOP_sync_int <= SPI_OPEN_LOOP;// 再將中間寄存器的值同步到最終同步寄存器,形成兩級同步SPI_OPEN_LOOP_sync <= SPI_OPEN_LOOP_sync_int;endendfifo #(.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),// 彈出請求// 根據(jù)不同條件組合數(shù)據(jù)輸入到FIFO,若有事件輸入則組合虛擬相關信息和地址信息作為輸入數(shù)據(jù),否則用神經(jīng)元地址信息作為輸入.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));// 推送請求控制邏輯,根據(jù)SPI_OPEN_LOOP_sync信號以及神經(jīng)元事件輸出等情況來決定是否允許推送數(shù)據(jù)// 當SPI_OPEN_LOOP_sync為低電平且有神經(jīng)元事件輸出,或者有控制器的事件輸入時,允許推送數(shù)據(jù)(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
