文章目录
- 为什么要握手
- 握手信号无非3种可能
 
- 怎样实现握手
- 案例一:数据反压
 
- 参考链接
 
为什么要握手
-  跨时钟域处理: 
  
-  握手信号法其实也用到了脉冲展宽的方法,只是展宽信号的变化条件不同。因为如果不对脉冲进行展宽,慢速时钟域的时钟很有可能无法采集到快速时钟域的信号,所以要在脉冲展宽的基础上加反馈信号,即握手机制。 
握手信号无非3种可能
- valid先变高:上游master提供的valid信号随数据一起拉高,但下游slave过一段时间才能准备好ready信号
  
- ready先变高:
  
- valid、ready一起变高:
  
怎样实现握手
案例一:数据反压
- 代码
`timescale 1ns/1nsmodule handshake(input   clk,input   rst_n,input           valid_i,input   [7:0]   data_i,output          ready_o,output  [7:0]   data_o,input           ready_i,output          valid_o
);reg [7:0]   data_o_r;
reg valid_o_r;assign ready_o = ready_i;always@(posedge clk or negedge rst_n)beginif(!rst_n)begindata_o_r <= 8'b0;end else if(valid_i && ready_i)begindata_o_r <= data_i * 2;end
endalways@(posedge clk or negedge rst_n)beginif(!rst_n)beginvalid_o_r <= 1'b0;end else if(ready_i)beginvalid_o_r <= valid_i;end
endassign data_o = data_o_r;
assign valid_o = valid_o_r;endmodule
- testbench
`timescale 1ns/10psmodule handshake_tb();reg clk;
reg rst_n;reg         valid_i;
reg [7:0]   data_i;
wire        ready_o;wire    data_o;
reg     ready_i;
wire    valid_o;always #10 clk = ~clk;initial beginclk = 0;rst_n = 0;data_i = 8'd0;valid_i = 1'd0;ready_i = 1'd1;#15rst_n = 1'b1;#15rst_n   <= 1'b1;data_i  <= 8'b0000_1000;valid_i <= 1'd0;    //upstream data invalidready_i <= 1'd1;    //downstream ready#20data_i <= 8'b0111_1000;valid_i <= 1'd1;     //upstream data valid#20data_i  <= 8'b0100_0100;    //upstream data change#20valid_i <= 1'd0;     //upstream data invalid#20data_i  <= 8'b0010_0100;valid_i <= 1'd1;    //upstream data validready_i <= 1'd0;    //downstream not ready#20ready_i <= 1'b1;    //downstream ready#20valid_i <= 1'b0;    //upstream data invalid#500$stop();
endhandshake u_handshake(.clk            (clk    ),.rst_n          (rst_n  ),.valid_i        (valid_i),.data_i         (data_i ),.ready_o        (ready_o),.data_o         (data_o ),.ready_i        (ready_i),.valid_o        (valid_o)    );endmodule
结果
 
参考链接
- Verilog手撕代码(8)握手机制
- cdc跨时钟域处理-结绳握手法