create_generated_clock符合设计真实状态很重要
- 不是所有的invert clock与non-invert clock都有直接的反相关系
- 另外一种计数器方式生成的时钟存在一定阶段的反相关系
- 定义 cnt_div约束
- 频率切换的问题
- cnt_div与 upcnt_div是反相关系
仍然基于【示例1】的RTL代码。
不是所有的invert clock与non-invert clock都有直接的反相关系
分频后,normal_div2与 inverted_div2有明确的反相关系。但是 div4和 div8不是。这与具体设计直接相关。
另外一种计数器方式生成的时钟存在一定阶段的反相关系
无论2分频、4分频、8分频其实都一样,下面的波形以4分频为例。
那么为什么不直接使用counter[2], counter[1], counter[0]生成时钟,然后通过mux选择一个?
这样也可以,只不过必须建立所有counter寄存器的时钟,才能遍历时钟路径。如果在计数器后面使用一个寄存器来生成,定义最高频率,也能遍历时钟路径,有机会少定义很多时钟。这个视设计环境而定。
需要注意,在cnter配置相同时,这两种RTL的时钟频率略有不同。
cnter | 直接定义在counter/q | 定义在后一级寄存器q |
---|---|---|
0 | 不分频 | 2分频 |
1 | 2分频 | 4分频 |
3 | 4分频 | 8分频 |
7 | 8分频 | 16分频 |
本示例代码使用 定义在后一级寄存器q。
定义 cnt_div约束
频率切换的问题
从仿真可以看到,更换分频时,不应该工作,等频率变化稳定之后,恢复工作。尤其是启动阶段。
cnt_div与 upcnt_div是反相关系
cnt_div根据向下计数生成,upcnt_div根据向上计数生成,相位正好相反,如果两者一起使用,或者如果其中一个与其它时钟一起使用,或者在当第一个生成时钟就要正式用于工作,那么必须准确定义与clk的相位关系。
create_generated_clock -name cnt_div2 [get_pins cnt_div_reg/Q] -divide_by 2 -master clk -source [get_ports clk] -invert
create_generated_clock -name upcnt_div2 [get_pins upcnt_div_reg/Q] -divide_by 2 -master clk -source [get_ports clk]
report_clocks:
Clock Period Waveform Attrs Sources
clk 20.00 {0 10} {clk}
cnt_div2 40.00 {20 40} G {cnt_div_reg/Q}
inv_clk_div2 40.00 {20 40} G {inverted_div2_reg/Q}
nom_clk_div2 40.00 {0 20} G {normal_div2_reg/Q}
sht_clk_div2 40.00 {10 30} G {clkout_reg/Q}
upcnt_div2 40.00 {0 20} G {upcnt_div_reg/Q}
这样定义的时钟与波形相符。