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

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

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 data_ack_r, data_ack_rr;
    wire pos_data_ack;
    assign pos_data_ack = !data_ack_rr & data_ack_r;
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            data_ack_r  <= 0;
            data_ack_rr <= 0;
        end else begin
            data_ack_r  <= data_ack;
            data_ack_rr <= data_ack_r;
        end
    end
    reg [2:0] cnt;
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            cnt <= 0;
        end else if (cnt == 'd4) begin
            cnt <= 0;
        end else if (!data_req) begin
            cnt <= cnt + 1;
        end
    end
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            data_req <= 0;
        end else if (cnt == 'd4) begin
            data_req <= 1;
        end else if (pos_data_ack) begin
            data_req <= 0;
        end
    end
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            data <= 0;
        end else if (pos_data_ack) begin
            data <= data + 1;
        end else if (data == 'd7) begin
            data <= 0;
        end
    end
endmodule
module data_receiver (
    input clk_b,
    input rst_n,
    output reg data_ack,
    input [3:0] data,
    input data_req
);
    reg [3:0] data_reg;
    reg data_req_r, data_req_rr;
    wire pos_data_req;
    assign pos_data_req = !data_req_rr & data_req_r;
    always @(posedge clk_b or negedge rst_n) begin
        if (!rst_n) begin
            data_ack <= 0;
        end else if (pos_data_req) begin
            data_ack <= 1;
        end else begin
            data_ack <= 0;
        end
    end
    always @(posedge clk_b or negedge rst_n) begin
        if (!rst_n) begin
            data_reg <= 0;
        end else if (pos_data_req) begin
            data_reg <= data;
        end
    end
endmodule

如果一个always块中的寄存器信号只有一种则不需要加begin end:

`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_r, data_ack_rr;
    wire pos_data_ack;
    assign pos_data_ack = !data_ack_rr & data_ack_r;
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            data_ack_r  <= 0;
            data_ack_rr <= 0;
        end else begin
            data_ack_r  <= data_ack;
            data_ack_rr <= data_ack_r;
        end
    end
    reg [2:0] cnt;
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) cnt <= 0;
        else if (cnt == 'd4) cnt <= 0;
        else if (!data_req) cnt <= cnt + 1;
    end
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) data_req <= 0;
        else if (cnt == 'd4) data_req <= 1;
        else if (pos_data_ack) data_req <= 0;
    end
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) data <= 0;
        else if (pos_data_ack) data <= data + 1;
        else if (data == 'd7) data <= 0;
    end
endmodule
module data_receiver (
    input clk_b,
    input rst_n,
    output reg data_ack,
    input [3:0] data,
    input data_req
);
    reg [3:0] data_reg;
    reg data_req_r, data_req_rr;
    wire pos_data_req;
    assign pos_data_req = !data_req_rr & data_req_r;
    always @(posedge clk_b or negedge rst_n) begin
        if (!rst_n) data_ack <= 0;
        else if (pos_data_req) data_ack <= 1;
        else data_ack <= 0;
    end
    always @(posedge clk_b or negedge rst_n) begin
        if (!rst_n) data_reg <= 0;
        else if (pos_data_req) data_reg <= data;
    end
endmodule

本题一次性答对,要点在于:

  1. data_ack和data_req握手信号在不同时钟域产生,因此均需要寄存器打两拍生成边沿检测
  2. 通过边沿控制握手信号的翻转和数据发射与接收
  3. 注意边界条件,data为0-7,cnt为0-4

该题可视为数据传输协议的最简版本

全部评论

相关推荐

想玩飞盘的菠萝蜜在春...:上交✌🏻也拒?
点赞 评论 收藏
分享
皮格吉:不,有的厂子面试无手撕,可以试试。都是一边学一边面。哪有真正准备好的时候,别放弃
无实习如何秋招上岸
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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