跨时钟域处理(三)---握手

在跨时钟域(一)中,我们介绍了打两拍的方法,尽管这个方法可以有效处理单bit跨时钟域信号的亚稳态问题,但是当发送方的时钟比接收方的时钟快时,有可能出现信号有效时间过段,接收方采样不到的情况。握手就是解决这一问题的有效方法,同时,握手还可以解决多bit跨时钟域信号的同步。本文就对该方法作一介绍。

同步握手

同一时钟控制下的握手过程比较简单,这里以著名的AXI4协议为例,如下图所示
在这里插入图片描述
发送方要发送数据的时候,就拉高VALID信号,同时把要发送的数据放到数据总线上,接受方看到VALID信号为高,并且自己也有时间接受数据,于是拉高READY信号,表示数据已经被接收,发送方看到接受方已完成数据的接收,于是拉低VALID信号,同时接收方也拉低READY信号,一次握手完成。可以看到,在上图的情况中,数据的读取发生在VALID和READY信号同为高的时候,这就是一个典型的握手过程。

异步握手

在跨时钟域的情况下,握手的过程略有不同,首先,为了防止亚稳态的出现,我们必须将VALID信号同步到接收方的时钟域中,同时,接收方拉高的READY信号也必须同步到发送方的时钟域中,才能被使用。与此同时,接收方在拉高READY信号之后,还需经过几个周期才会同步到发送方的时钟域,因此VALID信号不会马上拉低,进而接收方同步过来的VALID信号也不会马上拉低,这会导致接收方以为是下一个VALID信号的到来。因此,为了解决这个问题,我们不检测VALID的高电平信息,转而检测VALID的上升沿信息,同理READY信号同步的时候也这么做。
RTL代码如下:
sender.sv

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/22 20:50:31
// Design Name: 
// Module Name: sender
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module sender(
input logic sclk,
input logic rst,
input logic start,
input logic [31:0] data,
output logic valid,
output logic [31:0]sdata,
input logic ready                            //从另一个时钟域来的ready信号 
    );
logic ready_ff1;
logic ready_ff2;
logic ready_ff3;
logic pulse;
assign pulse=ready_ff2&&~ready_ff3;                        //检测read_ff3上升沿
always_ff@(posedge sclk,posedge rst)
if(rst)
begin
    ready_ff1<=0;
    ready_ff2<=0;
    ready_ff3<=0;
end
else
begin
    ready_ff1<=ready;
    ready_ff2<=ready_ff1;
    ready_ff3<=ready_ff2;
end
//valid
always_ff@(posedge sclk,posedge rst)
if(rst)
   valid<=0;
else if(start)
   valid<=1;
else if(pulse)
   valid<=0;
//sdata
always_ff@(posedge sclk,posedge rst)
if(rst)
   sdata<=0;
else if(start)
   sdata<=data;

endmodule

上述代码中的pulse信号就是对VALID上升沿的检测。
receiver.sv

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/22 21:15:54
// Design Name: 
// Module Name: receiver
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module receiver(
input logic rclk,
input logic rst,
input logic [31:0]sdata,                 //来自另一个时钟域的sdata
input logic valid,                       //来自另一个时钟域的valid
output logic ready,
output logic [31:0] dout
    );
logic valid_ff1;
logic valid_ff2;
logic valid_ff3;
logic pulse;
//valid信号同步至rclk时钟域
always_ff@(posedge rclk)
begin
    valid_ff1<=valid;
    valid_ff2<=valid_ff1;
    valid_ff3<=valid_ff2;
end
//pluse
always_comb
begin
    pulse=valid_ff2&&~valid_ff3;                     //检测valid_ff3的上升沿
end
//dout
always_ff@(posedge rclk,posedge rst)
if(rst)
    dout<=0;
else if(pulse)                                    
    dout<=sdata;
//ready
always_ff@(posedge rclk,posedge rst)
if(rst)
   ready<=0;
else if(pulse)
   ready<=1;
else
   ready<=0;
endmodule

top模块

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/22 20:49:47
// Design Name: 
// Module Name: handshake
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module handshake(
input logic rclk,
input logic sclk,
input logic rst,
input logic start,
input logic [31:0] data
    );
logic ready;
logic valid;
logic [31:0] sdata;
logic [31:0] dout;
sender U1(.*);
// input logic sclk,
// input logic rst,
// input logic start,
// input logic [31:0] data,
// output logic valid,
// output logic [31:0]sdata,
// input logic ready                            //从另一个时钟域来的ready信号 
//     );
receiver U2(.*);
// input logic rclk,
// input logic rst,
// input logic [31:0]sdata,                 //来自另一个时钟域的sdata
// input logic valid,                       //来自另一个时钟域的valid
// output logic ready,
// output logic [31:0] dout
endmodule

测试平台

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/22 21:41:49
// Design Name: 
// Module Name: test_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module test_tb;
parameter PERIOD_S = 10;
parameter PERIOD_R = 17;
logic rclk;
logic sclk;
logic rst;
logic start;
logic [31:0] data;
//rclk
initial begin
    rclk=0;
    forever begin
        #(PERIOD_R/2) rclk=~rclk;
    end
end
//sclk
initial
begin
    sclk=0;
    forever
    begin
        #(PERIOD_S/2) sclk=~sclk;
    end
end
//rst
initial
begin
    rst=1;
    #50
    rst=0;
end
//start
initial
begin
    start=0;
    #(100+$random%100)
    start=1;
    #(PERIOD_S)
    start=0;
end
//data
initial
begin
    data=23;
end
handshake U(.*);
// input logic rclk,
// input logic sclk,
// input logic rst,
// input logic start,
// input logic [31:0] data
//     );
endmodule

仿真波形
在这里插入图片描述

  • 10
    点赞
  • 107
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA硅农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值