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

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

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

本题难度不算太大,需要注意的是计数以及握手信号的处理,sop信号以及eop信号的使用
`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_reg1;
    reg             data_ack_reg2;
    wire            data_sop;
    reg    [2:0]    cnt;

    //data_ack signal delay two timeperiod
    always@(posedge clk_a or negedge rst_n) begin
        if(!rst_n) begin
            data_ack_reg1 <= 1'b0;
            data_ack_reg2 <= 1'b0;
        end
        else begin
            data_ack_reg1 <= data_ack;
            data_ack_reg2 <= data_ack_reg1;
        end
    end
    //数据发送开始检测flag
    assign data_sop = (data_ack_reg1 && ~data_ack_reg2);

    always@(posedge clk_a or negedge rst_n) begin
        if(!rst_n)
            cnt <= 3'b0;
        else if(data_sop)
            cnt <= 3'b0;
        else
            cnt <= cnt + 1'b1;
    end

    //循环发送数据0-7
    always@(posedge clk_a or negedge rst_n) begin
        if(!rst_n)
            data <= 4'b0;
        else begin
            if(data_sop)
                data <= data + 1'b1;
            else if(data == 4'd7)
                data <= 4'b0;
            else 
                data <= data;
        end
    end
    //output data_req
    always@(posedge clk_a or negedge rst_n) begin
        if(!rst_n)
            data_req <= 1'b0;
        else if(cnt == 3'd4)
            data_req <= 1'b1;
        else if(data_sop == 1)
            data_req <= 1'b0;
        else 
            data_req <= data_req;
    end 
endmodule
//数据接收模块
module data_receiver(
    input           clk_b,
    input           rst_n,
    input   [3:0]   data,
    input           data_req,
    output          data_ack
    );
    reg            data_ack;
    reg             data_req_reg1;
    reg             data_req_reg2;
    wire             data_eop;
    reg     [3:0]   data_in;
    always@(posedge clk_b or negedge rst_n) begin
        if(!rst_n) begin
            data_req_reg1 <= 1'b0;
            data_req_reg2 <= 1'b0;
        end
        else begin
            data_req_reg1 <= data_req;
            data_req_reg2 <= data_req_reg1;
        end
    end
     //数据接收检测flag
    assign data_eop = data_req_reg1 && ~data_req_reg2;
    always@(posedge clk_b or negedge rst_n) begin
        if(!rst_n) begin
            data_in <= 4'b0;
            data_ack <= 1'b0;
            end
        else if(data_eop) begin
            data_in <= data;
            data_ack <= 1'b1;
            end
        else begin
            data_in <= data_in;
            data_ack <= data_ack;
            end
    end
endmodule

全部评论
data_ack 除了flag 变回0就行?
点赞 回复 分享
发布于 2025-12-09 17:48 新加坡
你这个我仿真一下,你输出了1,data_ack拉高不拉回来,怎么可能对
点赞 回复 分享
发布于 2025-03-14 16:35 广东
终于看见一个data置0的了
点赞 回复 分享
发布于 2024-01-14 10:59 北京

相关推荐

钱嘛数字而已:辅导员肯定不能同意,不然你出事了,他要承担责任。但是,脚和脑子都长在你自己身上,使用它还需要向辅导员报告么? 辅导员必须按流程拒绝你,然后你拿出成年人的态度,做自己的选择。
点赞 评论 收藏
分享
哞客37422655...:你猜为什么福利这么好还得一直追着你问
点赞 评论 收藏
分享
评论
5
收藏
分享

创作者周榜

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