赞
踩
使用握手信号是在两个不同域之间传输数据的有效方式,如下图所示:
使用握手信号xack和yreq,系统X发给系统Y,下面是使用握手信号传输数据的例子:
1)发送器系统X将数据放到数据总线上并发出xreq请求信号,表示有效数据已经发送到接收器系统Y的数据总线上
2)把xreq信号同步到接收器的时钟域yclk上。
3)接收器在识别xreq同步信号yreq2后,锁存数据总线上的信号
4)接收器发出确认信号yack,表示其已经接受了数据
5)接收器发出的yack信号同步到发送时钟xclk上
6)发送器在识别同步的ack信号后,将下一个数据放到数据总线上
握手信号的时序图如下所示:
数据应该在发送时钟域内稳定至少两个时钟上升沿,请求信号xreq的宽度应该超过两个上升沿时钟,否则从高速时钟的低速时钟域传递可能无法捕捉到该信号。缺点是是延迟太大(相比于FIFO)。
模块框图如下
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
模块框图如下:
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
模块框图如下:
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
testbench代码如下:
`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
波形如下所示:
可知仿真正确。
自己基础还很薄弱,继续加油!!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。