在 RTL 中实现时钟门控的正确方法是什么?
时钟门控信号只能在锁存器关闭时切换,否则可能会出现毛刺和亚稳态问题。对于高电平有效锁存器,门控信号应在时钟的下降沿进行切换。低电平有效锁存器的上升沿。
通常你会使用边缘敏感触发器来保持latch_update_en
以防止选通信号上出现噪声。
always_ff @(negedge clk)
latch_update_en <= next_latch_update_en;
always_comb
gated_clk = (* clock_gating = "clk" *) clk & latch_update_en;
always_latch
if(gated_clk)
latch_data <= new_data;
提醒:如果您只有锁存器设计:边沿触发触发器只是主/从锁存器
always_latch
if (clk)
sync_latch_update_en <= next_latch_update_en;
always_latch
if (!clk)
latch_update_en <= sync_latch_update_en;
该工具在将时钟直接与另一个使能信号在always_comb块中进行“与”合成时是否遇到困难?
大多数综合确实存在直接与时钟进行“与”运算的问题。如何使用门控并不总是直观的。合成器的库中通常有许多 AND 门可供选择,每个 AND 门都有不同的回转、偏斜,并将其加载到输入组合上。虽然功能相同,A & B
然后会得到不同的时间结果B & A
.
从合成器库中实例化显式单元会缩小了解和预期行为的可能性。预定义的时钟门控单元还具有合成器使用的属性。属性包括用于平衡时钟树的时序信息(设计中用于管理负载和寄生的缓冲器放置)。
一些合成器支持在 RTL 中设置属性标签(例如:// synthesis attributes
or (* attributes *)
)而不需要显式实例化单元。没有具体说明如何执行的标准,因此请参阅用户手册。
使用定制时钟门控单元的目的是什么?
自定义单元是综合库中预先定义的单元,具有已知的时序信息、负载平衡和其他属性。有了这些信息,合成器就知道在哪里以及如何添加或校准时钟树中的缓冲区延迟。这确保非门控触发器在门控触发器之前看不到时钟边沿。
_____ _____
IN -------------|D Q|-----|D Q|--- OUT
| | | |
|\ |\ | | | |
+-| >| >---|> | +-|> |
| |/ |/ |_____| | |_____|
| ___ |
CLK -+-| \ |
| & )-------------+ BALANCED CLOCK : correct data sampled
GATE --|___/
如果没有指导,门控翻牌可能会出现延迟时钟。偏差会导致对错误的数据进行采样。
_____ _____
IN -------------|D Q|-----|D Q|--- OUT
| | | |
| | | |
+----------|> | +-|> |
| |_____| | |_____|
| ___ |
CLK -+-| \ |\ |\ |
| & )---| >| >----+ UNBALANCED CLOCK : wrong data sampled
GATE --|___/ |/ |/