新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 跨越時鐘域

        跨越時鐘域

        作者: 時間:2023-12-26 來源:電子森林 收藏

        設計可以使用多個。每個內部形成一個“域”,如果在另一個中需要在一個中生成的信號,則需要格外小心。

        本文引用地址:http://www.104case.com/article/202312/454268.htm

        1-信號

        假設 clkB 域中需要來自 clkA 域的信號。 它需要“同步”到 clkB 域,因此我們要構建一個同步器設計,它從 clkA 域獲取一個信號,并在 clkB 域中創建一個新信號。

        在第一種設計中,我們假設與 clkA 和 clkB 時鐘速度相比,“信號輸入”變化緩慢。
        您需要做的就是使用兩個觸發器將信號從 clkA 移動到 clkB。

        module Signal_CrossDomain(    

        input clkA, 

        // we actually don't need clkA in that example, but it is here for completeness as we'll need it in further examples    input SignalIn_clkA,    

        input clkB,   

        output SignalOut_clkB

        );

        // We use a two-stages shift-register to synchronize SignalIn_clkA to the clkB clock domain

        reg [1:0] SyncA_clkB;

        always @(posedge clkB) SyncA_clkB[0] <= SignalIn_clkA;   // notice that we use clkB

        always @(posedge clkB) SyncA_clkB[1] <= SyncA_clkB[0];   // notice that we use clkB

        assign SignalOut_clkB = SyncA_clkB[1];  // new signal synchronized to (=ready to be used in) clkB domain

        endmodule

        兩個觸發器具有延遲信號的副作用。

        例如,在以下波形中,您可以看到慢速移動的信號被兩個觸發器同步(和延遲)到 clkB 域:


        跨時鐘域 2 - 標志

        另一個時鐘域的標志

        如果需要跨越時鐘域的信號只是一個脈沖(即它只持續一個時鐘周期),我們稱之為“標志”。 以前的設計通常不起作用(標志可能會丟失,或者看到時間過長,具體取決于所使用的時鐘的比例)。

        我們仍然希望使用同步器,但該同步器適用于標志。

        訣竅是將標志轉換為電平變化,這樣可以更容易地跨越時鐘域。

        module Flag_CrossDomain(

            input clkA,

            input FlagIn_clkA,   // this is a one-clock pulse from the clkA domain

            input clkB,

            output FlagOut_clkB   // from which we generate a one-clock pulse in clkB domain

        );

        reg FlagToggle_clkA;

        always @(posedge clkA) FlagToggle_clkA <= FlagToggle_clkA ^ FlagIn_clkA;  // when flag is asserted, this signal toggles (clkA domain)

        reg [2:0] SyncA_clkB;

        always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};  // now we cross the clock domains

        assign FlagOut_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);  // and create the clkB flag

        endmodule

        現在,如果您希望 clkA 域收到確認(clkB 收到標志),只需添加繁忙信號即可。

        module FlagAck_CrossDomain(

            input clkA,

            input FlagIn_clkA,

            output Busy_clkA,

            input clkB,

            output FlagOut_clkB

        );

        reg FlagToggle_clkA;

        always @(posedge clkA) FlagToggle_clkA <= FlagToggle_clkA ^ (FlagIn_clkA & ~Busy_clkA);

        reg [2:0] SyncA_clkB;

        always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};

        reg [1:0] SyncB_clkA;

        always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[0], SyncA_clkB[2]};

        assign FlagOut_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);

        assign Busy_clkA = FlagToggle_clkA ^ SyncB_clkA[1];

        endmodule

        跨越時鐘域 3 - 任務

        在另一個時鐘域中完成任務

        如果 clkA 域中有任務需要在 clkB 域中完成,則可以使用以下設計。

        這是一種方法

        module TaskAck_CrossDomain(

            input clkA,

            input TaskStart_clkA,

            output TaskBusy_clkA, TaskDone_clkA,

            input clkB,

            output TaskStart_clkB, TaskBusy_clkB,

            input TaskDone_clkB

        );

        reg FlagToggle_clkA, FlagToggle_clkB, Busyhold_clkB;

        reg [2:0] SyncA_clkB, SyncB_clkA;

        always @(posedge clkA) FlagToggle_clkA <= FlagToggle_clkA ^ (TaskStart_clkA & ~TaskBusy_clkA);

        always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};

        assign TaskStart_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);

        assign TaskBusy_clkB = TaskStart_clkB | Busyhold_clkB;

        always @(posedge clkB) Busyhold_clkB <= ~TaskDone_clkB & TaskBusy_clkB;

        always @(posedge clkB) if(TaskBusy_clkB & TaskDone_clkB) FlagToggle_clkB <= FlagToggle_clkA;

        always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[1:0], FlagToggle_clkB};

        assign TaskBusy_clkA = FlagToggle_clkA ^ SyncB_clkA[2];

        assign TaskDone_clkA = SyncB_clkA[2] ^ SyncB_clkA[1];

        endmodule

        下面是一個匹配的仿真波形

        跨越時鐘域 4 - 數據總線

        數據總線到另一個時鐘域

        為了將數據總線(2 位寬或更高)從一個時鐘域移動到另一個時鐘域,我們可以使用多種技術。

        這里有一些想法。

        格雷碼:如果數據總線是單調計數器(即僅遞增或遞減),我們可以將其轉換為格雷碼,該格雷碼具有跨時鐘域的能力(在某些時序條件下)。

        數據凍結:如果數據總線是非單調的,則使用標志向另一個域發出信號以捕獲該值(當它在源時鐘域中凍結時)。

        數據突發:如果數據總線有許多需要跨越時鐘域的連續值,請使用異步 FIFO,從源時鐘域推送值,然后從另一個域讀回值。



        關鍵詞: FPGA 時鐘 時鐘域

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 昌黎县| 濮阳市| 台州市| 增城市| 湘乡市| 汉沽区| 临猗县| 泾源县| 尉氏县| 湘潭县| 广州市| 浦北县| 巴林左旗| 陆河县| 防城港市| 新丰县| 星子县| 潢川县| 冷水江市| 周宁县| 南康市| 将乐县| 固阳县| 赞皇县| 万州区| 桦川县| 陇川县| 沭阳县| 四川省| 和林格尔县| 红河县| 武夷山市| 博乐市| 嫩江县| 湘阴县| 澄城县| 股票| 辽源市| 抚州市| 邹城市| 彭州市|