Menu Close

异步时钟域RTL设计(1)

在RTL设计中异步时钟域几乎是不可避免的问题,多数复杂的系统都会涉及到异步时钟的处理。处理好异步时钟之间的逻辑电路是关系到系统性能提升,健壮性,安全性的重要环节。本节及后续的内容会针对异步时钟的应用场景,异步时钟的概念,异步时钟的逻辑电路处理,异步时钟约束等进行详细阐述。

  1. 异步时钟域的应用场景

(1)低功耗应用场景

由于系统或芯片的功率直接与系统的时钟频率相关,因此为了降低系统功耗,一般都会提供两个或多个时钟,当系统的主任务完成后就可以进入低功耗状态(睡眠)。处在睡眠状态的系统利用低频率的时钟监控系统是否需要全功能状态。常见的如手机在通话和浏览文字图片时采用频率高的时钟,在待机时就会停止较高的系统时钟而采用较低的时钟监控系统是否有来电,是否有功能键按下等,以便唤醒系统。目前在以ARM的系统设计中往往采用大小核的设计方式也是处于低功耗的应用场景。TI MPS430系列16位单片机内部使用多达7个时钟,可以使系统配置在不同的系统下工作,使系统在不同任务下配置不同的功率。在超低功耗的设计中,由于PLL也是功耗关键部件,因此许多以电池供电系统往往提供独立的实时时钟,一方面提供监控,另一方面可以保持系统的计时信息,在进入低功耗时可以把PLL关闭。典型的低功耗异步时钟系统如图1所示。

%title插图%num

图1 低功耗异步时钟系统示意图

(2)部件或外设需要不同的时钟频率

不同的功能部件运行在不同的时钟频率下可以发挥各自最大性能。如网络图像处理系统中,DDR3的接口时钟可能400MHz,HDMI 的时钟可能为148.5MHz在,网络接口为125M,系统时钟可能为100Mhz等。其他还有I2C 为100/400KHz, SPI 为5Mhz等。 可见一个负载的系统往往会随着不同的功能模块或外设设置不同的时钟。

2. 异步时钟域数据与信号交换

系统中有多个时钟,就形成了不同的时钟域。所谓时钟域是指在某个时钟控制下的时序逻辑,在同一个时钟控制下的时序电路一般称为同步时序电路。同步时序电路一般指在同一时钟下的各个触发器的时钟端都连在一起并统一连接到该时钟上。如图2所示。

%title插图%num

图2 同步时序电路

多数的信号或数据都是在同步时钟的控制下运行,但是既然系统是由不同的时钟域组成,就不可避免的会有异步时钟域间的数据交换。异步时钟域的数据交换涉及到数据的安全采集,亚稳态处理,重复数据丢弃,重要数据丢失等内容,以及时序约束处理等内容。

(1)单信号的不同时钟域的交换

    • 快时钟抓取慢时钟信号
      • 直接抓取:利用快时钟抓取慢时钟的信号一般比较简单,直接采用寄存器寄存即可,为了防止亚稳态的传递,一般要求将要转换的信号寄存两次。Verilog 代码如例1所示:

例1:

module async_signal
( 
input clk1, //low frequency 
input clk2, // high frequency 
input a, //clk1 domain 
output reg sync_clk2_b=0 
); 

reg a_tmp=0;
always@(posedge clk1) 
begin 
a_tmp<=a; 
end

reg b_tmp=0; 
always@(posedge clk2) 
begin 
b_tmp<=a_tmp; 
sync_clk2_b<=b_tmp; 
end
endmodule

 

为了能准确的抓取到原始信号,一般要去快时钟为慢时钟的两倍以上。

      • 重复数据删除

 由于利用快时钟采集慢时钟域的数据,而且异步时钟之间可能在频率上相差很多,因此不可避免出现重复数据,针对这种情况又分为不同的处理办法:

(1)单脉冲指示信号

由于在处理批量数据时,对于批量数据的指示至关重要,因此在不同的时钟域交换时使用比较广泛。低时钟单脉冲信号要求该信号在整个的时序处理过程中没有两个或两个以上的连续的时钟周期内为高电平(高电平指示信号)或低电平(低电平指示信号), 如图3所示,

%title插图%num

图3 单脉冲高电平指示信号

当该信号被异步的高频时钟采样时,不可避免的会有重复数据出现,利用例1可得仿真波形如下:

仿真程序:

`timescale  1ns/1ps
module tb_test_async
();

reg 	      clk1=0;
reg 	      clk2=0;

reg 	      a=0;
reg [3:0]	a_count=0;
wire        sync_clk2_b;

always #10  clk1=~clk1;
always #3   clk2=~clk2;

always@(posedge clk1) begin
a_count<=a_count+1;

case(a_count)
//1,5,6,9,10,11:a<=1'b1;
1:a<=1'b1;
default:a<=1'b0;
endcase

end

async_signal  async_signal_inst
( 
.clk1				(clk1), 
.clk2				(clk2), 
.a					(a), 
.sync_clk2_b	(sync_clk2_b)
); 

endmodule

仿真波形如图4所示,

%title插图%num

图4 单脉冲信号被高倍时钟采样时的重复

      从图4的波形可以看出,由于clk1,clk2的频率不同,单脉冲信号对于clk2 又没有固定的相位关系,因此在高倍时钟采样时出现了信号在该时钟下的重复,而且重复的次数并不惟一。图4中框1标注对于低时钟(clk1)的单脉冲信号,高频时钟采样为4次高电平;而同样的单脉冲信号如框2所示,高频时钟的采样却是3次。当然无论是3次,还是4次都不是源信号的真是含义的表达。那么在出现信号或数据重复时如何处理呢?

      • 提取边沿脉冲:关于提取边沿脉冲已经在多篇文中论述过,这里在总结和回顾一下:
        • 利用信号变换提取边沿脉冲,图5 显示上升沿边沿提取的过程。

%title插图%num

图5

   图5对应的Verilog 代码如下:

module async_signal
( 
input clk1, //low frequency 
input clk2, // high frequency 
input a, //clk1 domain 
output reg sync_clk2_b=0 
); 

reg a_tmp=0;
always@(posedge clk1) 
begin 
a_tmp<=a; 
end



reg b_tmp=0;
reg nb_tmp=0;
reg b_r_pulse=0; 
always@(posedge clk2) 
begin 
b_tmp<=a_tmp; 
nb_tmp<=~b_tmp;
b_r_pulse<=b_tmp&nb_tmp;
sync_clk2_b<=b_tmp; 
end
endmodule

经过脉冲边沿脉冲提取就可以在另一个时钟域内使用了。其它的边沿提取方法可以参照《亚稳态消除及边沿提取Verilog实现》文章中介绍的方法进行。

      • 可以采用握手的方式实现异步时钟域信号间同步

如果在两个时钟利用信号通信,已知通知信号为单脉冲信号,可以经过同步化后利用状态机的方式实现信号重复的消除。下文利用一段式状态机演示如何消除因为过采样造成的信号重复,如例2所示。

                     例2:

module async_signal
( 
input clk1, //low frequency 
input clk2, // high frequency 
input a, //clk1 domain 
output reg sync_clk2_b=0 
); 

reg a_tmp=0;
always@(posedge clk1) 
begin 
a_tmp<=a; 
end

reg b_tmp=0;

reg b_r_pulse=0; 
always@(posedge clk2) 
begin 
b_tmp<=a_tmp; 
sync_clk2_b<=b_tmp; 
end

reg [2:0]  st=0;


always@ (posedge clk2) begin

case(st)
0:begin
  b_r_pulse<=0;
  //insert user code here
 if(sync_clk2_b)begin
   //insert user code here
  b_r_pulse<=1'b1; 
  st<=1;
 end
end
1:begin
 b_r_pulse<=1'b0; 
 //insert user code here
 if(~sync_clk2_b)begin
 //insert user code here
 st<=2;
 end
end
2:begin
  b_r_pulse<=0;
  //insert user code here
 if(sync_clk2_b)begin
   //insert user code here
  b_r_pulse<=1'b1; 
  st<=3;
 end
end
...
endcase

end


endmodule

例2中,当某些行为需要在sync_clk2_b为高电平时只允许在一个时钟周期的执行时,可以判断高电平后执行并立即将状态跳转,如:

if(sync_clk2_b)

begin //insert user code here

b_r_pulse<=1’b1;

st<=3;

end

                   如例2中的行为方式,为了能消除重复信号引起代码的多次执行,需要状态机相邻状态交替判断指示信号的高低电平。这种设计方法也经常被I2C, SPI等数据捕获所采用。

注意:在状态机中使用指示信号进行状态条状时,严禁使用不经同步化的原始信号。如:

 always@(posedge clk2)

if(a)   // 此处不能使用a,或 a_tmp,因为这两个信号与clk2不在同一个时钟域

begin //insert user code here

b_r_pulse<=1’b1;

st<=3;

end

 (2)非单时钟周期脉冲信号如何在快时钟域采集

非单脉冲信号是指低时钟的信号高电平持续的宽度(时钟周期)是随机的,此类信号往往携带数据信息,如图6所示。如何能利用高速时钟恢复该类数据呢?

%title插图%num

图6  非单时钟周期脉冲信号

该类信号要求能准确无误的恢复出原始信号中携带的数据信息,需要采用过采样的方式,而且对采样的时钟有特定的要求。过采样的时钟要求如下:

  • 知道原始信号的时钟频率
  • 过采样时钟频率一般是原始信号(产生原始信号的时钟频率)的4倍或以上。

关于过采样恢复原始数据请参照异步串行高速通信的相关章节的内容。

Verilog自适应位同步信号提取高速异步串行通信的帧同步

  • 慢时钟抓取快时钟域的数据。

 

 

Posted in IC

发表回复

相关链接