電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 45|回復(fù): 0
收起左側(cè)

【芯片設(shè)計(jì)】異步電路碎碎念(八)多比特握手同步器

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
匿名  發(fā)表于 2024-10-11 12:26:00 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
DMUX同步器完成之后繼續(xù)完成多比特握手同步器,異步時(shí)鐘域的握手同步器典型結(jié)構(gòu)不只一種,還區(qū)分全握手和半握手,這里面的門道我也不是很專業(yè),所以就只把熟悉的結(jié)構(gòu)拿出來大家一起看下就好了。握手同步器的結(jié)構(gòu)簡圖是這樣的:

這個(gè)結(jié)構(gòu)簡圖里還可以補(bǔ)充兩個(gè)信號(hào),分別是目的時(shí)鐘域的輸出數(shù)據(jù)有效信號(hào)和源始終與的ready信號(hào),一會(huì)在代碼中我們嘗試加一下。這個(gè)結(jié)構(gòu)的核心是一句話,當(dāng)in_enable信號(hào)為高時(shí)開始進(jìn)行數(shù)據(jù)同步,當(dāng)數(shù)據(jù)同步?jīng)]有完成前,tx_sel信號(hào)是不會(huì)落下去。

代碼實(shí)現(xiàn)那么通過代碼來看,先來明確頂層:
module async_nbit_hand #(
  parameter DL = 2,
  parameter WD = 1,
  parameter FF = 1
)( /*AUTOARG*/
   // Outputs
   i_ready, o_data, o_en,
   // Inputs
   i_clk, i_rst_n, i_data, i_en, o_clk, o_rst_n
   );
// ----------------------------------------------------------------
// Interface declare
// ----------------------------------------------------------------
input          i_clk;
input          i_rst_n;
input [WD -1:0]i_data;
input          i_en;
output         i_ready;
input          o_clk;
input          o_rst_n;
output[WD -1:0]o_data;
output         o_en;同樣的,如果FF不為0時(shí)需要打拍,以i_data_in和i_en_in作為真實(shí)的跨異步輸入信號(hào):// ----------------------------------------------------------------
// i_data dff
// ----------------------------------------------------------------
wire [WD -1:0]i_data_in;
wire          i_en_in;
generate
  if(FF == 0)begin: NO_IN_DFF
    assign i_data_in = i_data;
    assign i_en_in   = i_en;
  end //if(FF == 0)begin: NO_IN_DFF
  else begin: IN_DFF
    reg [WD -1:0]i_data_ff;
    reg          i_en_ff;
    always @(posedge i_clk or negedge i_rst_n) begin
      if(!i_rst_n)begin
        i_data_ff 之后做TX側(cè)的邏輯,對(duì)著結(jié)構(gòu)圖做可以了:// ----------------------------------------------------------------
// tx enable logic
// ----------------------------------------------------------------
wire tx_en, tx_sel;
wire rx_sel, rx_sel_sync;
reg  tx_en_ff;
assign tx_en  = (i_en_in || tx_sel) && (!rx_sel_sync);
assign tx_sel = tx_en_ff;
always @(posedge i_clk or negedge i_rst_n) begin
  if(!i_rst_n)
    tx_en_ff TX和RX之間的同步器:// ----------------------------------------------------------------
// tx_sel rx_sel async
// ----------------------------------------------------------------
async_1bit_delay #(.DL(DL), .FF(0))
u_tx_sel_sync(
  .i_clk    (i_clk),
  .i_rst_n  (i_rst_n),
  .i_data   (tx_sel),
  .o_clk    (o_clk),
  .o_rst_n  (o_rst_n),
  .o_data   (rx_sel)
);
async_1bit_delay #(.DL(DL), .FF(0))
u_rx_sel_sync(
  .i_clk    (o_clk),
  .i_rst_n  (o_rst_n),
  .i_data   (rx_sel),
  .o_clk    (i_clk),
  .o_rst_n  (i_rst_n),
  .o_data   (rx_sel_sync)
);RX側(cè)的邏輯,同樣對(duì)照著結(jié)構(gòu)圖做就可以,在這里我補(bǔ)充一個(gè)rx_sel_pulse標(biāo)記rx_sel的上升沿:// ----------------------------------------------------------------
// rx_sel_pulse
// ----------------------------------------------------------------
reg  rx_sel_ff, rx_sel_pulse_ff;
wire rx_sel_pulse;
always @(posedge o_clk or negedge o_rst_n) begin
  if(!o_rst_n)
    rx_sel_ff 控制信號(hào)結(jié)束,后面是數(shù)據(jù)信號(hào)采樣,這里跟結(jié)構(gòu)有一些不同,我把輸入數(shù)據(jù)在源時(shí)鐘域通過使能信號(hào)寄存了:// ----------------------------------------------------------------
// i_data sample
// ----------------------------------------------------------------
reg [WD -1:0]i_data_lock;
always @(posedge i_clk or negedge i_rst_n) begin
  if(!i_rst_n)
    i_data_lock 最后的部分就是輸出邏輯,這里有三個(gè)輸出:o_data、o_en和i_ready:// ----------------------------------------------------------------
// out logic
// ----------------------------------------------------------------
assign o_en    = rx_sel_pulse_ff;
assign o_data  = i_data_sync;
generate
  if(FF == 0)begin: NO_IN_DFF_RD
    assign i_ready = (tx_sel == 1'b0) && (rx_sel_sync == 1'b0);
  end
  else begin: IN_DFF_RD
    assign i_ready = (tx_sel == 1'b0) && (rx_sel_sync == 1'b0) && (i_en_in == 1'b0);
  end
endgenerate
endmodule波形分析握手同步器面對(duì)的主場景是脈沖使能的多比特?cái)?shù)據(jù),在脈沖信號(hào)有效時(shí),輸入數(shù)據(jù)被鎖存:

而因?yàn)樵阪i存時(shí)的邏輯包含了i_ready,所以即使連續(xù)脈沖到來,也只會(huì)鎖存i_ready有效時(shí)的數(shù):

而后看TX->RX控制邏輯鏈i_en_in -> tx_sel -> rx_sel:

于是在目的時(shí)鐘域,rx_sel_pulse時(shí)就可以采樣在源始終域被寄存的數(shù)據(jù)i_data_lock了:

同時(shí)將rx_sel_pulse打一拍作為輸出信號(hào)的使能:

同時(shí),rx_sel信號(hào)要同步回去,因?yàn)樵趓x_sel上升沿時(shí)就已經(jīng)把數(shù)據(jù)采樣,因此rx_sel同步回去并取反告訴源時(shí)鐘域已經(jīng)同步完成了可以處理下一個(gè)值。rx_sel_sync會(huì)將tx_en置0,而后tx_sel也被置0,同步后rx_sel也歸0,完成一次握手反饋的傳輸:

當(dāng)rx_sel_sync也為0后,一次完整的握手同步宣告完成,那么i_ready就可以置1:

i_ready為1后可以進(jìn)行下一次傳輸:

需要注意的是,如果入口進(jìn)行了打拍操作,i_ready的邏輯需要適當(dāng)調(diào)整:
generate
  if(FF == 0)begin: NO_IN_DFF_RD
    assign i_ready = (tx_sel == 1'b0) && (rx_sel_sync == 1'b0);
  end
  else begin: IN_DFF_RD
    assign i_ready = (tx_sel == 1'b0) && (rx_sel_sync == 1'b0) && (i_en_in == 1'b0);
  end
endgenerate此時(shí)i_ready會(huì)看i_en_in信號(hào)即i_en_ff,不會(huì)和i_en信號(hào)產(chǎn)生邏輯環(huán)。

系列文章入口——
【芯片設(shè)計(jì)】SoC 101(一):緒論
【芯片設(shè)計(jì)】FIFO漫談(零)從無處不在的FIFO開始說起
【芯片設(shè)計(jì)】計(jì)算機(jī)體系結(jié)構(gòu)(一)虛擬內(nèi)存
【芯片設(shè)計(jì)】深入理解AMBA總線(零)緒論
【芯片設(shè)計(jì)】握手協(xié)議的介紹與時(shí)序說明
【芯片設(shè)計(jì)】復(fù)位那些小事 —— 復(fù)位消抖
【芯片設(shè)計(jì)】快速入門數(shù)字芯片設(shè)計(jì)(一)Introduction
【芯片驗(yàn)證】UVM源碼計(jì)劃(零)下定決心讀源碼前的自測環(huán)節(jié)
【芯片設(shè)計(jì)】異步電路碎碎念(一) 到底什么是異步電路
【芯片設(shè)計(jì)】從RTL到GDS(一):Introduction
其他文章鏈接——
【芯片驗(yàn)證】sva_assertion: 15道助力飛升的斷言練習(xí)
【芯片驗(yàn)證】可能是RTL定向驗(yàn)證的巔峰之作
【芯片驗(yàn)證】RTL仿真中X態(tài)行為的傳播 —— 從xprop說起
【芯片驗(yàn)證】年輕人的第一個(gè)systemVerilog驗(yàn)證環(huán)境全工程與解析
【芯片設(shè)計(jì)】verilog中有符號(hào)數(shù)和無符號(hào)數(shù)的本質(zhì)探究
【芯片設(shè)計(jì)】論RTL中always語法的消失術(shù)
【芯片設(shè)計(jì)】代碼即注釋,注釋即代碼
【芯片設(shè)計(jì)】700行代碼的risc處理器你確實(shí)不能要求太多了
入職芯片開發(fā)部門后,每天摸魚之外的時(shí)間我們要做些什么呢
如何計(jì)算系統(tǒng)的outstanding 和 burst length?
芯片搬磚日!け扑缽(qiáng)迫癥的關(guān)鍵詞不對(duì)齊事件
熟人社會(huì)里,一群沒有社會(huì)價(jià)值的局外人

本帖子中包含更多資源

您需要 登錄 才可以下載或查看,沒有賬號(hào)?立即注冊(cè)

x
回復(fù)

使用道具

發(fā)表回復(fù)

本版積分規(guī)則

關(guān)閉

站長推薦上一條 /1 下一條


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表