Implementierung von Cross-Clock-Domain-Handshake-Signalen (Verilog)

Methode

Die Verwendung von Handshake-Signalen ist eine effektive Möglichkeit, Daten zwischen zwei verschiedenen Domänen zu übertragen, wie in der folgenden Abbildung dargestellt:
Fügen Sie hier eine Bildbeschreibung ein
Mit den Handshake-Signalen xack und yreq sendet System
1) Sendersystem
_
3) Nachdem der Empfänger das xreq-Synchronisationssignal yreq2 erkannt hat, speichert er das Signal auf dem Datenbus.
4) Der Empfänger sendet ein Bestätigungssignal yack, das anzeigt, dass er die Daten akzeptiert hat.
5) Das vom Empfänger gesendete yack-Signal wird mit dem synchronisiert Sendetakt xclk
6) Nach dem Erkennen des synchronen Bestätigungssignals legt der Sender die nächsten Daten auf den Datenbus.
Das Zeitdiagramm des Handshake-Signals ist wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

Anforderungen an das Handshake-Signal

Die Daten sollten für mindestens zwei Taktanstiegsflanken innerhalb der Sendetaktdomäne stabil sein, und die Breite des Anforderungssignals xreq sollte zwei Taktanstiegsflanken überschreiten, da das Signal sonst möglicherweise nicht erfasst wird, wenn es von der langsamen Taktdomäne von weitergeleitet wird die Hochgeschwindigkeitsuhr. Der Nachteil besteht darin, dass die Verzögerung zu groß ist (im Vergleich zu FIFO).

Hardware-Implementierung

Datensendesystem

Das Modulblockdiagramm sieht wie folgt aus
Fügen Sie hier eine Bildbeschreibung ein

module tx_data(
    input   wire            tx_clk      ,
    input   wire            xack2       ,
    input   wire            rst_n       ,
    input   wire            en          ,

    output  reg             xreq        ,
    output  wire    [7:0]   t_data  
);

    reg     [3:0]       data1   ;
    reg     [3:0]       data2   ;

    //在yack2有效时data1和data2更新
    always @(posedge tx_clk or negedge rst_n) begin
        if(!rst_n) begin
            data1 <= 4'd1;
            data2 <= 4'd1;
        end
        else if(xack2) begin
            data1 <= data1 + 4'd1;
            data2 <= data2 + 4'd2;
        end
        else begin
            data1 <= data1;
            data2 <= data2;
        end
    end       

    //xreq信号
    always @(posedge tx_clk or negedge rst_n) begin
        if(!rst_n) begin
            xreq <= 1'b0;
        end
        else if(en) begin
            xreq <= 1'b1;
        end
        else if(xack2) begin
            xreq <= 1'b1;
        end
        else begin
            xreq <= 1'b0;
        end
    end

    assign t_data = {
    
    data1, data2};

endmodule

Datenempfangssystem

Das Modulblockdiagramm sieht wie folgt aus:
Fügen Sie hier eine Bildbeschreibung ein

module rv_data(
    input   wire        rv_clk      ,
    input   wire        rst_n       ,
    input   wire        yreq2       ,
    input   wire [7:0]  r_data      ,

    output  reg         yack        ,
    output  wire [5:0]  result           
);
    /*
        接收到数据的第一周期进行数据计算
        第二周期返回ack信号
    */
    reg             dly1        ;
    reg     [5:0]   result_reg  ;

    always @(posedge rv_clk or negedge rst_n) begin
        if(!rst_n) begin
            yack <= 1'b0;
        end
        else if(dly1) begin
            yack <= 1'b1;
        end
        else begin
            yack <= 1'b0;
        end
    end

    always @(posedge rv_clk or negedge rst_n) begin
        if(!rst_n) begin
            dly1 <= 1'b0;
        end
        else if(yreq2) begin
            dly1 <= 1'b1;
        end
        else begin
            dly1 <= 1'b0;
        end
    end

    always @(posedge rv_clk or negedge rst_n) begin
        if(!rst_n) begin
            result_reg <= 'd0;
        end
        else if(yreq2) begin
            result_reg <= r_data[3:0] + r_data[7:4];
        end
        else begin
            result_reg <= result_reg;
        end
    end

    assign result = dly1 ? result_reg : 6'd0;

endmodule

Asynchrone Handshake-Implementierung

Das Modulblockdiagramm sieht wie folgt aus:
Fügen Sie hier eine Bildbeschreibung ein

module shake_hand_asy(
    input   wire            tx_clk      ,
    input   wire            rv_clk      ,
    input   wire            rst_n       ,
    input   wire            en          ,

    output  wire    [5:0]   result 
);

    wire                xreq    ;
    wire                yack    ;
    wire    [7:0]       data    ;

    reg                 yreq1   ;
    reg                 yreq2   ;
    reg                 xack1   ;
    reg                 xack2   ;

    //xreg的两级同步
    always @(posedge rv_clk or negedge rst_n) begin
        if(!rst_n) begin
            yreq1 <= 1'b0;
            yreq2 <= 1'b0;
        end
        else begin
            yreq1 <= xreq;
            yreq2 <= yreq1;
        end
    end

    //yack的两级同步
    always @(posedge tx_clk or rst_n) begin
        if(!rst_n) begin
            xack1 <= 1'b0;
            xack2 <= 1'b0;
        end
        else begin
            xack1 <= yack;
            xack2 <= xack1;
        end
    end

    tx_data u_tx_data(
    . tx_clk    (tx_clk)    ,
    . xack2     (xack2)     ,
    . rst_n     (rst_n)     ,
    . en        (en)        ,

    . xreq      (xreq)      ,
    . t_data    (data)
);

    rv_data u_rv_data(
     .rv_clk     (rv_clk)    ,
     .rst_n      (rst_n)     ,
     .yreq2      (yreq2)     ,
     .r_data     (data)      ,

     .yack       (yack)      ,
     .result     (result)      
);

endmodule

Wellenformsimulation

Der Testbench-Code lautet wie folgt:


`timescale  1ns/1ns

module tb_shake_hand_asy();

    reg         tx_clk      ;
    reg         rv_clk      ;
    reg         rst_n       ;
    reg         en          ;

    wire [5:0]  result      ;

    initial begin
        tx_clk = 1'b0;
        rv_clk = 1'b0;
        rst_n = 1'b0;
        en = 1'b0;
        #30
        rst_n = 1'b1;
        @(posedge tx_clk);
        en = 1'b1;          //启动
        @(posedge tx_clk);
        en = 1'b0;
    end

    always #15 tx_clk = ~tx_clk;
    always #10 rv_clk = ~rv_clk;

    shake_hand_asy u_shake_hand_asy(
    . tx_clk    (tx_clk)  ,
    . rv_clk    (rv_clk)  ,
    . rst_n     (rst_n)  ,
    . en        (en)  ,

    . result    (result)
);

endmodule

Die Wellenform ist wie folgt:
Fügen Sie hier eine Bildbeschreibung ein
Es ist ersichtlich, dass die Simulation korrekt ist.

Zusammenfassen

Mein Fundament ist immer noch sehr schwach, also arbeite weiter hart! ! ! !

Guess you like

Origin blog.csdn.net/weixin_45614076/article/details/127673883