一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

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

一文解析跨時(shí)鐘域傳輸

FPGA設(shè)計(jì)論壇 ? 來(lái)源:FPGA設(shè)計(jì)論壇 ? 2024-11-16 11:55 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

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

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

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

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

1.2 快到慢

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

對(duì)于電平信號(hào)而言(一般電平信號(hào)持續(xù)時(shí)間足夠長(zhǎng)),信號(hào)長(zhǎng)度可以得到保證,所以正常采用兩級(jí)同步器采樣即可。

對(duì)于脈沖信號(hào)而言(一般脈沖信號(hào)持續(xù)時(shí)間很短),長(zhǎng)度難以得到保證,需要對(duì)信號(hào)進(jìn)行延長(zhǎng)。目前,常用延長(zhǎng)方法有兩種:

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

二是閉環(huán)(有反饋)延長(zhǎng),信號(hào)延長(zhǎng)的恢復(fù)位置由反饋信號(hào)決定,此方法實(shí)質(zhì)是通過(guò)相互握手的方式對(duì)窄脈沖信號(hào)進(jìn)行脈寬擴(kuò)展,這也是我們常說(shuō)的“握手協(xié)議”。

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

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

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

可以看到無(wú)論是電平還是脈沖信號(hào)使用起來(lái)都是有限制的,因?yàn)樗鼈儾捎玫亩际菬o(wú)反饋的開環(huán)設(shè)計(jì)(詳細(xì)可查看博文跨時(shí)鐘傳輸——單比特)。采用閉環(huán)的反饋設(shè)計(jì)可以避免這些問(wèn)題,具體流程如下:

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

快時(shí)鐘域?qū)γ}沖信號(hào)進(jìn)行檢測(cè),檢測(cè)為高電平時(shí)輸出高電平信號(hào)req。

慢時(shí)鐘域?qū)鞎r(shí)鐘域的信號(hào)req進(jìn)行延遲打拍采樣。因?yàn)榇藭r(shí)的脈沖信號(hào)被快時(shí)鐘域保持拉高狀態(tài),延遲打拍肯定會(huì)采集到該信號(hào)。

慢時(shí)鐘域確認(rèn)采樣得到高電平信號(hào)req_r2后,拉高反饋信號(hào)ack再反饋給快時(shí)鐘域。

快時(shí)鐘域?qū)Ψ答佇盘?hào)ack進(jìn)行延遲打拍采樣得到ack_r0。如果檢測(cè)到反饋信號(hào)為高電平,證明慢時(shí)鐘域已經(jīng)接收到有效的高電平信號(hào),信號(hào)恢復(fù)原來(lái)狀態(tài)。

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

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

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

verilog代碼

代碼語(yǔ)言:c

復(fù)制

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

module cdc_sbit_handshake(

input aclk,//快時(shí)鐘

input arst_n,//快時(shí)鐘域復(fù)位信號(hào)

input signal_a,//快時(shí)鐘域信號(hào)

input bclk,//慢時(shí)鐘

input brst_n,//慢時(shí)鐘域復(fù)位信號(hào)

output signal_b//慢時(shí)鐘域輸出信號(hào)

);

//慢時(shí)鐘域信號(hào)展寬直至反饋信號(hào)回來(lái)再恢復(fù)

reg req;//寄存慢時(shí)鐘域展寬信號(hào)

reg ack_r0;//反饋信號(hào)

always@(posedge aclk or negedge arst_n) begin

if(!arst_n) begin

req <= 1'b0;

end

else if(signal_a) begin

req <= 1'b1;//信號(hào)展寬

end

else if(ack_r0) begin

req <= 1'b0; //反饋信號(hào)到來(lái)時(shí)恢復(fù)

end

end

//展寬信號(hào)跨時(shí)鐘同步至慢時(shí)鐘域

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

//生成反饋信號(hào)并同步至快時(shí)鐘域

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

//信號(hào)上升沿檢測(cè),讓輸出持續(xù)一個(gè)慢時(shí)鐘周期

assign signal_b = ~req_r2 & req_r1;

endmodule

Testbench

代碼語(yǔ)言:c

復(fù)制

`timescale 1ns/1ps//仿真時(shí)間單位1ns 仿真時(shí)間精度1ps

module cdc_sbit_handshake_tb;

//信號(hào)申明

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)

);

//快時(shí)鐘域慢時(shí)鐘生成

always #5 aclk =~ aclk;

always #15 bclk =~ bclk;

//初始信號(hào)賦值與激勵(lì)

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

仿真結(jié)果

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

二、多比特CDC傳輸

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

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

2.1 慢到快:MUX同步器法

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

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

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

verilog代碼

代碼語(yǔ)言:c

復(fù)制

//同步模塊工作時(shí)鐘為 100MHz 的模塊

//異步數(shù)據(jù)對(duì)來(lái)自工作時(shí)鐘為 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

時(shí)序結(jié)構(gòu)如下圖所示:

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

但如果慢時(shí)鐘域沒(méi)有數(shù)據(jù)使能信號(hào) din_en, 或數(shù)據(jù)使能信號(hào)一直有效,此時(shí)在快時(shí)鐘域?qū)?shù)據(jù)使能信號(hào)進(jìn)行上升沿檢測(cè)的方法將會(huì)失效。因?yàn)閿?shù)據(jù)使能信號(hào)一直有效,除了第一個(gè)數(shù)據(jù),快時(shí)鐘域?qū)o(wú)法檢測(cè)到后繼數(shù)據(jù)的傳輸時(shí)刻。

解決方法就是,在快時(shí)鐘域?qū)β龝r(shí)鐘信號(hào)的邊沿進(jìn)行檢測(cè)。

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

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

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

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

優(yōu)點(diǎn):可以解決快時(shí)鐘域向慢時(shí)鐘域過(guò)渡的問(wèn)題,且其適用的范圍很廣。

缺點(diǎn):實(shí)現(xiàn)較為復(fù)雜,特別是其效率不高,在對(duì)設(shè)計(jì)性能要求較高的場(chǎng)合應(yīng)該慎用。

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

這一部分具體可以查看鏈接:FPGA學(xué)習(xí)筆記——跨時(shí)鐘域(CDC)設(shè)計(jì)之多bit信號(hào)同步

verilog代碼

代碼語(yǔ)言:c

復(fù)制

module data_driver(

input clk_a, //發(fā)送端時(shí)鐘信號(hào)

input rst_n, //復(fù)位信號(hào),低電平有效

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

input clk_b, //接收端時(shí)鐘信號(hào)

input rst_n, //復(fù)位信號(hào),低電平有效

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

input data_req, //請(qǐng)求接收信號(hào)

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

);

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

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

reg data_req ; //請(qǐng)求接收信號(hào)

reg [2:0] cnt_reg;

reg data_ack_sync1;

reg data_ack_sync2;

//計(jì)數(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兩級(jí)同步

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

//請(qǐng)求接收信號(hào)

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兩級(jí)同步

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ù)接收確人信號(hào)

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(慢到快和快到慢通殺)

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

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

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

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

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

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

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

兩個(gè)時(shí)鐘同步端:讀指針同步到寫指針域進(jìn)行“寫滿”判斷,寫指針同步到讀指針域進(jìn)行“讀空”判斷。

verilog代碼

代碼語(yǔ)言:c

復(fù)制

//深度為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, //寫時(shí)鐘

input wr_rst_n,//寫時(shí)鐘復(fù)位

input wr_en,//寫使能

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

input rd_rst_n,//讀時(shí)鐘復(fù)位

input rd_en,//讀使能

output reg fifo_full,//“滿”標(biāo)志位

output reg fifo_empty,//“空”標(biāo)志位

output reg [DATA_WIDTH - 1 : 0] rd_data //寫時(shí)鐘

);

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

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

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

//定義一個(gè)寬度為8,深度為DEPTH的8的RAM_FIFO

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

//寫指針計(jì)數(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;//復(fù)位

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

//讀指針計(jì)數(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;//復(fù)位

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

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

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

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

//讀寫指針轉(zhuǎn)換成格雷碼

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);

//寫指針同步到讀時(shí)鐘域

//打兩拍

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

//讀指針同步到寫時(shí)鐘域

//打兩拍

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

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

--------------------------------------空滿信號(hào)判斷模塊-----------------------------------

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

//組合邏輯判斷寫滿

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

代碼語(yǔ)言:c

復(fù)制

`timescale 1ns/1ps;//仿真時(shí)間單位1ns 仿真時(shí)間精度1ps

module async_fifo_tb #(

parameter DATA_DEPTH = 8,

parameter DATA_WIDTH = 8,

parameter PTR_WIDTH = 3

);

//信號(hào)申明

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)

);

//讀寫時(shí)鐘信號(hào)生成

always #10 rd_clk = ~rd_clk;

always #5 wr_clk = ~wr_clk;

//信號(hào)初始化和賦值

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

仿真結(jié)果

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

三、CDC的幾個(gè)重要問(wèn)題(重要?。。。?/p>

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

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

慢到快使用打兩拍的前提是什么?先給結(jié)論:兩級(jí)同步器與慢時(shí)鐘域之間無(wú)組合邏輯,因?yàn)榻M合邏輯里存在競(jìng)爭(zhēng)冒險(xiǎn),從而導(dǎo)致毛刺產(chǎn)生。我們無(wú)法預(yù)先知道CLKB 的上升沿何時(shí)會(huì)到來(lái),CLKB 采樣到的信號(hào)就無(wú)法預(yù)知。

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

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

僅僅通過(guò)簡(jiǎn)單的同步器同步有可能是不安全的,那么如何傳遞兩個(gè)同時(shí)需要的信號(hào)(b_load和b_en)?

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

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

四、總結(jié)(重要)

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

CDC傳輸方法總結(jié):?jiǎn)伪忍兀?/p>

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

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

多比特:

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

快到慢:因?yàn)榭紤]時(shí)鐘采樣速度,所以需要延長(zhǎng)(使能信號(hào))信號(hào)長(zhǎng)度。最常用的還是“握手協(xié)議”,將使能信號(hào)同步后再加載多比特?cái)?shù)據(jù)。

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

一來(lái)異步FIFO同時(shí)適用快到慢和慢到快兩種CDC傳輸;

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

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

    關(guān)注

    0

    文章

    156

    瀏覽量

    27833
  • 脈沖信號(hào)
    +關(guān)注

    關(guān)注

    6

    文章

    402

    瀏覽量

    37646
  • 時(shí)鐘域
    +關(guān)注

    關(guān)注

    0

    文章

    53

    瀏覽量

    9791

原文標(biāo)題:跨時(shí)鐘域傳輸總結(jié)

文章出處:【微信號(hào):gh_9d70b445f494,微信公眾號(hào):FPGA設(shè)計(jì)論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    時(shí)鐘設(shè)計(jì)之控制信號(hào)傳輸工作原理

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

    vivado約束案例:時(shí)鐘路徑分析報(bào)告

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

    時(shí)鐘控制信號(hào)傳輸設(shè)計(jì)方案

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

    關(guān)于時(shí)鐘信號(hào)的處理方法

    我在知乎看到了多bit信號(hào)時(shí)鐘的問(wèn)題,于是整理了下自己對(duì)于時(shí)鐘信號(hào)的處理方法。
    的頭像 發(fā)表于 10-09 10:44 ?7174次閱讀

    cdc路徑方案幫您解決時(shí)鐘難題

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

    如何利用FPGA設(shè)計(jì)個(gè)時(shí)鐘的同步策略?

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

    關(guān)于時(shí)鐘的詳細(xì)解答

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

    時(shí)鐘電路設(shè)計(jì)總結(jié)

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

    FPGA時(shí)鐘處理方法()

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

    FPGA時(shí)鐘處理方法(二)

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

    CDC時(shí)鐘處理及相應(yīng)的時(shí)序約束

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

    時(shí)鐘電路設(shè)計(jì)—單比特信號(hào)傳輸

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

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

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

    請(qǐng)問(wèn)雙口RAM能用來(lái)進(jìn)行時(shí)鐘傳輸數(shù)據(jù)嗎?

    請(qǐng)問(wèn)雙口RAM能用來(lái)進(jìn)行時(shí)鐘傳輸數(shù)據(jù)嗎? 雙口RAM是種用于在兩個(gè)時(shí)鐘
    的頭像 發(fā)表于 10-18 15:24 ?1211次閱讀

    如何處理時(shí)鐘這些基礎(chǔ)問(wèn)題

    對(duì)于數(shù)字設(shè)計(jì)人員來(lái)講,只要信號(hào)從個(gè)時(shí)鐘跨越到另個(gè)時(shí)鐘,那么就可能發(fā)生亞穩(wěn)態(tài)。我們稱為“
    發(fā)表于 01-08 09:39 ?988次閱讀
    如何處理<b class='flag-5'>跨</b><b class='flag-5'>時(shí)鐘</b><b class='flag-5'>域</b>這些基礎(chǔ)問(wèn)題