RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

一文解析跨時鐘域傳輸

FPGA設計論壇 ? 來源:FPGA設計論壇 ? 2024-11-16 11:55 ? 次閱讀

一、單比特CDC傳輸1.1 慢到快

時鐘域相比慢時鐘域采樣速度更快,也就是說從慢時鐘域來到快時鐘域的信號一定可以被采集到。既然快時鐘一定可以采集到慢時鐘分發(fā)的數(shù)據(jù),那么考慮的問題就只剩下如何保證采樣到的信號質量!最常用的同步方法是雙級觸發(fā)器緩存法,俗稱延遲打拍法。信號從一個時鐘域進入另一個時鐘域之前,將該信號用兩級觸發(fā)器連續(xù)緩存兩次,可有效降低因為時序不滿足而導致的亞穩(wěn)態(tài)問題。

具體如下圖所示:來自慢時鐘clk1的信號在clk2被多次采樣(信號在clk1持續(xù)一個時鐘周期,在clk2持續(xù)三個時鐘周期),如果只需要在clk2持續(xù)一個時鐘周期,可以采用邊沿檢測即可得到signal4;

293f65e2-9d7f-11ef-93f3-92fbcf53809c.png

1.2 快到慢

慢時鐘域相比快時鐘域采樣速度更慢,也就是說從快時鐘域來到慢時鐘域的信號極有可能被漏采。一般要求在接收時鐘域中采樣信號要保持三個時鐘邊沿的時間(也就是1.5倍的采樣時鐘周期)才會避免出現(xiàn)漏采。也就是快到慢跨時鐘域的核心是如何延長信號長度!

對于電平信號而言(一般電平信號持續(xù)時間足夠長),信號長度可以得到保證,所以正常采用兩級同步器采樣即可。

對于脈沖信號而言(一般脈沖信號持續(xù)時間很短),長度難以得到保證,需要對信號進行延長。目前,常用延長方法有兩種:

一是開環(huán)(無反饋)延長,在知道兩個時鐘頻率比的情況下,可以采用“快時鐘域脈寬擴展+慢時鐘域延遲打拍”的方法進行同步。

二是閉環(huán)(有反饋)延長,信號延長的恢復位置由反饋信號決定,此方法實質是通過相互握手的方式對窄脈沖信號進行脈寬擴展,這也是我們常說的“握手協(xié)議”。

然而,除了“握手協(xié)議”以外其他兩種方法都是有缺陷、有限制的,具體如下圖所示:

2956ac5c-9d7f-11ef-93f3-92fbcf53809c.png

295bad56-9d7f-11ef-93f3-92fbcf53809c.png

可以看到無論是電平還是脈沖信號使用起來都是有限制的,因為它們采用的都是無反饋的開環(huán)設計(詳細可查看博文跨時鐘傳輸——單比特)。采用閉環(huán)的反饋設計可以避免這些問題,具體流程如下:

297ff08a-9d7f-11ef-93f3-92fbcf53809c.png

快時鐘域對脈沖信號進行檢測,檢測為高電平時輸出高電平信號req。

慢時鐘域對快時鐘域的信號req進行延遲打拍采樣。因為此時的脈沖信號被快時鐘域保持拉高狀態(tài),延遲打拍肯定會采集到該信號。

慢時鐘域確認采樣得到高電平信號req_r2后,拉高反饋信號ack再反饋給快時鐘域。

快時鐘域對反饋信號ack進行延遲打拍采樣得到ack_r0。如果檢測到反饋信號為高電平,證明慢時鐘域已經(jīng)接收到有效的高電平信號,信號恢復原來狀態(tài)。

29988898-9d7f-11ef-93f3-92fbcf53809c.png

29bd859e-9d7f-11ef-93f3-92fbcf53809c.png

1.3 單比特“握手協(xié)議”verilog代碼

verilog代碼

代碼語言:c

復制

//單比特快到慢“握手協(xié)議”

module cdc_sbit_handshake(

input aclk,//快時鐘

input arst_n,//快時鐘域復位信號

input signal_a,//快時鐘域信號

input bclk,//慢時鐘

input brst_n,//慢時鐘域復位信號

output signal_b//慢時鐘域輸出信號

);

//慢時鐘域信號展寬直至反饋信號回來再恢復

reg req;//寄存慢時鐘域展寬信號

reg ack_r0;//反饋信號

always@(posedge aclk or negedge arst_n) begin

if(!arst_n) begin

req <= 1'b0;

end

else if(signal_a) begin

req <= 1'b1;//信號展寬

end

else if(ack_r0) begin

req <= 1'b0; //反饋信號到來時恢復

end

end

//展寬信號跨時鐘同步至慢時鐘域

reg req_r0;

reg req_r1;

reg req_r2;

always@(posedge bclk or negedge brst_n) begin

if(!brst_n)begin

{req_r2,req_r1,req_r0} <= 3'b0;

end

else begin

{req_r2,req_r1,req_r0} <= ?{req_r1,req_r0,req};

end

end

//生成反饋信號并同步至快時鐘域

reg ack;

always@(posedge aclk or negedge arst_n) begin

if(!arst_n) begin

{ack_r0,ack} <= 2'b0;

end

else begin

{ack_r0,ack} <= ?{ack,req_r1};

end

end

//信號上升沿檢測,讓輸出持續(xù)一個慢時鐘周期

assign signal_b = ~req_r2 & req_r1;

endmodule

Testbench

代碼語言:c

復制

`timescale 1ns/1ps//仿真時間單位1ns 仿真時間精度1ps

module cdc_sbit_handshake_tb;

//信號申明

reg aclk;

reg arst_n;

reg signal_a;

regbclk;

regbrst_n;

wiresignal_b;

//例化

cdc_sbit_handshake u_cdc_sbit_handshake(

.aclk(aclk),

.bclk(bclk),

.arst_n(arst_n),

.brst_n(brst_n),

.signal_a(signal_a),

.signal_b(signal_b)

);

//快時鐘域慢時鐘生成

always #5 aclk =~ aclk;

always #15 bclk =~ bclk;

//初始信號賦值與激勵

initial begin

signal_a = 0;

aclk = 0;

bclk = 0;

arst_n = 1;

brst_n = 1;

#15;

arst_n = 0;

brst_n = 0;

#15;

arst_n = 1;

brst_n = 1;

signal_a = 1;

#10;

signal_a = 0;

end

endmodule

仿真結果

29c78b0c-9d7f-11ef-93f3-92fbcf53809c.png

二、多比特CDC傳輸

多比特為能不能使用二級同步器傳輸?使用格雷碼也不行嗎?什么情況下可以使用同步器加格雷碼跨時鐘傳輸?

先給結論:多比特信號不能用二級同步器跨時鐘傳輸,哪怕使用格雷碼大部分情況也不行,只有在格雷碼自增或自減順序變化才可以跨時鐘傳輸。對于多比特數(shù)據(jù),在進行傳輸時候會因為時序問題導致所有寄存器不會同時翻轉(不是不翻轉,是不同時翻轉?。匀菀自诳鐣r鐘傳輸?shù)臅r候出現(xiàn)中間態(tài)。使用格雷碼可以避免這種現(xiàn)象,但是當格雷碼不是按計數(shù)順序變化(非順序變化相當于每次變化不止一位),這同樣是不允許的,因為格雷碼每次只有一位發(fā)生變化的前提是,數(shù)據(jù)是遞增或遞減的。比如異步FIFO中格雷碼可以通過二級同步器進行CDC傳輸。

2.1 慢到快:MUX同步器法

慢到快這種情況在快時鐘接收端是一定能夠采樣得到的,但是根據(jù)上文可知,多比特不適合采用二級同步器直接傳輸采樣,因為在傳輸過程中有多位同時變化,那么有什么解決辦法呢?解決辦法是在傳輸過程中不變化!所以必須在寫入使能信號有效時傳輸!

傳輸非同步數(shù)據(jù)到接收時鐘域時配上一個同步的控制信號,數(shù)據(jù)和控制信號被同時發(fā)送到接收時鐘域,同時控制信號在接收時鐘域使用兩級寄存器同步到接收時鐘域,使用此同步后的控制信號來加載數(shù)據(jù),這樣數(shù)據(jù)就可以在目的寄存器被安全加載。

具體代碼可參考鏈接:Verilog 跨時鐘域傳輸:慢到快

verilog代碼

代碼語言:c

復制

//同步模塊工作時鐘為 100MHz 的模塊

//異步數(shù)據(jù)對來自工作時鐘為 20MHz 的模塊

module delay_sample(

input rstn,

input clk1,

input [31:0] din,

input din_en,

input clk2,

output [31:0] dout,

output dout_en);

//sync din_en

reg [2:0] din_en_r ;

always @(posedge clk2 or negedge rstn) begin

if (!rstn) din_en_r <= 3'b0 ;

else din_en_r <= {din_en_r[1:0], din_en} ;

end

wire din_en_pos = din_en_r[1] && !din_en_r[2] ;

//sync data

reg [31:0] dout_r ;

reg dout_en_r ;

always @(posedge clk2 or negedge rstn) begin

if (!rstn)

dout_r <= 'b0 ;

else if (din_en_pos)

dout_r <= din ;

end

//dout_en delay

always @(posedge clk2 or negedge rstn) begin

if (!rstn) dout_en_r <= 1'b0 ;

else dout_en_r <= din_en_pos ;

end

assign dout = dout_r ;

assign dout_en = dout_en_r ;

endmodule

時序結構如下圖所示:

29deb304-9d7f-11ef-93f3-92fbcf53809c.png

但如果慢時鐘域沒有數(shù)據(jù)使能信號 din_en, 或數(shù)據(jù)使能信號一直有效,此時在快時鐘域對數(shù)據(jù)使能信號進行上升沿檢測的方法將會失效。因為數(shù)據(jù)使能信號一直有效,除了第一個數(shù)據(jù),快時鐘域將無法檢測到后繼數(shù)據(jù)的傳輸時刻。

解決方法就是,在快時鐘域對慢時鐘信號的邊沿進行檢測。

2.2 快到慢:握手協(xié)議

快到慢必然會伴隨著漏采的風險,根據(jù)單比特CDC傳輸?shù)姆椒梢灾辣苊獾姆椒ň褪茄娱L信號的長度,所以需要帶寫入的使能信號對信號進行延長。此處任采用握手的方式,完全握手具體原理如下圖所示:

2a15d03c-9d7f-11ef-93f3-92fbcf53809c.png

2a336aca-9d7f-11ef-93f3-92fbcf53809c.png

優(yōu)點:可以解決快時鐘域向慢時鐘域過渡的問題,且其適用的范圍很廣。

缺點:實現(xiàn)較為復雜,特別是其效率不高,在對設計性能要求較高的場合應該慎用。

2a4c4270-9d7f-11ef-93f3-92fbcf53809c.png

這一部分具體可以查看鏈接:FPGA學習筆記——跨時鐘域(CDC)設計之多bit信號同步

verilog代碼

代碼語言:c

復制

module data_driver(

input clk_a, //發(fā)送端時鐘信號

input rst_n, //復位信號,低電平有效

input data_ack, //數(shù)據(jù)接收確人信號

input clk_b, //接收端時鐘信號

input rst_n, //復位信號,低電平有效

input [3:0] data, //接收數(shù)據(jù)

input data_req, //請求接收信號

output reg data_ack//數(shù)據(jù)接收確人信號

);

/********************** 發(fā)送端 **********************/

reg [3:0] data;//發(fā)送數(shù)據(jù)

reg data_req ; //請求接收信號

reg [2:0] cnt_reg;

reg data_ack_sync1;

reg data_ack_sync2;

//計數(shù)

always@(posedge clk_a or negedge rst_n)

begin

if(!rst_n)

cnt_reg <= 3'd0;

else if(data_ack_sync1 && !data_ack_sync2 == 1'b1)

cnt_reg <= 3'd0;

else if(data_req == 1'b1)

cnt_reg <= cnt_reg;

else

cnt_reg <= cnt_reg + 1'b1;

end

//data_ack兩級同步

always@(posedge clk_a or negedge rst_n)

begin

if(!rst_n)

begin

data_ack_sync1 <= 1'b0;

data_ack_sync2 <= 1'b0;

end

else

begin

data_ack_sync1 <= data_ack;

data_ack_sync2 <= data_ack_sync1;

end

end

//請求接收信號

always@(posedge clk_a or negedge rst_n)

begin

if(!rst_n)

data_req <= 1'b0;

else if(cnt_reg == 3'd4)

data_req <= 1'b1;

else if(data_ack_sync2 == 1'b1)

data_req <= 1'b0;

else

data_req <= data_req;

end

//發(fā)送數(shù)據(jù)

always@(posedge clk_a or negedge rst_n)

begin

if(!rst_n)

data <= 4'd0;

else if(data == 4'd7 && data_ack_sync2 == 1'b1 && data_req == 1'b1 )

data <= 4'd0;

else

begin

if(data_ack_sync2 == 1'b1 && data_req == 1'b1 )

data <= data + 1'b1;

else

data <= data;

end

end

/********************** 接收端 **********************/

reg data_req_sync1;

reg data_req_sync2;

//data_req兩級同步

always@(posedge clk_b or negedge rst_n)

begin

if(!rst_n)

begin

data_req_sync1 <= 1'b0;

data_req_sync2 <= 1'b0;

end

else

begin

data_req_sync1 <= data_req;

data_req_sync2 <= data_req_sync1;

end

end

//數(shù)據(jù)接收確人信號

always@(posedge clk_b or negedge rst_n)

begin

if(!rst_n)

data_ack <= 1'b0;

else if(data_req_sync2 == 1'b1)

data_ack <= 1'b1;

else

data_ack <= 1'b0;

end

endmodule2.3 異步FIFO(慢到快和快到慢通殺)

關于異步FIFO具體可以看看這篇:異步FIFO設計原理與設計方法以及重要問題匯總(包含verilog代碼|Testbench|仿真結果),對異步FIFO介紹很詳細并且總結了若干重要問題。

FIFO 是一種“先進先出隊列”,數(shù)據(jù)從一頭寫入,從另一頭讀出,讀出順序和寫入順序一模一樣。因為隊列空間有限,因此一般把隊列設計為環(huán)形。對于隊列來說,最重要的事情是不能在隊空的時候讀數(shù)、不能在隊滿的時候寫數(shù)。一般通過比較讀寫指針來獲得“隊空”和“隊滿”信息。異步FIFO常常用在高速數(shù)據(jù)跨時鐘域的場景上。

2a5fb6ca-9d7f-11ef-93f3-92fbcf53809c.png

異步FIFO主要由五部分組成:RAM、寫控制端、讀控制端、兩個時鐘同步端

端口RAM:此處為偽雙端口RAM進行數(shù)據(jù)存儲與讀出,有兩組數(shù)據(jù)線、地址線、時鐘線。

寫控制端:寫指針與滿信號產(chǎn)生器,用于判斷是否可以寫入數(shù)據(jù),寫操作時,寫使能有效且FIFO未滿。

讀控制端:讀指針與空信號產(chǎn)生器,用于判斷是否可以讀取數(shù)據(jù),讀操作時,讀使能有效且FIFO未空。

兩個時鐘同步端:讀指針同步到寫指針域進行“寫滿”判斷,寫指針同步到讀指針域進行“讀空”判斷。

verilog代碼

代碼語言:c

復制

//深度為8,數(shù)據(jù)位寬為8的異步FIFO

module async_fifo #(

parameter DATA_DEPTH = 8,//深度為8

parameter DATA_WIDTH = 8,//數(shù)據(jù)位寬為8

parameter PTR_WIDTH = 3//讀寫指針位寬為3

)(

input [DATA_WIDTH - 1 : 0] wr_data, //寫數(shù)據(jù)

input wr_clk, //寫時鐘

input wr_rst_n,//寫時鐘復位

input wr_en,//寫使能

input rd_clk,//讀數(shù)據(jù)

input rd_rst_n,//讀時鐘復位

input rd_en,//讀使能

output reg fifo_full,//“滿”標志位

output reg fifo_empty,//“空”標志位

output reg [DATA_WIDTH - 1 : 0] rd_data //寫時鐘

);

/*-----------------------------------------------------------------

-----------------------------偽雙口RAM模塊--------------------------

------------------------------------------------------------------*/

//定義一個寬度為8,深度為DEPTH的8的RAM_FIFO

reg [DATA_WIDTH - 1 : 0] ram_fifo [DATA_DEPTH - 1 : 0];

//寫指針計數(shù)

reg [PTR_WIDTH : 0] wr_ptr; //信息位+地址位所以指針位寬為4

always@ (posedge wr_clk or negedge wr_rst_n) begin

if(!wr_rst_n) begin

wr_ptr <= 0;

end

else if(wr_en && !fifo_full) begin

wr_ptr <= wr_ptr + 1;

end

else begin

wr_ptr <= wr_ptr;

end

end

//RAM寫入數(shù)據(jù)

wire [PTR_WIDTH -1 : 0] wr_addr;

assign wr_addr = wr_ptr[PTR_WIDTH -1 : 0];//RAM寫數(shù)據(jù)只需要地址位不需要信息位,所以尋址地址位寬為3

always@ (posedge wr_clk or negedge wr_rst_n) begin

if(!wr_rst_n) begin

ram_fifo[wr_addr] <= 0;//復位

end

else if(wr_en && !fifo_full) begin

ram_fifo[wr_addr] <= wr_data;//數(shù)據(jù)寫入

end

else begin

ram_fifo[wr_addr] <= ram_fifo[wr_addr];//保持不變

end

end

//讀指針計數(shù)

reg [PTR_WIDTH : 0] rd_ptr;

always@ (posedge rd_clk or negedge rd_rst_n) begin

if(!rd_rst_n) begin

rd_ptr <= 0;

end

else if(rd_en && !fifo_empty) begin

rd_ptr <= rd_ptr + 1;

end

else begin

rd_ptr <= rd_ptr;

end

end

//RAM讀出數(shù)據(jù)

wire [PTR_WIDTH -1 : 0] rd_addr;

assign rd_addr = rd_ptr[PTR_WIDTH -1 : 0];//RAM讀數(shù)據(jù)只需要地址位不需要信息位,所以尋址地址位寬為3

always@ (posedge rd_clk or negedge rd_rst_n) begin

if(!rd_rst_n) begin

rd_data <= 0;//復位

end

else if(rd_en && !fifo_empty) begin

rd_data <= ram_fifo[rd_addr];//讀數(shù)據(jù)

end

else begin

rd_data <= rd_data;//保持不變

end

end

/*--------------------------------------------------------------------

------------------------讀寫指針(格雷碼)轉換與跨時鐘域同步模塊------

---------------------------------------------------------------------------------------*/

//讀寫指針轉換成格雷碼

wire [PTR_WIDTH : 0] wr_ptr_gray;

wire [PTR_WIDTH : 0] rd_ptr_gray;

assign wr_ptr_gray = wr_ptr ^ (wr_ptr >> 1);

assign rd_ptr_gray = rd_ptr ^ (rd_ptr >> 1);

//寫指針同步到讀時鐘域

//打兩拍

reg [PTR_WIDTH : 0] wr_ptr_gray_r1;

reg [PTR_WIDTH : 0] wr_ptr_gray_r2;

always@ (posedge rd_clk or negedge rd_rst_n) begin

if(!rd_rst_n) begin

wr_ptr_gray_r1 <= 0;

wr_ptr_gray_r2 <= 0;

end

else begin

wr_ptr_gray_r1 <= wr_ptr_gray;

wr_ptr_gray_r2 <= wr_ptr_gray_r1;

end

end

//讀指針同步到寫時鐘域

//打兩拍

reg [PTR_WIDTH : 0] rd_ptr_gray_r1;

reg [PTR_WIDTH : 0] rd_ptr_gray_r2;

always@ (posedge wr_clk or negedge wr_rst_n) begin

if(!wr_rst_n) begin

rd_ptr_gray_r1 <= 0;

rd_ptr_gray_r2 <= 0;

end

else begin

rd_ptr_gray_r1 <= rd_ptr_gray;

rd_ptr_gray_r2 <= rd_ptr_gray_r1;

end

end

/*--------------------------------------------------------------------------------------

--------------------------------------空滿信號判斷模塊-----------------------------------

---------------------------------------------------------------------------------------*/

//組合邏輯判斷寫滿

always@ (*) begin

if(!wr_rst_n) begin

fifo_full <= 0;

end

else if( wr_ptr_gray == { ~rd_ptr_gray_r2[PTR_WIDTH : PTR_WIDTH - 1],

rd_ptr_gray_r2[PTR_WIDTH - 2 : 0] }) begin

fifo_full <= 1;

end

else begin

fifo_full <= 0;

end

end

//組合邏輯判斷讀空

always@ (*) begin

if(!rd_rst_n) begin

fifo_empty <= 0;

end

else if(rd_ptr_gray == wr_ptr_gray_r2) begin

fifo_empty <= 1;

end

else begin

fifo_empty <= 0;

end

end

endmodule

Testbench

代碼語言:c

復制

`timescale 1ns/1ps;//仿真時間單位1ns 仿真時間精度1ps

module async_fifo_tb #(

parameter DATA_DEPTH = 8,

parameter DATA_WIDTH = 8,

parameter PTR_WIDTH = 3

);

//信號申明

reg [DATA_WIDTH - 1 : 0] wr_data;

reg wr_clk;

reg wr_rst_n;

reg wr_en;

reg rd_clk;

reg rd_rst_n;

reg rd_en;

wire fifo_full;

wire fifo_empty;

wire [DATA_WIDTH - 1 : 0] rd_data;

//例化

async_fifo u_async_fifo (

.wr_clk(wr_clk),

.rd_clk(rd_clk),

.wr_rst_n(wr_rst_n),

.rd_rst_n(rd_rst_n),

.wr_en(wr_en),

.rd_en(rd_en),

.wr_data(wr_data),

.rd_data(rd_data),

.fifo_empty(fifo_empty),

.fifo_full(fifo_full)

);

//讀寫時鐘信號生成

always #10 rd_clk = ~rd_clk;

always #5 wr_clk = ~wr_clk;

//信號初始化和賦值

initial begin

wr_clk = 0;

wr_rst_n = 1;

wr_en = 0;

rd_clk = 0;

rd_rst_n = 1;

rd_en = 0;

#10;

wr_rst_n = 0;

rd_rst_n = 0;

#10;

wr_rst_n = 1;

rd_rst_n = 1;

//only write

wr_en = 1;

rd_en = 0;

repeat(10) begin

@(negedge wr_clk) begin

wr_data = {$random}%30;

end

end

//only read

wr_en = 0;

rd_en = 1;

repeat(10) begin

@(negedge rd_clk);

end

rd_en =0;

//read and write

wr_en = 0;

rd_en = 0;

#80;

wr_en = 1;

rd_en = 1;

repeat(20) begin

@(negedge wr_clk) begin

wr_data = {$random}%30;

end

end

end

endmodule

仿真結果

2a6406e4-9d7f-11ef-93f3-92fbcf53809c.png

三、CDC的幾個重要問題(重要?。。。?/p>

多比特為能不能使用二級同步器傳輸?使用格雷碼也不行嗎?什么情況下可以使用同步器加格雷碼跨時鐘傳輸?

先給結論:多比特信號不能用二級同步器跨時鐘傳輸,哪怕使用格雷碼大部分情況也不行,只有在格雷碼自增或自減順序變化才可以跨時鐘傳輸。對于多比特數(shù)據(jù),在進行傳輸時候會因為時序問題導致所有寄存器不會同時翻轉(不是不翻轉,是不同時翻轉!),所以容易在跨時鐘傳輸?shù)臅r候出現(xiàn)中間態(tài)。使用格雷碼可以避免這種現(xiàn)象,但是當格雷碼不是按計數(shù)順序變化(非順序變化相當于每次變化不止一位),這同樣是不允許的,因為格雷碼每次只有一位發(fā)生變化的前提是,數(shù)據(jù)是遞增或遞減的。比如異步FIFO中格雷碼可以通過二級同步器進行CDC傳輸。

慢到快使用打兩拍的前提是什么?先給結論:兩級同步器與慢時鐘域之間無組合邏輯,因為組合邏輯里存在競爭冒險,從而導致毛刺產(chǎn)生。我們無法預先知道CLKB 的上升沿何時會到來,CLKB 采樣到的信號就無法預知。

2a8780ba-9d7f-11ef-93f3-92fbcf53809c.png

2ab5b53e-9d7f-11ef-93f3-92fbcf53809c.png

僅僅通過簡單的同步器同步有可能是不安全的,那么如何傳遞兩個同時需要的信號(b_load和b_en)?

將b_load和b_en信號在b_clk時鐘域中合并成一個信號b_lden,然后同步至a_clk中。若果不能合并,比如譯碼信息則加入一個控制信號,等兩個信號穩(wěn)定了再采樣!

2ac89320-9d7f-11ef-93f3-92fbcf53809c.png

四、總結(重要)

采樣中“快到慢”與“慢到快”在考慮問題時有什么區(qū)別?慢到快:只需要考慮亞穩(wěn)態(tài)問題.
快到慢:除亞穩(wěn)態(tài)問題外,還需考慮慢時鐘的采樣速率問題。因為根據(jù)采樣定理,采樣頻率低于信號最高頻率2倍的時候,是無法完整采樣的。

CDC傳輸方法總結:單比特:

慢到快只考慮亞穩(wěn)態(tài)問題,采用延遲打拍法;

快到慢還需要考慮慢時鐘采樣速度,但是只要延長信號長度即可。常用方法為電平同步器、脈沖同步器、握手協(xié)議。其中,握手協(xié)議限制較為靈活,但握手信號需要在兩個時鐘域來回傳遞導致延時很大,所以握手協(xié)議是以犧牲效率為代價保證信號傳遞質量。

多比特:

慢到快:只考慮亞穩(wěn)態(tài)問題,采用延遲打拍法。為需要傳輸?shù)臄?shù)據(jù)配上一個同步的控制使能信號,數(shù)據(jù)和控制信號被同時發(fā)送到接收時鐘域,使用此同步后的控制信號來加載數(shù)據(jù)(控制信號有效表示數(shù)據(jù)穩(wěn)定不變化從而避免傳輸出錯),這樣數(shù)據(jù)就可以在目的寄存器被安全加載。這種方法我們稱為MUX同步器法/多周期路徑同步法(意思都差不多)。

快到慢:因為考慮時鐘采樣速度,所以需要延長(使能信號)信號長度。最常用的還是“握手協(xié)議”,將使能信號同步后再加載多比特數(shù)據(jù)。

處理多比特數(shù)據(jù)跨時鐘傳輸,最常用還是異步FIFO,

一來異步FIFO同時適用快到慢和慢到快兩種CDC傳輸;

二來也能更好地滿足數(shù)據(jù)流具有較快的傳輸速度要求。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 傳輸
    +關注

    關注

    0

    文章

    153

    瀏覽量

    27456
  • 脈沖信號
    +關注

    關注

    6

    文章

    398

    瀏覽量

    36956
  • 時鐘域
    +關注

    關注

    0

    文章

    52

    瀏覽量

    9535

原文標題:跨時鐘域傳輸總結

文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    時鐘設計之控制信號傳輸工作原理

    時鐘通俗地講,就是模塊之間有數(shù)據(jù)交互,但是模塊用的不是同時鐘進行驅動。
    的頭像 發(fā)表于 10-08 17:00 ?2634次閱讀
    <b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>設計之控制信號<b class='flag-5'>傳輸</b>工作原理

    vivado約束案例:時鐘路徑分析報告

    時鐘路徑分析報告分析從時鐘(源時鐘)跨越到
    的頭像 發(fā)表于 11-27 11:11 ?5862次閱讀
    vivado約束案例:<b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>路徑分析報告

    時鐘控制信號傳輸設計方案

    1、時鐘與亞穩(wěn)態(tài) 時鐘通俗地講,就是模塊之間有數(shù)據(jù)交互,但是模塊用的不是同
    發(fā)表于 10-16 15:47 ?1150次閱讀
    <b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>控制信號<b class='flag-5'>傳輸</b>設計方案

    關于時鐘信號的處理方法

    我在知乎看到了多bit信號時鐘的問題,于是整理了下自己對于時鐘信號的處理方法。
    的頭像 發(fā)表于 10-09 10:44 ?6154次閱讀

    cdc路徑方案幫您解決時鐘難題

    章介紹下CDC也就是時鐘可能存在的些問題以及基本的
    的頭像 發(fā)表于 11-30 06:29 ?7182次閱讀
    cdc路徑方案幫您解決<b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>難題

    如何利用FPGA設計時鐘的同步策略?

    帶來的亞穩(wěn)態(tài)、采樣丟失、潛在邏輯錯誤等等系列問題處理不當,將導致系統(tǒng)無法運行。本文總結出了幾種同步策略來解決時鐘問題。
    的頭像 發(fā)表于 09-01 08:29 ?5547次閱讀
    如何利用FPGA設計<b class='flag-5'>一</b>個<b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>的同步策略?

    關于時鐘的詳細解答

    個做數(shù)字邏輯的都繞不開時鐘處理,談談SpinalHDL里用于
    的頭像 發(fā)表于 04-27 10:52 ?4266次閱讀
    關于<b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>的詳細解答

    時鐘電路設計總結

    時鐘操作包括同步時鐘操作和異步
    的頭像 發(fā)表于 05-18 09:18 ?735次閱讀
    <b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>電路設計總結

    FPGA時鐘處理方法()

    時鐘是FPGA設計中最容易出錯的設計模塊,而且時鐘
    的頭像 發(fā)表于 05-25 15:06 ?1985次閱讀
    FPGA<b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>處理方法(<b class='flag-5'>一</b>)

    FPGA時鐘處理方法(二)

    篇文章已經(jīng)講過了單bit時鐘的處理方法,這次解說下多bit的
    的頭像 發(fā)表于 05-25 15:07 ?1021次閱讀
    FPGA<b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>處理方法(二)

    CDC時鐘處理及相應的時序約束

    CDC(Clock Domain Conversion)時鐘分單bit和多bit傳輸
    的頭像 發(fā)表于 06-21 14:59 ?1823次閱讀

    時鐘電路設計—單比特信號傳輸

    時鐘(CDC)的應從對亞穩(wěn)定性和同步性的基本了解開始。
    的頭像 發(fā)表于 06-27 14:25 ?1054次閱讀
    <b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>電路設計—單比特信號<b class='flag-5'>傳輸</b>

    fpga時鐘通信時,慢時鐘如何讀取快時鐘發(fā)送過來的數(shù)據(jù)?

    fpga時鐘通信時,慢時鐘如何讀取快時鐘發(fā)送過來的數(shù)據(jù)? 在FPGA設計中,通常需要
    的頭像 發(fā)表于 10-18 15:23 ?1065次閱讀

    請問雙口RAM能用來進行時鐘傳輸數(shù)據(jù)嗎?

    請問雙口RAM能用來進行時鐘傳輸數(shù)據(jù)嗎? 雙口RAM是種用于在兩個時鐘
    的頭像 發(fā)表于 10-18 15:24 ?852次閱讀

    如何處理時鐘這些基礎問題

    對于數(shù)字設計人員來講,只要信號從時鐘跨越到另時鐘,那么就可能發(fā)生亞穩(wěn)態(tài)。我們稱為“
    發(fā)表于 01-08 09:39 ?632次閱讀
    如何處理<b class='flag-5'>跨</b><b class='flag-5'>時鐘</b><b class='flag-5'>域</b>這些基礎問題
    RM新时代网站-首页