《硬件架构的艺术》读书笔记(四)跨时钟域传输

第3章:处理多个时钟

 

3.1跨时钟域数据传输简介

主要难点:

1.满足建立时间和保持时间条件;

2.避免产生亚稳态;

 

建立时间:在时钟脉冲到来前,输入数据需要保持稳定的时间。

保持时间:在时钟脉冲到来后,输入数据仍需保持稳定的时间。

(即输入数据在时钟触发沿前后均需要保持稳定相应的时间)

 

3.4多时钟设计的处理技术

 

1.时钟命名法:

系统时钟:sysy_clk,发送时钟:tx_clk,接收时钟:rx_clk

 

同一时钟域的时钟也应当使用相同的前缀:如sys_rom_addr,sys_rom_data

 

方便脚本处理,提高接口可读性,提高团队工作效率

 

2.分块化设计

1)每个模块都应当在单个时钟下工作;

2)在信号跨时钟域传输时,使用同步器模块,将信号同步;

3)同步器模块规模应尽可能小。

 

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

3.同步器模块

 

双级同步器:

电路:

《硬件架构的艺术》读书笔记(四)跨时钟域传输

时序:

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

当出现的亚稳态回到稳态的时间超过一个采样时钟周期时,也会产生亚稳态传输,此时就应当使用三级同步器

 

电路:

《硬件架构的艺术》读书笔记(四)跨时钟域传输

时序:

《硬件架构的艺术》读书笔记(四)跨时钟域传输

当使用的级数越多,产生亚稳态的概率越低,但大多数设计中使用两级同步电路就可以满足需求,只有在时钟频率较高的设计中,才会用到三级同步器

 

 

3.5跨时钟域

 

数据跨时钟域传输的两种方法

1.使用握手信号的方式

2.使用异步FIFO

 

 

 

在异步时钟域传输中,多个时钟源于同一时钟,并且它们的相位和频率是已知的,则可以看成跨同步时钟域的时钟。

 

1)同频零相位时钟

实际不算跨时钟域传输,等效为同一时钟;

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

2)同频恒定相位时钟

当相位差固定时,只要满足建立/保持时间,就可以正确传输,但是要注意组合逻辑的时延设计;

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

3)非同频、可变相位差时钟

1.整数倍频时钟

 

一个时钟是另一个时钟的整数倍,并且有效边沿的相位差是可变的。最小相位差是中等于较快时钟的时钟周期。

 

快时钟域到慢时钟域传输时,为了避免数据丢失,数据应当至少保持一个目的周期的稳定转态,这可以通过源时钟计数来完成。

慢时钟域到快时钟域传输时,数据均能采集到

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

2.非整数倍频时钟

 

此种条件下比较复杂,大体分为三种情况:

 

1)在源时钟和目的时钟有效沿之间有足够大的相位差,所以不会产生亚稳态;

clk1为5ns,clk2为10ns,最小相位差为2.5ns,可以满足建立保持时间。

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

2)源时钟和目的时钟有效沿非常接近,导致产生亚稳态问题。

在慢时钟域到快时钟域传输时,如下图,可以发现会产生数据不连贯的现象(产生亚稳态,但是在下一边沿即正常采样),

但是不会丢失数据,这是由于数据信号的稳定时间超过一个目的周期;

当在快时钟域到慢时钟域传输时,只要保证数据信号稳定时间大于一个目的周期即可。

 

clk1为10ns,clk2为7ns,最小相位差差在49,50ns产生,为0.5ns,这时不满足建立保持时间

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

3)两个时钟沿在许多连续的有效沿都很接近,这与异步时钟很相似

 

clk1为10ns,clk2为9ns,会产生4个连续周期,时钟沿很近

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

此时会产生很多亚稳态,需要进行同步,为了不丢失数据,数据应保持2个目的时钟周期,适用于两个方向的传输。

 

3.6握手信号方法

 

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

时序如下:需要同步x_req和y_ack,一个数据从发送器传输到接收器,需要5个时钟周期

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

握手信号要求

数据在发送时钟域内稳定至少两个时钟上升沿(等待req的同步);

请求信号x_req宽度应该超过两个上升沿时钟,避免由快到慢时钟域数据丢失。

 

3.7同步FIFO

先入先出存储器,常用于跨时钟域数据传输。双端口RAM可以使得FIFO的读写操作可以独立进行。

 

同步FIFO架构

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

通过读写指针产生读写地址,写指针指向下一个要写入的地址,读指针指向下一个要读取的地址,有效的读写使能信号使读写指针递增。

当产生fifo_empty信号,表示fifo中没有数据,不可以读取;

当产生fifo_full信号,表示fifo中数据已满,不可以写入。

 

 

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

产生空、满信号的方法:

一、累加比较读写指针

fifo_full 逻辑代码:

[email protected](posedge clk or negedge reset_n)

begin: fifo_full_gen

if(~reset_n)

fifo_full <= 1'b0;

else if(wr_fifo && rd_fifo)

;//do nothing

else if(rd_fifo)

fifo_full <= 1'b0;

else if(wr_fifo && (rd_ptr = wr_ptr + 1'b1))

fifo_full <= 1'b1;

end

 

fifo_empty 逻辑代码:

[email protected](posedge clk or negedge reset_n)

begin: fifo_empty_gen

if(~reset_n)

fifo_empty <= 1'b0;

else if(wr_fifo && rd_fifo)

;//do nothing

else if(wr_fifo)

fifo_emptyl <= 1'b0;

else if(wr_fifo && (wr_ptr = rd_ptr + 1'b1))

fifo_empty <= 1'b1;

end

 

二、计数器表示当前fifo状态

 

3.8异步FIFO

 

用于对性能要求较高的设计中,尤其是时钟延迟比系统资源更为重要的环境中。

 

3.8.1使用格雷码

 

格雷码产生亚稳态的几率远小于二进制码计数。

 

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

当异步FIFO位于满或空的状态时,需要把读写指针进行同步。

FIFO满:

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

同步写指针需要两个周期的延迟,在此期间,FIFO一直保持满的状态,不能写入,这可以避免数据丢失。

 

FIFO空:

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

同理,空状态时,也需要把读指针同步到写时钟域中,也会延迟两个周期。

 

3.8.3使用格雷码实现FIFO指针

 

使用二进制加法器的格雷码计数器

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

格雷码与二进制码的转换

 

格雷码转二进制码:

 

binn-1 = grayn-1

bini = grayi ^ bini+1

即bin = grayi ^ gray i+1 ^ grayi+2 ^…..^grayn-1

 

verilog代码;

module gray_to_bin(bin,gray)

parameter SIZE = 4;

input [SIZE - 1: 10] bin;

output [SIZE-1:10] gray;

reg [SIZE-1 :0]bin;

 

integer I;

[email protected](*)

for(i = 0,i<=SIZE,i++)

bin[i]= ^(gray >>1);

endmodule

 

二进制码转格雷码:

 

grayn-1 = binn-1

grayi = bini ^ binn+1

 

verilog代码:

module  bin_to_gray(bin,gray)

parameter SIZE = 4;

input [SIZE - 1: 0] bin;

output [SIZE-1 : 10] gray;

assign gray = (bin >> 1) ^ bin;

endmodule

 

3.8.3.3格雷码计数器

verilog代码:

module gray_counter(clk,gray,inr,reset_n)

parameter SIZE = 4;

input clk,inr,reset_n;

output [SIZE-1:0] gray;

reg [SIZE-1] gray_temp,gray,bin_temp,bin;

 

integer I;

[email protected](*)

begin:gray_bin_gray

for(i=0;i<SIZE;i++)

b[i] = ^(gray >> i);

bin_temp = bin +inr;

gray_temp = (bin_temp >> 1) ^ bin_temp;

end

 

 

[email protected](posedge clk or negedge reset_n)

begin:gray——registered

if(~reset_n)

gray <={SIZE{1'b0}};

else

gray <= gray_temp;

end

endmodule

 

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

3.8.4FIFO满和FIFO空的产生

 

当二进制码指针最高有效位不同,其余位相同时,FIFO为满;

当二进制码的所有为都相同时,FIFO为空。

 

当直接用格雷码实现计算FIFO空和FIFO满进,需要4个格雷码-二进制码转换器;

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

 

 

3.8.5双n位格雷码计数器用于FIFO空满产生逻辑

 

创建2个格雷码计数器,一个n位,一个n-1位

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

 

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

FIFO空产生的条件:

此时为格雷码计数器

verilog代码为:

[email protected](posedge clk or negedge reset_n)

begin:fifo_mpty_gen

if(~reset_n)

fifo_empty <= 1'b1;

else

fifo_empty<= (rd_getmp == wr_ptr_sync);  //当前读指针被暂存,与被同步后的写指针比较

end

 

FIFO满条件的产生:

《硬件架构的艺术》读书笔记(四)跨时钟域传输

 

1.当FIFO为空,即rd_ptr == wr_ptr==0,

2.连续写,直到FIFO满,此时wr_ptr==7,rd_ptr=0;

3.连续读,直到FIFO空,rd_ptr==wr_ptr==1

 

但是在位于7,8时,会产生错误的位信号,所以我们将读写指针的MSB和第二MSB异或,所得到的的值进行对比,若一致,则为空

verilog代码如下:

wire rd_2nd_msb =rd_ptr_sync[SIZE ^ rd_ptr_sync[SIZE-1]];

wire wr_2nd_msb =wr_ptr_sync[SIZE ^ wr_ptr_sync[SIZE-1]];

[email protected](posedge clk or negedge reset_n)

begin:fifo_full_gen

if(~reset_n)

fifo_full <= 1'b0;

else

fifo_full <= ((wr_gtemp[SIZE] != rd_ptr_sync[SIZE]) && (rd_2nd_msb == wr_2nd_msb) && (wr_gtemp[SIZE-2:0] == rd_ptr_sync[SIZE-2:0]));

end