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:
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:
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
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:
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:
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:
Es ist ersichtlich, dass die Simulation korrekt ist.
Zusammenfassen
Mein Fundament ist immer noch sehr schwach, also arbeite weiter hart! ! ! !