数据cdc (clock domain cross)

常见的跨时钟有以下相关的问题:

单bit:

单bit 电平信号

单bit 脉冲信号:

慢时钟到快时钟

快时钟到慢时钟

多bit:

多bit 控制数据:

快时钟到慢时钟

慢时钟到快时钟

自带vld 有效信号

不自带vld 有效信号

多bit 连续数据:

慢时钟到快时钟

快时钟到慢时钟

自带vld 有效信号

不自带vld 有效信号

单bit 电平信号

对于电平信号的快时钟,只要遵循3沿原则,就可以实现任意的快慢时钟间的跨时钟。

单bit 脉冲信号

快时钟到慢时钟

快时钟到慢时钟的电平,若2个时钟的频率跨度很大,直接跨时钟,在慢时钟侧有概率会丢掉快时钟传递过来的数据 。

脉冲转电平

为了实现任意跨度的快时钟到慢时钟间脉冲采样。 可以快时钟的plus 转为level 信号。在慢时钟侧,对level 采样并捕获边沿。

脉冲展宽

根据快时钟和慢时钟的频率关系,将快时钟的脉冲信号使用shift reg 后,对脉冲展宽(展宽后的脉冲在慢时钟域满足三个沿的原则)。 在慢时钟域,使用同步器对展宽后的脉冲采样,并捕获器上升沿作为跨时钟后的脉冲信号。

补充说明下,为什么至少有三个沿???

为什么2沿不行,2个沿的情况有以下几种形式:

先下降沿 再上升沿:若慢时钟在上升沿采样,不一定保证t_hd 可以满足

先上升沿 再下降沿:若慢时钟在下降沿采样,不一定保证t_hd 可以满足

而3沿原则可以保证中间的采样沿的t_st和h_hd 时间是充足的。

慢时钟到快时钟

同步器+边沿检测

慢时钟到快时钟,在快时钟侧存在对同一个慢时钟数据的多次采样。 可以使用同步器+边沿检测,实现对快时钟侧的脉冲采样。

NOTE :有时候我们在做设计时,会将脉冲信号直接用2/3 拍DFF 组成的synczr 做同步。这种方式的前提是,设计者做过时钟频率的分析,可以保证。

握手

握手机制在单bit 上,使用的很少。 但是可以精确的保证脉冲可以被同步过去 。握手机制常用与多bit的数据跨时钟。 在单bit的脉冲跨时钟上,可以理解为隐含1bit的 数据跨时钟。

多bit含vld的跨时钟

多bit的数据,在跨时钟时。 若使用同步器跨时钟存在问题: 不能保证所有bit 的稳定时间相同(同步器的一级DFF 同步部分bit,同步器的二级dff 同步部分bit),造成同步后的数据出错。

所以常用的同步方法包括: 握手机制、异步fifo 、gray码转换

burst 数据

对于burst的数据,数据会背靠背的给。 握手机制存在req 和ack 过同步器时间消耗,一次数据同步消耗多个周期,造成数据丢失。

多以对于burst 数据,常采用的异步跨时钟方法时: 异步缓存。

这里也涉及到 异步缓存fifo的最小深度计算:

写快读慢,易造成写满 ;写慢读快,易造成读空。

常见的计算是写或者读是否有背靠背(写玩或者读完一整包后,连续来一整包的写、读)?

例如: 写时钟100Mhz ,读时钟75Mhz ,最大连续包长为1500bytes,fifo 位宽为64bits(8bytes) 。没有背靠背

1500/8 = 188 cycles

写一包需要188 * 10 ns=1880ns。

1880/(1000/75) = 141 cycles

188-141 = 47 。

理论上fifo的最小深度是47 。 但是如果fifo读有延时、fifo 需要吸收前级的pipe(链路上的延时)。 此时fifo深度要加上链路上的时延和读的延时。

如果存在背靠背呢?

也就是写完一包后,继续写一包,可以理解为包长扩展到1500x2=3000 bytes 。 此时理论深度为47x2 = 94。

还有一类题型: 读时钟为75Mhz,但是读侧是3 拍读一次,求fifo深度?

fifo的读频率降为75/3=25Mhz ,没有背靠背下,需要深度为47x3 = 141 。

异步fifo的核心是:

读写ptr的跨时钟生成empty 和full 信号;

gray 和bin的互转;

binary 转gray

gray= bin ^ (bin>>1);

gray 转binary

binn = grayn

binn-1 = grayn-1 ^ binn

......

bin0 = gray0 ^ bin1

读写指针 位宽增加1bit,借助gray 的镜像实现快慢判断:

空 : wr_sync == rd_sync

满: rd_syncn-:2 == ~wr_ptrn-:2 && ( rd_syncn-2:0 == wr_ptrn-2:0 )

满是高位和次高位取反,其他bit相同

控制数据

控制数据,不是每拍数据都有效。 中间的间隔就给了握手处理预留了时间。

cpp 复制代码
//using handshak for data sync 
// data has valid 
module data_vld_sync#(
    parameter DATA_WDTH=8
)(
    input in_clk,
    input rst_n,
    input in_vld,
    input [DATA_WDTH-1:0]in_data,

    input out_clk,
    input out_vld,
    input [DATA_WDTH-1:0]out_data
);


reg [DATA_WDTH-1:0]  in_data_r;
reg req;
reg ack;
reg [2:0] req2dst;
reg [2:0] ack2src;

wire ack2src_pos;
wire req2dst_pos;
wire ack_neg;


assign ack2src_pos = ack2src[1]  && (ack2src[2]==1'b0);
assign req2dst_pos = (req2dst[1] && (req2dst[2]==1'b0);

//req 
always_ff @(posedge in_clk or negedge rst_n) begin
    if(rst_n==1'b0)begin
        req<=1'b0;
    end 
    else if(ack2src_pos)begin
        req <=1'b0;
    end 
    else if(in_vld)begin
        req <=1'b1;
    end 
end

// req2dst 
always_ff @(posedge out_clk or negedge rst_n) begin
    if(rst_n==1'b0)begin
        req2dst <= 3'b0;
    end 
    else begin
        req2dst <=  {req2dst[1:0],req};
    end 
end


//ack
always_ff @(posedge out_clk or negedge rst_n) begin
    if(rst_n==1'b0)begin
        ack <=1'b0;
    end 
    else if(req==0)begin
        ack <=1'b0;
    else if( req2dst_pos )begin
        ack <=1'b1;
    end 
end

// ack2src
always_ff @(posedge in_clk or negedge rst_n) begin
    if(rst_n==1'b0)begin
        ack2src <=3'b0;
    end 
    else begin
        ack2src <= {ack2src[1:0],ack};
    end 
end 


// latch in_data 
always_ff @(posedge clk or negedge rst_n) begin
    if(rst_n==1'b0)begin
        in_data_r <={DATA_WDTH{1'b0}};
    end 
    else if(req==1'b0  && in_vld) begin
        in_data_r <=  in_data;
    end
end

assign out_data =  in_data_r;
assing out_vld  =  req2dst_pos;


endmodule 
相关推荐
博览鸿蒙2 小时前
[特殊字符]AI+FPGA 全栈学习大纲【就业版】定位
人工智能·学习·fpga开发
燎原星火*3 小时前
AD/DA硬件电路设计
fpga开发
GateWorld5 小时前
LCD显示技术完全指南:原理·制造·驱动·FPGA实现之点屏三
fpga开发·lcd显示·fpga点亮屏幕·minilvds
XINVRY-FPGA5 小时前
XC7Z035-2FFG900I Xilinx/AMD Zynq-7000 SoC FPGA
人工智能·嵌入式硬件·计算机视觉·fpga开发·硬件工程·dsp开发·fpga
zlinear数据采集卡20 小时前
基准电压电路深度解析:从理论参数到ZLinear采集卡的精准参考实战
c语言·单片机·嵌入式硬件·fpga开发·自动化
ALINX技术博客1 天前
【黑金云课堂】FPGA技术教程Vitis开发:PS端SD读写
fpga开发·vitis·sd读写
尤老师FPGA1 天前
LVDS系列50:Xilinx Ultrascale系 ADC LVDS接口参考方法(十二)
fpga开发
zlinear数据采集卡1 天前
模拟输入限流保护电路深度解析:从理论原理到ZLinear采集卡的实战设计
c语言·单片机·嵌入式硬件·fpga开发·自动化
Dillon Dong2 天前
【风电控制】FPGA采集Vdc的ADC增益系数解析——从数字码到实际电压的桥梁
算法·fpga开发·变流器·风电控制
ALINX技术博客2 天前
【黑金云课堂】FPGA技术教程FPGA基础:FIFO与Uart通信
fpga开发·uart·fpga·fifo