时序约束高级进阶使用详解四:Set_False_Path
目录
一、背景
二、Set_False_Path
2.1 Set_false_path常用场景
2.2 Set_false_path的优势
2.3 Set_false_path设置项
2.4 细节区分
三、工程示例
3.1 工程代码
3.2 时序约束如下
3.3 时序报告
3.4 常规场景
3.4.1 设计代码
3.4.2 约束场景
3.4.3 约束对象总结
四、参考资料
一、背景
在进行时序分析时,工具默认对所有的时序路径进行分析,在实际的设计中,存在一些路径不属于逻辑功能的,或者不需要进行时序分析的路径,使用set_false_path对该路径进行约束,时序分析时工具将会直接忽略路径不进行分析。
二、Set_False_Path
2.1 Set_false_path常用场景
可以设置为false path的场景包括
a) 跨时钟域中添加的进行两次同步的逻辑单元
b) 只在FPGA通电启动时的配置寄存器
c) 复位或测试的逻辑模块
d) 异步的分布式RAM中读时钟和写时钟之间的路径
非功能路径示例如下,在两个触发器中级联了两个选择器,选择器的选项信号相同,因此,两个MUX不会同时有效,Q到D的时序路径时不存在。
2.2 Set_false_path的优势
a)减少运行时间:将一些路径设置为false path后,时序分析工具无需耗费时间对该路径进行分析,也不需要对非功能模块路径进行优化,可以节省时间
b)提高QOR(quality of results):将路径设置为false path可以极大地提高QOR,综合,布局后的质量,优化设计也会极大地受工具尝试解决的时序问题影响。
因为如果非功能模块的路径存在时序违例时,工具可能尝试去修复这些违例,这不仅可能会导致设计(如逻辑复制)而优化复杂,也可能因为非功能模块有更大的违例而忽略了实际功能模块的违例问题。只有正确的设置约束才能获取最好的结果。
2.3 Set_false_path设置项
set_false_path设置包含Targets和Options两个子界面,Targets中主要是From,Through,To三个对象的设置
Start Point/From:设置false path的起点,可以为Cell pins,clocks,cells,I/O ports,也可指定应用到设置对象的上升沿或下降沿,默认为上升沿和下降沿都有效;
rise_from:约束在路径起点的上升沿有效
fall_from:约束在路径起点的下降沿有效
Through Points:设置false path经过的中间路径,可以为Nets,cells,cell pins,也可指定应用到设置对象的上升沿或下降沿,默认为上升沿和下降沿都有效;
rise_through:约束在路径经过单元的上升沿有效
fall_through:约束在路径经过单元的下降沿有效
End Points/To:设置false path的终点,可以为Cell pins,clocks,cells,I/O ports,也可指定应用到设置对象的上升沿或下降沿,默认为上升沿和下降沿都有效;
rise_to:约束在路径终点的上升沿有效
fall_to:约束在路径终点的下降沿有效
Options中可以对约束路径做一些限定
Setup:设置约束仅对路径的Setup不进行分析
Hold:设置约束仅对路径的hold不进行分析
rise:设置约束对路径的上升沿都不进行分析
fall:设置约束对路径的下降沿都不进行分析
reset_path:在设置false_path前移除路径上的其他时序例外
2.4 细节区分
a)多个-through时,顺序不同结果不同,下面两条约束不是等价的,第一条表示先通过cell1/pin1,再通过cell2/pin2的路径,第二条约束则相反
set_false_path -through cell1/pin1 -through cell2/pin2
set_false_path -through cell2/pin2 -through cell1/pin1
b)get_cells连接多个单元时,表示从复位端口reset到多个cells(ff1_reg,ff2_reg,ff3_reg)中的路径都将设为false path
set_false_path -from [get_ports reset] -to [get_cells {ff1_reg ff2_reg ff3_reg}]
c)不对两个异步时钟clk1,clk2间的路径进行分析,只会将从clk1到clk2间的路径设置为false path
set_false_path -from [get_clocks clk1] -to [get_clocks clk2]
d)如果要对clk1到clk2,clk2到clk1的路径都设置为false path,则需要两条约束命令
set_false_path -from [get_clocks clk1] -to [get_clocks clk2]
set_false_path -from [get_clocks clk2] -to [get_clocks clk1]
e)当需要对多个异步时钟间都不进行时序分析时,对异步时钟两两间设置false path则太繁琐,此时可使用set_clock_groups代替
set_clock_groups -name clk_group -asynchronous -group [get_clocks clk1] -group [get_clocks clk2] -group [get_clocks clk3]
f)在两个寄存器间的非正常逻辑功能路径中,设置false path可以只使用两个through,而不用指定start point和end point,以下图设计
命令中MUX1/a0和MUX2/a1位置不能换,交换后则表示先经过MUX2/a1再经过MUX1/a0
set_false_path -through [get_pins MUX1/a0] -through [get_pins MUX2/a1]
f)对于异步双端口分布式RAM,写操作和RAM的时钟是同步的,读操作可以不同步,因此,在写时钟和读时钟间设置false path符合设计需求,rd_clk为读时钟,wr_clk为写时钟,设置从写寄存器到读寄存器的false path,实现方式如下
set_false_path -from [get_cells <write_registers>] -to [get_cells <read_registers>]
三、工程示例
3.1 工程代码
以几种常见场景的示例进行说明set_false_path的使用
module false_path(clkA,clkB,data_in,data_out,clk,async_rst,async_rst_reg,
config_en,mode,config_reg,scan_en,scan_in,scan_out,scan_data_out,a,b,result);
input clkA,clkB,data_in;
output reg data_out;
reg data_reg;
reg data_meta;
input clk,async_rst;
output reg async_rst_reg;
input config_en,mode;
output reg config_reg;
input scan_en,scan_in;
output scan_out, scan_data_out;
reg scan_reg; // 扫描链寄存器
input wire [3:0] a, b;
output reg [7:0] result;
reg [7:0] temp;
reg [1:0] cycle_count;// 用于两级同步的寄存器,clkA和clkB间的时序不需要分析
always @(posedge clkA) data_reg <= data_in; // 第一级同步
// 两级同步器(防止亚稳态)
always @(posedge clkB)
begindata_meta <= data_reg; // 第一级同步data_out <= data_meta; // 第二级同步
end//异步复位信号路径,不需要分析async_rst和clk的时序
always @(posedge clk or negedge async_rst)
beginif (!async_rst) async_rst_reg <= 1'b0; // 异步复位else async_rst_reg <= data_in;
end//上电配置信,上电后config_en固定不变,因为mode为配置信号,固定不变,故不需要分析mode到config_reg的时序always @(posedge clk) beginif (config_en) config_reg <= (mode == 1'b0) ? data_in : ~data_in;else config_reg <= 1'b0;
end//测试模块中,在scan_en有效时,scan_in到scan_reg的路径不需要分析
always @(posedge clk) beginif (scan_en) scan_reg <= scan_in; // 测试模式下,数据来自 scan_inelse scan_reg <= data_in; // 正常模式下,数据来自 data_in
end
assign scan_out = scan_reg;
assign scan_data_out = scan_reg;//多周期路径,计数值cycle_count到temp的路径不需要分析
always @(posedge clk)
beginif (cycle_count == 2'b00) temp <= a * b; // 第1周期:计算乘法else if (cycle_count == 2'b01) temp <= temp + 1; // 第2周期:加1else result <= temp; // 第3周期:输出结果 cycle_count <= cycle_count + 1;
endendmodule
3.2 时序约束如下
#时钟约束
create_clock -period 10.000 -name clk -waveform {0.000 5.000} [get_ports clk]
create_clock -period 10.000 -name clkA -waveform {0.000 5.000} [get_ports clkA]
create_clock -period 10.000 -name clkB -waveform {0.000 5.000} [get_ports clkB]
#端口约束
set_input_delay -clock [get_clocks clk] 0.123 [get_ports {{a[0]} {a[1]} {a[2]} {a[3]} async_rst {b[0]} {b[1]} {b[2]} {b[3]} config_en data_in mode scan_en scan_in}]
set_output_delay -clock [get_clocks clk] 0.123 [get_ports -regexp -filter { NAME =~ ".*" && DIRECTION == "OUT" }]
#时序不分析约束
set_false_path -from [get_clocks clkA] -to [get_clocks clkB]
set_false_path -from [get_ports async_rst] -to [all_registers]
set_false_path -from [get_ports scan_in] -to [get_cells scan_reg_reg]
#set_false_path -from [get_ports {{a[0]} {a[1]} {a[2]} {a[3]}}] -to [get_cells {{result_reg[0]} {result_reg[1]} {result_reg[2]} {result_reg[3]} {result_reg[4]} {result_reg[5]} {result_reg[6]} {result_reg[7]}}]
set_false_path -from [get_ports mode]
set_false_path -from [get_cells {{cycle_count_reg[0]} {cycle_count_reg[1]}}] -to [get_cells {{temp_reg[0]} {temp_reg[1]} {temp_reg[2]} {temp_reg[3]} {temp_reg[3]_i_2} {temp_reg[4]} {temp_reg[5]} {temp_reg[6]} {temp_reg[7]} {temp_reg[7]_i_3}}]
3.3 时序报告
用于两级同步的寄存器,clkA和clkB间的时序不需要分析
异步复位信号路径,不需要分析async_rst和clk的时序,但复位信号的释放需要分析
上电配置信号,上电后config_en固定不变,因为mode为配置信号,固定不变,故不需要分析mode到config_reg的时序
测试模块中,在scan_en有效时,scan_in到scan_reg的路径不需要分析
多周期路径,计数值cycle_count到temp的路径不需要分析
3.4 常规场景
3.4.1 设计代码
下面将针对约束对象细节进行说明,设计如下
module SetFalsePath(D1,D2,D3,D4,I0,I1,I2,clkA,clkB,out,out1,out2);
input D1,D2,D3,D4,I0,I1,I2,clkA,clkB;
output reg out,out1,out2;
reg FF1,FF2,FF3,FF4;
wire n_lut3,n_lut6;
always @(posedge clkA) FF1 <= D1;
always @(posedge clkA) FF2 <= D2;
always @(posedge clkA) FF3 <= D3;
always @(posedge clkA) FF4 <= D4; LUT3 #(.INIT(8'hF1) // Specify LUT Contents) LUT3_inst (.O(n_lut3), // LUT general output.I0(FF1), // LUT input.I1(FF2), // LUT input.I2(FF3) // LUT input);
LUT6 #(.INIT(64'h0001001010000100) // Specify LUT Contents) LUT6_inst (.O(n_lut6), // LUT general output.I0(I0), // LUT input.I1(I1), // LUT input.I2(I2), // LUT input.I3(n_lut3), // LUT input.I4(FF4), // LUT input.I5(n_lut3) // LUT input);always @(posedge clkA) out <= n_lut6;
always @(posedge clkB) out1 <= n_lut6;
always @(posedge clkA) out2 <= FF4;
endmodule
schematic如下图,三个触发器FF1,FF2,FF3输出连接到一个LUT3_inst,然后与触发器FF4共同输入到LUT_inst。
基础约束主要是主时钟以及输入输出端口的约束
create_clock -period 10.000 -name clkA -waveform {0.000 5.000} [get_ports clkA]
create_clock -period 10.000 -name clkB -waveform {0.000 5.000} [get_ports clkB]
set_input_delay -clock [get_clocks clkA] 0.123 [get_ports {D1 D2 D3 D4 I0 I1 I2}]
set_output_delay -clock [get_clocks clkB] 0.123 [get_ports -regexp -filter { NAME =~ ".*" && DIRECTION == "OUT" }]
3.4.2 约束场景
a)约束from对象类型为get_cells和get_ports下降沿false path
set_false_path -fall_from [get_cells FF1_reg]
set_false_path -fall_from [get_ports D1]
因为FF1_reg的clk输入都为上升沿,所以没有对应生效的false_path
对于D1的输出net为下降沿f是约束生效
b) 约束through对象的类型Cells和Nets为false path
set_false_path -fall_through [get_cells LUT3_inst]
set_false_path -rise_through [get_pins LUT6_inst/I4]
LUT3_inst的输出n_lut3为下降沿,约束生效
LUT6_inst/I4的约束效果
c)约束To对象的类型Cells和I/O port为false path
set_false_path -reset_path -rise_to [get_cells out1_reg]
set_false_path -fall_to [get_ports out2]
rise_to为out1_reg,out1_reg的D端口输入为n_lut6,对应为上升沿,约束生效
out2端口的输入信号为下降沿f,约束生效
d)约束包含多个对象,部分对象不是有效的from/through/to
以from包含多个对象为例,其中只有FF1_reg为有效的start point
set_false_path -from [get_cells {FF1_reg LUT3_inst LUT6_inst}]
有效的起点约束生效,无效的起点直接忽略
f)所有路径设置false path,对所有起点的时钟进行约束
set_false_path -from [all_clocks]
g)指定多个through,在设置through时,可以按照时序路径经过先后顺序指定路径,如约束先上升沿经过LUT3_inst,再以下降沿经过LUT6_inst的路径
set_false_path -rise_through [get_cells LUT3_inst] -fall_through [get_cells LUT6_inst]
对应的路径约束生效
3.4.3 约束对象总结
Set_False_path各约束对象与边沿生效的关系如下图
四、参考资料
用户手册:ug903-vivado-using-constraints-en-us-2022.2.pdf