參考文件
前言對於訊號需要跨時鐘域處理而言,最重要的就是確保資料能穩定的傳送到取樣時鐘域。
普通的cdc處理方法需要關注時鐘域速度的異同,即分慢時鐘域到快時鐘域、快時鐘域到慢時鐘域、相位關係等問題,會讓人瞬間**。
那麼,是否有一種相對穩定,又無需關注傳送時鐘域和接收時鐘域兩者時鐘速度、相位關係的資料傳遞方式呢?
這裡**驗證握手結繩法,自己想的,不知道跟結繩法是不是一致的。。。。。。
思考方式為:要絕對的保證資料被接收,自然是握手應答機制。
流程首先考慮亞穩態說明:對於非同步訊號的採集,不可避免的會有亞穩態,但亞穩態的恢復時間一般為1個時鐘或者兩個時鐘,同樣其不會是0、1的中間值,而是乙個開發者無法確定的定值,同時你的時鐘頻率越高,亞穩態發生的概率就越大。
網上感覺都說的不明就裡,對於簡單的使用多級觸發器,然後使用最高的2bit進行邊沿檢測,目測是不行的。
可以理解為**中的x值,但數位電路的本質上是有值的,要麼0,要麼1。
所以如果是檢測乙個訊號的上公升沿,即使採到亞穩態,那就分兩種情況:
(1)邊沿比較陡峭,時鐘只採到1次亞穩態,那麼邊沿暫存器的值就可能為:00、01。檢測到00,下一次就會採到01。如果是檢測到01,就是想要的沿。
(2)邊沿一點都不陡峭,導致時鐘採到兩次甚至更多次的亞問題,那這就沒得玩了。因為你不知道當前是00\01\10\11,這就可能導致你的後續邏輯完蛋了。
當然這裡第二種情況不予考慮,fpga內部不太可能出現這麼糟糕的上公升沿,除非你的時鐘過快,在時鐘沿到來前,亞穩態還沒有恢復過來。
極端的處理方式是(本質上是濾波):用更多位的暫存器,比如8bit,當檢測到為8'b0000_1111,那就是上公升沿啦,雖然這闊以絕對可靠的檢測到邊沿,但檢測出沿的所用的時間更長,同時需要保證前級訊號的高低電平長度,否則就被濾波了。。。。。。
所以,訊號的邊沿陡峭性是很重要的,專業術語叫做:上公升時間、下降時間。
言歸正傳,那麼握手結繩法是咋樣的操作呢?
如下圖所示:有點複雜
如圖所示,則操作流程為:上述方法應該是支援多bit資料跨時鐘域的,這裡的多bit說的是fpga內部資料,pulse_clk1表示傳送資料使能,clk1檢測到使能則拉高pulse_delay_clk1開始結繩。在clk2中,檢測到clk1中的結繩訊號的上公升沿則產生pulse_clk2,clk2檢測到pulse_clk2則啟動clk2中的結繩pulse_delay_clk2,在clk1中檢測到clk2中的結繩訊號為高則解掉clk1的結繩。在clk2中檢測到clk1的結繩拉低,則解繩clk2中的結繩訊號pulse_delay_clk2,完成傳輸。
待傳送資料在clk2的結繩上公升沿被取樣。
busy訊號為clk1中的訊號,在clk1的傳送資料使能到來則拉高,在pulse_delay_clk2的下降沿則拉低。
可以看到,這種方式只適合少量的慢速的資料傳輸。
源**
`timescale 1ns/1ps**看看。module
cdc_test (
input
i_clk1 ,
input
i_clk2 ,
//input i_rst_n ,
input
i_en_clk1 ,
input [15:0
] i_data_clk1 ,
output
o_busy_clk1 ,
output
o_valid_clk2 ,
output [15:0
] o_data_clk2
);///
/clk1
////clk1的傳送使能邊沿檢測
reg [1:0] r_en_clk1_edge = 2
'b00;
always @(posedge
i_clk1)
begin
r_en_clk1_edge
<= ;
endreg r_en_clk2 = 1
'b0;clk2的使能邊沿檢測
reg [1:0] r_en_clk2_edge = 2
'b00;
always @(posedge
i_clk1)
begin
r_en_clk2_edge
<= ;
endreg r_en_expand = 1
'b0; clk1的使能延長
always @(posedge
i_clk1)
begin
if (r_en_clk1_edge == 2
'b01)
r_en_expand <= 1
'b1;
else
if (r_en_clk2_edge == 2
'b01)
r_en_expand <= 1
'b0;
endreg r_busy_clk1 = 1
'b0; 傳輸忙碌指示,忙碌的時候clk1的資料不可發生改變
always @(posedge
i_clk1)
begin
if (r_en_clk1_edge == 2
'b01)
r_busy_clk1 <= 1
'b1;
else
if (r_en_clk2_edge == 2
'b10)
r_busy_clk1 <= 1
'b0;
end///
/clk2
reg [1:0] r_en_expand_edge = 2
'b00; clk1的擴充套件後的使能邊沿檢測
always @(posedge
i_clk2)
begin
r_en_expand_edge
<= ;
endalways @(posedge i_clk2) ///
/clk2中的使能
begin
if (r_en_expand_edge == 2
'b01)
r_en_clk2 <= 1
'b1;
else
if (r_en_expand_edge == 2
'b10)
r_en_clk2 <= 1
'b0;
endreg r_valid_clk2 = 1
'b0;
always @(posedge
i_clk2)
begin
if (r_en_expand_edge == 2
'b01) 上公升沿表示資料有效
r_valid_clk2 <= 1
'b1;
else
r_valid_clk2
<= 1
'b0;
endreg [15:0] r_data_clk2 = 16
'd0;
always @(posedge
i_clk2)
begin
if (r_en_expand_edge == 2
'b01) 上公升沿重新整理資料
r_data_clk2 <=i_data_clk1;
end///
/訊號輸出
assign o_busy_clk1 =r_busy_clk1;
assign o_valid_clk2 =r_valid_clk2;
assign o_data_clk2 =r_data_clk2;
endmodule
//end the cdc_test model
可以看到資料正確傳輸,不管是快到慢還是慢到快。
以後再板級測試啦。
以上。
跨時鐘域處理
需要做的事情 使能訊號txe to eth由時鐘122.88m時鐘輸出 另一使能訊號vde dv由25m時鐘輸出,計算兩個使能訊號之間的時間間隔,即兩個訊號上公升沿之間的時鐘計數。由於兩個訊號屬於不同的時鐘域,因此要先進行跨時鐘域處理,這裡對vde dv進行處理 在122.88m時鐘下將vde dv...
跨時鐘域處理
討論 今天華為面試題 非同步fifo讀時鐘是寫時鐘的100倍,或者寫是讀的100倍會出現什麼問題?今天華為面試題 非同步fifo讀時鐘是寫時鐘的100倍,或者寫是讀的100倍會出現什麼問題?答得 如果是瞬態資料中間有足夠間隔,則不會出現問題。如果是連續資料,則很快輸出空滿標誌位。面試官不滿意,請教下...
跨時鐘域(CDC)技術 亞穩態簡介
1.亞穩態以及其危害 對我們使用的邊沿觸發器而言 例如上公升沿觸發 由建立時間 setup time 和保持時間 hold time 在上公升沿定義了乙個時間視窗,如果在這個視窗內觸發器的輸入資料發生變化,就會產生時序違規。這會導致觸發器在這個視窗內採集的資料處於乙個不確定的狀態,也就是亞穩態。乙個...