转:https://blog.csdn.net/bleauchat/article/details/96857247
下图是一个基本的握手通信方式。所谓握手,意即通信双方使用了专用控制信号进行状态指示。这个控制信号既有发送域给接收域的,也有接收域给发送域的,有别于前面的单向控制信号检测方式
使用握手协议方式处理跨时钟域数据传输,只需要对双方的握手信号(req和ack)分别使用脉冲检测方法进行同步。在具体实现中,假设req、ack、data总线在初始化时都处于无效状态,发送域先把数据放入总线,随后发送有效的req信号给接收域。接收域在检测到有效的req信号后锁存数据总线,然后回送一个有效的ack信号表示读取完成应答。发送域在检测到有效ack信号后撤销当前的req信号,接收域在检测到req撤销(需要进行边沿检测)后也相应撤销ack信号,此时完成一次正常握手通信。此后,发送域可以继续开始下一次握手通信,如此循环。该方式能够使接收到的数据稳定可靠,有效的避免了亚稳态的出现,但控制信号握手检测会消耗通信双方较多的时间。以上所述的通信流程如下图所示:
-
-
module handshake(
-
input clk,
//50MHZ时钟
-
input rst_n,
//复位信号
-
input req,
//数据发送请求信号
-
input [
15:
0]data_in,
//数据输入
-
output reg ack,
//应答信号
-
output [
15:
0]data_out
-
);
-
-
reg req1,req2,req3;
//req输入同步信号
-
reg [
15:
0]data_in_r;
//输入数据寄存器
-
wire pos_req1,pos_req2;
-
//---------通过三级寄存器同步异步输入信号req--------
-
always@(posedge clk
or negedge rst_n)
begin
-
if(!rst_n)
begin
-
req1 <=
1
'b0;
-
req2 <= 1'b0;
-
req3 <=
1
'b0;
-
end
-
else begin
-
req1 <= req;
-
req2 <= req1;
-
req3 <= req2;
-
end
-
end
-
//--------------检测req1、req2的上升沿---------------
-
assign pos_req1 = req1 && ~req2;
-
assign pos_req2 = req2 && ~req3;
-
//----------在检测到pos_req1上升沿时,锁存数据-------
-
always@(posedge clk or negedge rst_n)begin
-
if(!rst_n)begin
-
data_in_r <= 16'd0;
-
end
-
else
begin
-
if(pos_req1)
begin
-
data_in_r <= data_in;
-
end
-
end
-
end
-
assign data_out = data_in_r;
-
//----------在检测到pos_req2上升沿时,发出ack应答信号,表示数据已经锁存-------
-
//----------检测req信号,如果req信号取消,则ack也取消-----------------------
-
always@(posedge clk
or negedge rst_n)
begin
-
if(!rst_n)
begin
-
ack <=
1
'b0;
-
end
-
else begin
-
if(pos_req2)begin
-
ack <= 1'b1;
-
end
-
else
if(!req)
begin
-
ack <=
1
'b0;
-
end
-
end
-
end
-
endmodule