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

`timescale 1ns/1ns
module data_driver(
	input clk_a,
	input rst_n,
	input data_ack,
	output reg [3:0]data,
	output reg data_req
	);
//1、对于发送端,data 输出需满足 data_req==1 ,且 data_req 需保持直到收到接收端回传的 data_ack,之后转低电平;
//2、data 循环 0-7 , 位宽为4, 需额外限制;变化时间点可选在收到回传 data_ack 时自加一
//3、接受到 data_ack 后需等待5个clk
//4、发送端需与接收端同步,选择 data_ack 的变化作为各项操作时机

//4、获取 data_ack 变化:【跨时钟域需打两拍消除亚稳态】
    reg data_ack0,data_ack_flag;
	always @ (posedge clk_a or negedge rst_n)
		if (~rst_n) begin
            data_ack0 <= 1'b0;
            data_ack_flag <= 1'b0;
        end else begin
            data_ack0 <= data_ack;
            data_ack_flag <= data_ack0;
        end

//2、data 变化
	always @ (posedge clk_a or negedge rst_n)
		if (~rst_n) begin
            data <= 3'd0;
        end else if (data == 3'd7) begin
            data <= 3'd0; 
        end else if (data_ack_flag) begin
            data <= data + 1'b1;
        end

//3、等待5个clk
reg [2:0] cnt;
	always @ (posedge clk_a or negedge rst_n)
		if (~rst_n) begin
            cnt <= 3'd0;
        end else if (data_ack_flag) begin
            cnt <= 3'd0;
        end else if (cnt == 3'd4) begin
            cnt <= 3'd0; 
        end else begin
            cnt <= cnt + 1'b1;
        end

//4、发送
	always @ (posedge clk_a or negedge rst_n)
		if (~rst_n) begin
            data_req <= 1'b0;
        end else if (cnt == 3'd4) begin
            data_req <= 1'b1;
        end else if (data_ack_flag) begin
            data_req <= 1'b0;
        end
endmodule

module data_receiver(
	input  clk_b,
	input  rst_n,
	input  data,
	output data_req,
	output reg data_ack
	);

//获取 data_req 变化
reg data_req0,data_req_flag;
always @ (posedge clk_b or negedge rst_n)
    if (~rst_n) begin
        data_req0 <= 1'b0;
        data_req_flag <= 1'b0;
    end else begin
        data_req0 <= data_req;
        data_req_flag <= data_req0;
    end

// 发送 data_ack
always @ (posedge clk_b or negedge rst_n)
    if (~rst_n) begin
        data_ack <= 1'b0;
    end else if (data_req_flag) begin
        data_ack <= 1'b1; 
    end else begin
        data_ack <= 1'b0;
    end

endmodule

全部评论

相关推荐

昨天 18:37
门头沟学院 Java
勇敢的ssr求对象:前面看的有点奔溃,看到只有你是真玩啊,忍不住笑出了声😂
点赞 评论 收藏
分享
04-27 08:59
常州大学 Java
牛客139242382号:《两门以上汇编语言》
点赞 评论 收藏
分享
头像
05-16 11:16
已编辑
东华理工大学 Java
牛客737698141号:盲猜几十人小公司,庙小妖风大,咋不叫她去4️⃣呢😁
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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