仍然基于【示例1】的RTL代码。
分频后,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根据向下计数生成,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}
这样定义的时钟与波形相符。