题解 | #使用握手信号实现跨时钟域数据传输#
使用握手信号实现跨时钟域数据传输
https://www.nowcoder.com/practice/2bf1b28a4e634d1ba447d3495134baac
`timescale 1ns/1ns module data_driver( input clk_a, input rst_n, input data_ack, output reg [3:0]data, output reg data_req ); reg data_ack_delay; reg data_ack_delay_2; wire data_ack_up_edge; always@(posedge clk_a or negedge rst_n)begin if(~rst_n)begin data_ack_delay<=1'b0; data_ack_delay_2<=1'b0; end else begin data_ack_delay<=data_ack; data_ack_delay_2<=data_ack_delay; end end assign data_ack_up_edge = data_ack_delay & ~data_ack_delay_2; reg [2:0] data_cnt; always@(posedge clk_a or negedge rst_n)begin if(~rst_n)begin data_cnt<=3'd0; end else if(data_ack_up_edge)begin data_cnt<=3'd0; end else if(data_req)begin data_cnt<=data_cnt; end else begin data_cnt<=data_cnt+1'b1; end end always@(posedge clk_a or negedge rst_n)begin if(~rst_n)begin data_req<=1'b0; end else if(data_cnt==3'd4)begin data_req<=1'b1; end else if(data_ack_up_edge)begin data_req<=1'b0; end else begin data_req<=data_req; end end always@(posedge clk_a or negedge rst_n)begin if(~rst_n)begin data<=4'd0; end else if(data_ack_up_edge)begin if(data==4'd7) data<=4'd0; else data<=data+1'b1; end else begin data<=data; end end endmodule module data_receiver( input clk_b, input rst_n, input [3:0]data, input data_req, output reg data_ack ); reg [3:0] data_temp; reg data_req_delay; reg data_req_delay_2; wire data_req_up_edge; always@(posedge clk_b or negedge rst_n)begin if(~rst_n)begin data_req_delay<=1'b0; data_req_delay_2<=1'b0; end else begin data_req_delay<=data_ack; data_req_delay_2<=data_req_delay; end end assign data_req_up_edge = data_req_delay & ~data_req_delay_2; always@(posedge clk_b or negedge rst_n)begin if(~rst_n)begin data_temp<=4'd0; data_ack<=1'b0; end else if(data_req_up_edge)begin data_temp<=data; data_ack<=1'b1; end else begin data_temp<=data_temp; data_ack<=1'b0; end end endmodule
首先搞懂一下握手信号的作用是什么?握手信号是用来处理数据在进行跨时钟域传输的时候进行的一种发送和应答信号。在上面题目中数据由快时钟域到慢时钟域传输的时候如果直接使用data数据线直接相连传输就会出现快时钟域数据丢失的问题。为了解决这样的问题就需要进行一种发送应答机制。
第二思考为什么叫握手信号。两个人进行握手的话肯定要有个人要先主动的去和对方握手,然后另外一个人在接收主动方的握手。所以这里的发送方就是主动的一方,他需要先把data_req信号进行驱动拉高。这里题目中说五个clock发送一次数据因此需要一个计数器。当计数器计数到五个clock的时候将data_req拉高。当data_req拉高之后说明此时数据传输开始,由于快时钟域数据发送的较快,数据发送到慢时钟域的时候需要等待慢时钟域捕获沿拉高,因此在data_req拉高之后需要发送的数据保持一段时间,当接收端接收到数据之后发出应答信号之后才表明当前的数据发送完成。一次握手进行完毕。