建立余量
保持余量
实例分析
环境:Vivado 2019.2
芯片型号:xc7z020clg484-2
举例子说明怎么使用Reporte Timing Summary
建立源工程
module timing_analyze (
input wire clk ,
input wire reset ,
input wire [ 4: 0] data_in ,
output reg [ 4: 0] data_out
);
reg [ 4: 0] data_tmp_in ;
wire [ 4: 0] data_tmp_out;
wire [ 4: 0] data_tmp2, data_tmp_3, data_tmp_4, data_tmp_5, data_tmp_6, data_tmp_7;
wire [ 4: 0] data_cal_out;
always @ (posedge clk)
if (reset == 1'b1)
data_tmp_in <= 0;
else
data_tmp_in <= data_in;
// 为了增加经过逻辑门的数量,做连续的乘法
assign data_tmp_2 = data_tmp_in * data_tmp_in;
assign data_tmp_3 = data_tmp_2 * data_tmp_in;
assign data_tmp_4 = data_tmp_3 * data_tmp_2;
assign data_tmp_5 = data_tmp_4 * data_tmp_3;
assign data_tmp_6 = data_tmp_5 * data_tmp_4;
assign data_tmp_7 = data_tmp_6 * data_tmp_5;
assign data_cal_out= data_tmp_7;
always @ (posedge clk)
if (reset == 1'b1)
data_out <= 0;
else
data_out <= data_cal_out;
endmodule
添加.xdc文件
设定clk时钟为200MHz,T = 5ns
# create_clock - name clk - period 5.000 [get_ports clk] // err
create_clock -name clk -period 5.000 [get_ports clk]
查看时序报告
Run Systhesis、Run Implementation,可以在Design Runs状态栏看到下面的情况,impl_1一行有红色,表示布线的时序不通过
WNS 代表最差负时序裕量 (Worst Negative Slack)
TNS 代表总的负时序裕量 (Total Negative Slack),也就是负时序裕量路径之和。
WHS 代表最差保持时序裕量 (Worst Hold Slack)
THS 代表总的保持时序裕量 (Total Hold Slack),也就是负保持时序裕量路径之和。
这些值告诉设计者设计与时序要求相差多少。如果为正值,则说明能达到时序要求,若为负值,则说明时序达不到要求。
点Implementation -> Open Implementation -> Reporte Timing Summary,通过时序报告查看时序问题的产生原因,可以在Timing状态栏看到下面的情况,Design Timing Summary和Intra-Clock Paths时红色的,表示时序不合格的部分就在这里。
点击红色框中的选项可以看到,时序不合格的地方时clk时钟下的Setup时间不能达到要求,默认情况下最多显示10条每个时钟能显示的问题数量
时序分析
双击Path1,打开时序报告的界面。
Slack为-1.344ns,表示和5ns的建立时间的要求相比,这条线的路还差1.344ns,单击-1.344ns,弹出来一个对话框,可以看到这条线需要数据在9.417ns内到达第二个触发器的输入,但实际到达时间为10.761ns,导致建立时间不够。
Source Clock Path为时钟到第一级触发器的时间,Data Path为数据经过组合逻辑产生的延迟,Source Clock Path + Data Path算出的是数据延迟的综合,为10.761ns。Destination Clock Path算出的是Clock延迟的总和,为9.417ns
单击Path1,再点Implementation -> Open Implementation -> Schematic查看原理图,原理图中可以看到其经过的逻辑电路(高亮),并且在Divice界面里可以看到在FPGA内部的实际走线。原理图可以看到,最左边和最右边的器件是触发器,两级触发器之间的电路则是经过的逻辑器件。
时序优化
根据时序分析已经找到了时序不通过的地方,可以采取三种解决办法,推荐第二种
-
简化逻辑
通过减少器件的数目,来减少逻辑延迟,使之能符合时序要求,
为了能只直观看到减少组合逻辑带来的好处,这里简单粗暴去掉一些乘法器,再运行一遍,可以看到时序直接通过assign data_tmp_2 = data_tmp_in * data_tmp_in; assign data_tmp_3 = data_tmp_2 * data_tmp_in; assign data_tmp_4 = data_tmp_3 * data_tmp_2; // assign data_tmp_5 = data_tmp_4 * data_tmp_3; // assign data_tmp_6 = data_tmp_5 * data_tmp_4; // assign data_tmp_7 = data_tmp_6 * data_tmp_5; assign data_cal_out= data_tmp_4;
-
插入触发器
通过在组合逻辑之间插入触发器,将原本需要一个周期完成的逻辑转换为两个周期完成,分散时序的压力,从而使时序达到要求
有关流水线的优化,可以参考: 四输入乘法器的优化.always @ (posedge clk) if (reset == 1'b1) data_tmp_2 <= 0; else data_tmp_2 <= data_tmp_in * data_tmp_in; always @ (posedge clk) if (reset == 1'b1) data_tmp_3 <= 0; else data_tmp_3 <= data_tmp_2 * data_tmp_in; always @ (posedge clk) if (reset == 1'b1) data_tmp_4 <= 0; else data_tmp_4 <= data_tmp_3 * data_tmp_2; always @ (posedge clk) if (reset == 1'b1) data_tmp_5 <= 0; else data_tmp_5 <= data_tmp_4 * data_tmp_3; always @ (posedge clk) if (reset == 1'b1) data_tmp_6 <= 0; else data_tmp_6 <= data_tmp_5 * data_tmp_4; always @ (posedge clk) if (reset == 1'b1) data_tmp_7 <= 0; else data_tmp_7 <= data_tmp_6 * data_tmp_5; assign data_cal_out= data_tmp_7;
-
用低频时钟
修改约束文件,频率约束为5mHz,T = 20ns
20230119修改:
修改约束文件,频率约束为50MHz,T = 20ns
create_clock -name clk -period 20.000 [get_ports clk]