题解 | #使用握手信号实现跨时钟域数据传输#
使用握手信号实现跨时钟域数据传输
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
查看8道真题和解析
阿里云成长空间 747人发布