题解 | 使用握手信号实现跨时钟域数据传输
使用握手信号实现跨时钟域数据传输
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 [2:0] ack_reg;
reg [2:0] count;
//跨时钟域,此处打2拍避免亚稳态
always@(posedge clk_a or negedge rst_n) begin
if(!rst_n)
ack_reg <= 3'b0;
else
ack_reg <= {ack_reg[1:0],data_ack};
end
//ack上升沿
assign ack_posedge = !ack_reg[2] && ack_reg[1];
always@(posedge clk_a or negedge rst_n) begin
if(!rst_n)
count <= 3'b0;
else if(ack_posedge)
count <= 3'b0;
else
count <= count + 1'b1;
end
always@(posedge clk_a or negedge rst_n) begin
if(!rst_n) begin
data <= 3'b000;
data_req <= 1'b0;
end
else if(count == 3'b100)
data_req <= 1'b1;
else if(ack_posedge) begin
data_req <= 1'b0;
data <= data + 1'b1;
end
end
endmodule
module data_receiver(
input clk_b,
input rst_n,
input data_req,
input [3:0] data,
output reg data_ack
);
reg [3:0] data_reg;
reg [2:0] req_reg;
always@(posedge clk_b or negedge rst_n) begin
if(!rst_n)
req_reg <= 3'b0;
else
req_reg <= {req_reg[1:0],data_req};
end
//req上升沿
assign req_posedge = !req_reg[2] && req_reg[1];
always@(posedge clk_b or negedge rst_n) begin
if(!rst_n) begin
data_ack <= 1'b0;
end
else if(req_reg[1]) begin
data_ack <= 1'b1;
end
else begin
data_ack <= 1'b0;
end
end
always@(posedge clk_b or negedge rst_n) begin
if(!rst_n) begin
data_reg <= 4'b0;
end
else if(req_posedge) begin
data_reg <= data;
end
end
endmodule

