牛客刷题——使用握手信号实现跨时钟域数据传输

分别编写一个数据发送模块和一个数据接收模块,模块的时钟信号分别为clk_a,clk_b。两个时钟的频率不相同。数据发送模块循环发送0-7,在每个数据传输完成之后,间隔5个时钟,发送下一个数据。请在两个模块之间添加必要的握手信号,保证数据传输不丢失。

握手信号的要求

数据应该在发送时钟域内稳定至少两个时钟上升沿。
请求信号”xreq"的宽度应该超过两个上升沿时钟,否则从高速时钟域低速时钟域传递可能无法捕捉到该信号。

握手信号的特点

跨时钟域传输单个数据的延迟比使用FIFO传输相同的数据要大得多

发送的数据不能连续,也不能太快,必须在req拉低的时候才能开始一个新数据的发送。如果在req拉高的时候又来了新的数据,这个数据就会被丢掉。所以对于连续数据的跨时钟域同步一般是采用异步缓存的方式

`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;
reg [3:0] cnt;

//收到的ack打两拍 降低亚稳态
always@(posedge clk_a or negedge rst_n)
	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

//收到ack之后 可以在总线上放下一个数据
always@(posedge clk_a or negedge rst_n)
	if(!rst_n)
		data <= 'd0;
	else if(data_ack_reg1 & ~data_ack_reg2)
		data <= data + 1;

//收到ack  间隔五个时钟周期 发送下一个数据
always@(posedge clk_a or negedge rst_n)
	if(!rst_n)
		cnt <= 'd0;
	else if(data_ack_reg1 & ~data_ack_reg2)
		cnt <= 'd0;
	else if(data_req)
		cnt <= cnt;
	else	
		cnt <= cnt + 1'b1;

//计数到4  则拉高req代表输入数据有效,收到ack之后 req即可拉低
always@(posedge clk_a or negedge rst_n)
	if(!rst_n)
		data_req <= 1'b0;
	else if(cnt == 3'd4)
		data_req <= 1'b1;
	else if(data_ack_reg1 & ~data_ack_reg2)
		data_req <= 1'b0;

endmodule

module data_receiver(
	input clk_b,
	input rst_n,
	output reg data_ack,
	input [3:0]data,
	input data_req
	);

reg data_req_reg1;
reg data_req_reg2;

//req打拍 降低亚稳态
always@(posedge clk_b or negedge rst_n)
	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

//收到req 就可以将ack拉高
always@(posedge clk_b or negedge rst_n)
	if(!rst_n)
		data_ack <= 1'b0;
	else if(data_req_reg2)
		data_ack <= 1'b1;
	else 
		data_ack <= 1'b0;

endmodule

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值