题解 | #使用握手信号实现跨时钟域数据传输#
使用握手信号实现跨时钟域数据传输
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 ); //data_ack上升沿 reg data_ack_reg1; reg data_ack_reg2; always@(posedge clk_a or negedge rst_n) if(!rst_n) begin data_ack_reg1 <=0; data_ack_reg2 <=0; end else begin data_ack_reg1 <= data_ack; data_ack_reg2 <=data_ack_reg1; end //data_cnt reg [2:0]data_cnt; always@(posedge clk_a or negedge rst_n) if(!rst_n) data_cnt <= 0; else if(data_ack_reg1 && !data_ack_reg2)//data_ack上升沿,表示传输完成,开始计时 data_cnt <= 0;//5个时钟:0,1,2,3,4 else if(data_req)//data_req拉高,开始传数,保持不变 data_cnt <= data_cnt; else data_cnt <= data_cnt + 1'b1; //data_req always@(posedge clk_a or negedge rst_n) if(!rst_n) data_req <= 0; else if(data_cnt == 3'd4) data_req <= 1'b1; else if(data_ack_reg1 && !data_ack_reg2) data_req <= 1'b0; else data_req <= data_req; //data always@(posedge clk_a or negedge rst_n) if(!rst_n) data <= 0; else if(data_ack_reg1 && !data_ack_reg2) begin if(data==4'd7) //发送0-7的循环数据 data <= 4'd0; else data <=data + 1'b1; end else data <= data; endmodule //接收模块 `timescale 1ns/1ns module data_receiver( input clk_b, input rst_n, input data_req, input [3:0]data, output reg data_ack ); //data_req上升沿 reg data_req_reg1; reg data_req_reg2; always@(posedge clk_b or negedge rst_n) if(!rst_n) begin data_req_reg1 <=0; data_req_reg2 <=0; end else begin data_req_reg1 <= data_ack; data_req_reg2 <=data_req_reg1; end //data_ack always@(posedge clk_b or negedge rst_n) if(!rst_n) data_ack <= 0; else if(data_req_reg1) data_ack <= 1'b1; else data_ack <= 0; //data reg [3:0] data_in_reg;//接收数据 always@(posedge clk_b or negedge rst_n) if(!rst_n) data_in_reg <= 0; //要检测上升沿而不是 高信号(会维持两个周期) else if(data_req_reg1 && !data_req_reg2) data_in_reg <= data; else data_in_reg <= data_in_reg; endmodule