题解 | #使用握手信号实现跨时钟域数据传输#

使用握手信号实现跨时钟域数据传输

http://www.nowcoder.com/practice/2bf1b28a4e634d1ba447d3495134baac

数据打两拍后(d0_r, d1_r)才能使用(d1_r),要制造脉冲信号不能使用d0_r,因为大概率还会有亚稳态,得再延一个周期得到d2_r,用d1_r和d2_r制造脉冲

`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 data_ack_d0_r;
    reg data_ack_d1_r;
    reg data_ack_d2_r;
    
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            data_ack_d0_r <= 'd0;
            data_ack_d1_r <= 'd0;
            data_ack_d2_r <= 'd0;
        end
        else begin
            data_ack_d0_r <= data_ack;
            data_ack_d1_r <= data_ack_d0_r;
            data_ack_d2_r <= data_ack_d1_r;
        end
    end

    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            data <= 'd0;
        end
        else if (data_ack_d1_r & !data_ack_d2_r) begin
            data <= data == 'd7 ? 'd0 : data + 'd1;
        end
    end
    
    reg [3-1:0] cnt_r;
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            cnt_r <= 'd0;
        end
        else if (data_ack_d1_r & !data_ack_d2_r) begin
            cnt_r <= 'd0;
        end
        else if (data_req) begin
            cnt_r <= cnt_r;
        end
        else begin
            cnt_r <= cnt_r + 'd1;
        end
    end
    
    
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            data_req <= 'd0;
        end
        else if (data_ack_d1_r) begin
            data_req <= 'd0;
        end
        else if (cnt_r == 'd4) begin
            data_req <= 'd1;
        end
    end
endmodule


module data_receiver(
	input clk_b,
	input rst_n,
	input [3:0]data,
	input data_req,
	output reg data_ack
	);
    
    reg data_req_d0_r;
    reg data_req_d1_r;
    reg data_r;
    always @(posedge clk_b or negedge rst_n) begin
        if (!rst_n) begin
            data_req_d0_r <= 'd0;
            data_req_d1_r <= 'd0;
        end
        else begin
            data_req_d0_r <= data_req;
            data_req_d1_r <= data_req_d0_r;
        end
    end
    
    always @(posedge clk_b or negedge rst_n) begin
        if (!rst_n) begin
            data_r <= 'd0;
            data_ack <= 'd0;
        end
        else if (data_req_d1_r) begin
            data_r <= data;
            data_ack <= 'd1;
        end
        else begin
            data_ack <= 'd0;
        end
    end
    
    
    
endmodule
全部评论
module data_receiver中,data_r的位宽设置和data不匹配。不过牛客的tb看起来是自己做了个receiver逻辑,所以检查不到。
1 回复 分享
发布于 2022-07-31 01:35
你说得很有道理
点赞 回复 分享
发布于 2023-05-22 16:58 上海
感谢提醒 谢谢
点赞 回复 分享
发布于 2022-09-06 09:35 四川

相关推荐

点赞 评论 收藏
分享
10-13 13:49
南京大学 财务
饿魔:笑死我了,你简直是个天才
点赞 评论 收藏
分享
评论
21
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务