目录
1 介绍
使用握信号是最古老的跨时钟域传递数据信号的方式

将双时钟域分为两个独立系统
2 握手步骤
1 发送器发送xreq信号,表示有效数据已经发送
2 把xreq同步到接收器的时钟域yclk上
3 接收器识别到xreq的同步的信号yreq2后,锁存数据总线上的信号
4 接收器发出yack,表示接受了数据
5 发送器在识别同步的xack2后,将下一个数据放到数据总线上
时序图如图

安全的将一个数据发送到接收器需要5个时钟周期
3 握手信号的要求
数据在发送时钟域至少稳定两个时钟上升沿
请求xreq信号的宽度应该超过两个上升沿时钟,否则从高到低时钟传递可能无法捕捉到该信号。
4 握手信号的缺点
传输单个数据的延迟比使用FIFO传输相同的数据延迟要大的多。
5 代码实现
module handshack(
input yclk,
input yrst_n,
input xreq, //请求信号,高电平有效
input[7:0] datain,
output yack, //应答信号,高电平有效
output[7:0] dataout
);
//req上升沿检测
reg yreq1, yreq2,yreq3;
always @(posedge yclk or negedge yrst_n)
if(!rst_n) begin
reqr1 <= 1'b0;
reqr2 <= 1'b0;
reqr3 <= 1'b0;
end
else begin
//将xreq跨时钟到yclk,并进行同步
yreq1 <= xreq;
yreq2 <= yreq1;
yreq3 <= yreq2;
end
//pos_req2比pos_req1延后一个时钟周期,确保数据被稳定锁存
wire pos_req1 = yreq1 & ~yreq2; //req上升沿标志位,高有效一个时钟周期
wire pos_req2 = yreq2 & ~yreq3; //req上升沿标志位,高有效一个时钟周期
//数据锁存
reg[7:0] dataout_r;
always @(posedge yclk or negedge rst_n)
if(!rst_n)
dataoutr <= 8'h00;
else if(pos_req1) //检测到req有效后锁存输入数据
dataout_r <= datain;
assign dataout = dataoutr;
//产生应答信号ack
reg yack_r;
always @(posedge yclk or negedge rst_n)
if(!rst_n)
yackr <= 1'b0;
else if(pos_req2)//确保数据被稳定锁存后,发送yack
yackr <= 1'b1;
else if(!req)
yack_r <= 1'b0;
assign yack = yack_r;
endmodule
参考《硬件架构的艺术》

本文详细介绍了跨时钟域数据传输中常用的握手信号机制,包括握手步骤、信号要求及其实现代码。通过五个时钟周期确保数据安全传输,但同时也存在传输延迟较大的缺点。代码示例展示了如何在Verilog中实现握手信号的同步和数据锁存。
5979

被折叠的 条评论
为什么被折叠?



