文章目录[隐藏]
1. 概述
ASIC设计成本增加,周期一般为一年,保证芯片第一次流片后可以工作是很重要的。 结构良好、可综合的RTL模块方便集成和复用,下文给出时钟和复位信号的设计建议。
2. 同步设计
在同步设计中,由单个主时钟和单个复位/置位信号驱动设计中所有的时序器件。经验表明对ASIC的时钟域控制最安全的方法就是同步设计。
同步设计中应避免以下几种设计:
-
行波计数器:用触发器的输出来驱动其他触发器的时钟输入,一般会存在问题。此时触发器的时钟并不是同步的,存在相位偏移,若该触发器链很长,延迟累积,会导致采样到错误的数据。
-
门控时钟:门控时钟作为低功耗设计的常用方法,通常由DC工具插入,在RTL除auto_clock_gating控制外,不要对时钟做任何处理,错误设计如下图:
-
双边沿或混合边沿时钟:DDR控制器中会使用,但ASIC中应避免使用。
-
用触发器的输出驱动另一个触发器的异步复位:违反了同步设计原则,第二级触发器的时钟和复位之间存在潜在的竞争条件。
3. 推荐的设计技术
在使用HDL代码进行设计时,理解代码综合结果是很重要的,从硬件角度思考设计(编码风格),这会影响到设计综合的门数和时序性能。
- 避免在设计中出现组合环路:环路中应有寄存器,否则电路会进入振荡;同时该设计是不同综合的,在综合报告中会给出。
- 避免使用延迟:不可综合;
- 避免使用异步脉冲产生器:使用组合逻辑延迟电平信号,延迟信号取反与原信号“相与”,得到“毛刺”脉冲,该脉冲宽度并不是一个时钟周期,典型的上升沿脉冲和下降沿脉冲代码如下:
// dff
always@(posedge clk) begin
m_flag_dff1 <= m_flag;
end
// posedge edge detect
assign m_flag_posedge_pls = m_flag && (!m_flag_dff1);
// negedge edge detect
assign m_flag_negedge_pls = (!m_flag) && m_flag_dff1;
- 避免使用锁存器:锁存器由电平触发,数据输入和输出之间是连通的,故锁存器可以传递毛刺;锁存器本身的时序是模糊的,STA无法分析;锁存器产生的原因源自不完整的"if-else"、“case”语句,在每个分支都应该对always中出现的变量赋值,否则会形成锁存器。
不完整的"if-else"语句产生latch如下图所示:
- 避免使用双沿时钟:ASIC设计中很少遇到,接口模块中倒是会出现;
4. 时钟方案
- 避免内部产生时钟:内部产生的时钟若存在毛刺,对功能和时序会产生严重影响;
- 分频时钟:使用同步计数器的输出直接产生分频时钟信号,避免再对计数器解码等操作后再产生时钟,可能会出现毛刺;
- 避免使用行波计数器
- 避免使用多路时钟:同一个模块使用多个时钟(分时复用,存在时钟切换问题)
- 门控时钟:门控时钟要使用专用电路,不要使用组合逻辑对时钟进行门控操作;
5. 门控时钟方法学
在同步设计中,系统时钟连接到每个寄存器的时钟端,这使得系统的功耗分为三个部分:
- 组合逻辑功耗:组合逻辑输入为寄存器输出,寄存器输出变化时组合逻辑的翻转会产生功耗;
- 触发器功耗:触发器翻转或不翻转均会产生功耗,翻转时功耗更大;
- 时钟树功耗:时钟需要驱动每个寄存器,时钟树随着设计的规模增大变得复杂,时钟树几乎消耗了整个芯片功耗的50%;
时钟树消耗了约50%的功耗,对时钟路径进行门控能大幅降低触发器的功耗,门控时钟可以存在于时钟树的源头(可以降低时钟树的功耗)、末端或两者之间。
5.1 门控时钟电路
5.1.1 不含锁存器的门控时钟电路
不含锁存器的门控时钟使用一个简单的“与”门实现,如下图所示:
由于EN和CLK直接进行“与”操作,正常情况下时钟门控波形如下图所示,EN有效时输出时钟有效,EN无效时关闭时钟以降低寄存器功耗。
不含锁存器的门控时钟电路有两个明显的缺点,导致其在工程中无法使用。
- 毛刺:EN与CLK直接相与,EN的毛刺会直接传递给时钟信号GATE_CLK,导致电路功能错误;
- 过早截断:若不对EN做约束(约束:时钟上升沿到时钟下降沿之间保持常量),会出现过早截断CLK的情况,最后一个时钟周期无法正常驱动电路,导致功能错误。
EN若存在毛刺,则CLK也会存在毛刺,则输出时钟波形下图所示,此时输出时钟存在的毛刺会影响电路的正常工作,如GATE_CLK驱动计数器。
除此之外,不含锁存器的门控时钟电路还有一个缺点,即过早截断时钟脉冲,如下图所示。输出的GATED_CLK的最后一个时钟周期的高电平持续时间小于50%,该时钟不能正常驱动寄存器,从而导致功能错误。
5.1.2 基于锁存器的门控时钟电路
基于锁存器的门控时钟电路在设计中加入一个电平敏感的锁存器,以在时钟活跃沿和不活跃沿之间保持使能信号不变,这样就无需依靠门控电路本身来满足这一要求(不需要再对EN做约束),设计如下图所示。
图中Latch为D-Latch,特性表如下所示,其中Q为当前状态,Q*为次态,CLK低电平有效,D-Latch的输出高电平或低电平的持续时间都是T_clk的整数倍。
CLK | EN | Q | Q* |
---|---|---|---|
1 | X | 0 | 0 |
1 | X | 1 | 1 |
0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 |
0 | 1 | 0 | 1 |
0 | 1 | 1 | 1 |
上述电路的RTL代码如下:
always@(*) begin
if(~clk) begin
E_latch = E | TE;
end
end
assign Eclk = E_latch & clk;
基于锁存器的门控时钟输入只需要在时钟上升沿保持稳定,锁存器就能捕捉到使能信号,进而产生完整的时钟脉冲。该电路避免了输出时钟存在毛刺或尖峰脉冲。尽管如此,该电路还是存在一个不可忽略的缺点,产生使能信号逻辑的延迟(Latch延迟)和时钟到达“与”门的延迟非对齐时,会产生毛刺,如下图所示(情况一):
- 情况一:clock_B延迟大于Latch延迟,第一个时钟周期出现毛刺
- 情况二:clock_B超前于clock(skew<0),此时在最后一个时钟周期出现毛刺。
5.1.3 基于寄存器的门控时钟电路
基于寄存器的门控时钟电路使用寄存器缓存EN,然后再与CLK_B相与,得到GATED_CLK,电路图如下所示:
该电路的时序图如下所示,由于EN由寄存器锁存输出,EN1和CLK_B可认为是同步的,所以不存在“基于锁存器的门控时钟电路”的缺点,上述电路RTL代码实现:
always@(posedge clk) begin
if(en == 1'b1) begin
en1 <= en;
end
end
assign gclk = en1 & clk;
5.1.4 实际使用门控时钟电路
基于以上分析,基于寄存器的门控时钟电路在性能上是最优的,理论上实际芯片应该使用该策略进行寄存器级的门控时钟以降低功耗,但实际芯片中使用的确是“基于锁存器的门控时钟电路”,原因如下:
- 芯片设计一般要求时钟门控率在95%以上(甚至98%以上),芯片中大量的寄存器需要门控时钟单元,而锁存器的面积仅为寄存器的1/2(甚至更小),所以从面积角度考虑会使用“基于锁存器的门控时钟电路”。
- “基于锁存器的门控时钟电路”毛刺问题:大多数ASIC生产厂商都提供“门控时钟单元”作为标准单元库的一部分,所以Latch的延迟和CLK_B的延迟问题可以由厂商解决。
5.2 门控时钟使用
门控时钟的实现可以从模块级和寄存器级分别实现,即从时钟的源头和时钟的末端关闭时钟,当然在源头和末端的中间位置也可以关闭时钟。
5.2.1 模块级门控时钟
模块不工作时,关闭其输入时钟,降低整个模块的功耗,如下图所示。
5.2.2 寄存器级门控时钟
寄存器级的门控时钟不需要设计师手动添加,综合工作会自动插入门控时钟单元,如下图所示。代码风格会决定综合结果,时序逻辑中寄存器的翻转均有对应条件时DC会在综合时插入CG(代码的门控率高,电路上来看该条件用于产生EN信号,而无条件的时序逻辑无法产生门控时钟电路的EN信号),插入CG会增加面积,但当该寄存器输入数据位宽较大时,CG的面积可能小于原组合逻辑的面积。
5.2.3 SRAM门控时钟
SRAM的功耗约占SOC的1/3,当某些SRAM不使用时,可以将其时钟关闭以降低功耗。除此之外,当module包含多个功能时,确定不会使用的电路的时钟也可以关闭,以降低功耗。
6. 复位信号的设计策略
6.1 复位概述
复位的目的是使SOC进入一个能进行稳定操作的确定状态,防止上电后进入随机状态而死机,好的设计会为每个寄存器提供复位信号。但在某些情况下,当流水线的寄存器在高速应用中使用时,应该去掉某些寄存器的复位信号以使设计达到更高性能。
同步复位和异步复位的使用根据设计者的功能,一般来说所有寄存器都需要异步复位和同步复位,其中打N拍(DFF_N)信号不要使用同步复位,否则可能会出现异常的脉冲。
6.2 同步复位设计
同步复位的电路图如下所示:
同步复位的RTL代码如下所示( 同步复位信号未出现在敏感列表中):
always @(posedge clk) begin
if(rst_n == 1'b0) begin
out <= 1'b0;
end
else if(load == 1'b1) begin
out <= in;
end
end
6.3 异步复位设计
6.3.1 异步复位电路
异步复位的电路如下所示:
异步复位的RTL代码如下所示( 敏感列表中需要添加异步复位信号rst_n):
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
out <= 1'b0;
end
else if(load == 1'b1)begin
out <= in;
end
end
6.3.2 异步复位同步释放
在亚稳态的世界中,曾分析过异步复位在移除时可能会造成亚稳态问题,寄存器输出不定态或在一定时间内返回0或1,此时SOC复位失败。
复位信号在产生时可以采用以下设计:
RTL代码如下所示:
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
out_0 <= 1'b0;
out_1 <= 1'b0;
end
else begin
out_0 <= 1'b1;
out_1 <= out_0;
end
end
异步复位信号移除(rst_n :0→1)亚稳态分析:
- 复位信号移除时(T_0):当复位信号移除时导致第一级寄存器输出亚稳态(第一级寄存器输入为高电平、输出为低电平,复位信号移除和上升沿接近时会导致亚稳态),第二级的输出为低电平(第二级寄存器输入为低电平、输出为低电平,复位信号移除和上升沿接近时不会导致亚稳态);
- T_1:第一级寄存器的输出高电平,第二级输出0或1(原因是第一级亚稳态恢复到0或1是未知的)。
- T_2:第一级输出高电平,第二级输出高电平
经过三个周期,可以看到第二级寄存器的输出有两种情况:001或011,均表示复位信号正确移除。
参考资料
- 《芯片架构的艺术》
- https://zhuanlan.zhihu.com/p/139363948
版权声明:本文为CSDN博主「南风在冥想」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shiwq1127/article/details/122833514
暂无评论