题解 | #使用握手信号实现跨时钟域数据传输#
使用握手信号实现跨时钟域数据传输
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 d_data_ack;
reg d1_data_ack;
reg d2_data_ack;//两拍后的为了上升沿检测用
reg[2:0] cnt;
reg en;
always @(posedge clk_a)begin
d_data_ack<=data_ack;
end
always @(posedge clk_a)begin
d1_data_ack<=d_data_ack;
end
always @(posedge clk_a or negedge rst_n )begin
if(!rst_n)
en<=0;
else if({d1_data_ack,d_data_ack}==2'b01)
en<=1;
else if(cnt==4)
en<=0;
end
always @(posedge clk_a or negedge rst_n )begin
if(!rst_n)
cnt<=0;
else if({d1_data_ack,d_data_ack}==2'b01)
cnt<=0;
else if(cnt==4)
cnt<=0;
else
cnt<=cnt+1;
end
always @(posedge clk_a or negedge rst_n )begin
if(!rst_n)
data_req<=0;
else if({d1_data_ack,d_data_ack}==2'b01)
data_req<=0;
else if (cnt==4)
data_req<=1;
else
data_req<=data_req;
end
always @(posedge clk_a or negedge rst_n )begin
if(!rst_n)
data<=0;
else if({d1_data_ack,d_data_ack}==2'b01)
if(data==7)
data<=0;
else
data<=data+1;
else
data<=data;
end
endmodule
module data_receiver(
input clk_b,
input rst_n,
input [3:0]data,
input data_req,
output reg data_ack
);
reg d_data_req;
reg d1_data_req;
reg [3:0]receive_data;
always@(posedge clk_b)begin
d_data_req<=data_req;
end
always@(posedge clk_b)begin
d1_data_req<=d_data_req;
end
always@(posedge clk_b or negedge rst_n)begin
if(!rst_n)
data_ack<=0;
else if({d1_data_req,d_data_req}==2'b01)
data_ack<=1;
else
data_ack<=0;
end
always@(posedge clk_b or negedge rst_n)begin
if(!rst_n)
receive_data<=0;
else if({d1_data_req,d_data_req}==2'b01)
receive_data<=data;
else
receive_data<= receive_data;
end
endmodule
// module top(
// input clk_a,
// input clk_b,
// input rst_n,
// output [3:0]receive_data
// );
// wire data_ack;
// wire data_req;
// wire [3:0]data;
// data_driver uut(
// .clk_a(clk_a),
// .rst_n(rst_n),
// .data_ack(data_ack),
// .data_req(data_req),
// .data(data)
// );
// data_receiver aat(
// .clk_b(clk_b),
// .rst_n(rst_n),
// .data_ack(data_ack),
// .data_req(data_req),
// .data(data),
// .receive_data(receive_data)
// );
// endmodule
自己写的时候出了点问题,自己写的时候是在CNT+到4的时候才拉高req,cnt加到4又是用ack上升沿实现的,之前设计是让ack先到以后再加。这样出现的问题就是,第一次的时候ack没有识别到req无法拉高,而cnt无法到4 req不会拉高。一直会是0,因此一直计数,记到第一个4产生一个req给他一个初值,在检测到上升沿后cnt置0,重新计数,记到4时数据有效,req拉高发出
