相关阅读
Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm=1001.2014.3001.5482
在Design Compiler中,由于分频时钟无法从时钟分频器的输出自动推断,需要使用create_generated_clock命令创建生成时钟,本文不会对生成时钟与create_generated_clock命令进行过多讨论,关于他们两者的详细信息见下面的博客。
静态时序分析:ideal_clock、propagated_clock以及generated_clock的关系及其延迟计算规则(二)https://chenzhang.blog.csdn.net/article/details/140070290SDC命令详解:使用create_generated_clock命令进行约束(上)
https://blog.csdn.net/weixin_45791458/article/details/134236547?ops_request_misc=%257B%2522request%255Fid%2522%253A%252299223a1e0648316debe75df9d6dfc6ca%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=99223a1e0648316debe75df9d6dfc6ca&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-5-134236547-null-null.nonecase&utm_term=%E7%94%9F%E6%88%90%E6%97%B6%E9%92%9F&spm=1018.2226.3001.4450 由于分频器可能有多种描述形式(直接显式例化、通过RTL表示),创建生成时钟的方式也有细微差别,本文的重点就在于此。
直接显式例化
可以选择显式例化用于分频的触发器,如下所示,此时原理图如图1所示。
module freq_div_and_ff (
input wire clk,
input wire rst_n,
input wire din,
output reg q1,
output reg q2
);
wire div_clk_q;
wire div_clk_qn;
DFFX1 u_div (
.Q (div_clk_q),
.QN (div_clk_qn),
.D (div_clk_qn),
.CK (clk)
);
wire clk_div2 = div_clk_q;
always @(posedge clk_div2 or negedge rst_n) begin
if (!rst_n)
q1 <= 1'b0;
else
q1 <= din;
end
always @(posedge clk_div2 or negedge rst_n) begin
if (!rst_n)
q2 <= 1'b0;
else
q2 <= q1;
end
endmodule
图1 显式例化分频器
此时创建生成时钟的方式是较为明确的,如下create_generated_clock命令所示。
create_generated_clock -source [get_pins u_div/CK] -divide_by 2 [get_pins u_div/Q]
通过RTL表示
如果选择通过RTL表示用于分频的触发器,如下所示,此时原理图如图2所示。
module freq_div_and_ff (
input wire clk,
input wire rst_n,
input wire din,
output reg q1,
output reg q2
);
reg div_clk_q;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
div_clk_q <= 1'b0;
else
div_clk_q <= !div_clk_q;
end
wire clk_div2 = div_clk_q;
always @(posedge clk_div2 or negedge rst_n) begin
if (!rst_n)
q1 <= 1'b0;
else
q1 <= din;
end
always @(posedge clk_div2 or negedge rst_n) begin
if (!rst_n)
q2 <= 1'b0;
else
q2 <= q1;
end
endmodule
图2 通过RTL表示分频器
当读取RTL设计时,HDL Compiler会把时序逻辑转化为通用时序单元SEQGEN(或者称为Generic/Unmapped Sequential Cell),综合时才将其映射到具体的触发器或锁存器。
此时创建生成时钟的方式较为模糊,下面给出两种方式。
方法一
可以利用通用时序单元的引脚进行约束,尽管尚未映射到具体的时序单元,但有些信息可以提前知道,比如通用时序单元的名字为信号名加_reg,用一个输入引脚clocked_on表示其时钟(对于触发器),拥有两个输出引脚Q和QN,他们将被映射为时序单元的输出和反向输出引脚,此时生成时钟的约束方式如下create_generated_clock命令所示。
create_generated_clock -source [get_pins div_clk_q_reg/clocked_on] -divide_by 2 [get_pins div_clk_q_reg/Q]
综合过程中的设计变化(例如引脚名的变化)会考虑在内,即综合后使用write_sdc命令输出的约束文件中,以上的命令会变为:
create_generated_clock [get_pins div_clk_q_reg/Q] -name div_clk_q_reg/Q -source [get_pins div_clk_q_reg/CK] -divide_by 2
方法二
方法一的缺点在于:需要维护两套约束,其实可以基于映射后的库引脚名称只创建一套约束并在综合前后都可以使用,使用set_pin_name_synonym命令创建引脚别名可以做到这一点,如下所示。
set_pin_name_synonym CK clocked_on
这表示引脚名CK与clocked_on等价,这样就可以使用以下create_generated_clock命令:
create_generated_clock -source [get_pins div_clk_q_reg/CK] -divide_by 2 [get_pins div_clk_q_reg/Q]