题解 | #使用握手信号实现跨时钟域数据传输#
使用握手信号实现跨时钟域数据传输
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 ); //=========================================================================\\ //*****************************define sinals*******************************\\ //=========================================================================\\ reg [2:0] cnt_wait ; reg data_ack_r0 ; reg data_ack_r1 ; //=========================================================================\\ //*****************************main code***********************************\\ //=========================================================================\\ //data_ack 跨时钟域处理 always@(posedge clk_a or negedge rst_n)begin if(!rst_n)begin data_ack_r0 <= 1'b0 ; data_ack_r1 <= 1'b0 ; end else begin data_ack_r0 <= data_ack ; data_ack_r1 <= data_ack_r0 ; end end //data_req 边沿检测实现 数据请求信号的拉低 然后 通过等待5个时钟周期的cnt实现拉高 always@(posedge clk_a or negedge rst_n)begin if(!rst_n) data_req <= 1'b0 ; else if(data_ack_r0 && !data_ack_r1) data_req <= 1'b0 ; else if(cnt_wait == 'd4 ) data_req <= 1'b1 ; else data_req <= data_req ; end //cnt_wait 只有在数据响应信号为低电平的时候才会进行计数,目的是计算等待的5个时间间隔 always@(posedge clk_a or negedge rst_n)begin if(!rst_n) cnt_wait <= 'd0 ; else if(cnt_wait == 'd4) cnt_wait <= 'd0 ; else if(data_req == 'd0) cnt_wait <= cnt_wait + 1'b1 ; else cnt_wait <= cnt_wait ; end //data always@(posedge clk_a or negedge rst_n)begin if(!rst_n) data <= 'd0 ; else if(data_ack_r0 && !data_ack_r1) data <= data + 1'b1 ; else data <= data ; end endmodule `timescale 1ns/1ns module data_receiver( input clk_b , input rst_n , input [3:0] data , input data_req , output reg data_ack ); //=========================================================================\\ //*****************************define sinals*******************************\\ //=========================================================================\\ reg data_req_r0 ; reg data_req_r1 ; reg [3:0] data_reg ; //=========================================================================\\ //*****************************main code***********************************\\ //=========================================================================\\ //data_req 输入信号需要打两拍进行跨时钟域处理 always@(posedge clk_b or negedge rst_n)begin if(!rst_n)begin data_req_r0 <= 1'b0 ; data_req_r1 <= 1'b0 ; end else begin data_req_r0 <= data_req ; data_req_r1 <= data_req_r0 ; end end //data_reg always@(posedge clk_b or negedge rst_n)begin if(!rst_n) data_reg <= 'd0 ; else if(data_req_r0 && !data_req_r1) data_reg <= data ; else data_reg <= data_reg ; end //data_ack 通过上边沿检测实现响应信号ack的生成 always@(posedge clk_b or negedge rst_n)begin if(!rst_n) data_ack <= 1'b0 ; else if(data_req_r0 && !data_req_r1) data_ack <= 1'b1 ; else data_ack <= 1'b0 ; end endmodule