布局布線沒有滿足我們要求的時序情況下,該如何去解決呢?
一、時序分析的優化流程
二、查看時序報告
1.ILA相關約束可以忽略
2.Report timing summary可以打印所有路徑報告,方便查看哪些違例了。
三、解決跨時鍾域違例
1、set false path
(1)復位信號,選擇point到point,否則所有信號都 false了
(2)跨時鍾域信號,可以選擇clock到clock。
2、Set multicycle
兩級寄存器之間有復雜的組合邏輯,導致延遲可能超過1個時鍾周期。
(1)修改建立時間:set_multicycle_path -from $from_list -to $to_list <N>,建立時間采樣沿在N處,建立時間OK了
(2)保持時間采樣沿在N-1處,要求上一個數據的結束位置要在這,太難了,很可能報告時序違例,因此要把保持時間推回原先的采樣沿0時刻位置:set_multicycle_path -from $from_list -to $to_list-hold <N-1>,還不行就<N-2>、<N-3>
四、解決同時鍾域違例
1、synthesis策略
點擊 SYNTHESIS --- Synthesis,在Options界面可以選擇不同的綜合策略,時序改善余地不大。
2、Implementation策略
點擊 IMPLEMENTTION --- Synthesis,在Options界面可以選擇不同的綜合策略,進行時序改善。
3、布局布線物理優化(div_timing)
例如乘法器除法器常常出現問題,可以用此方法解決。
(1)設置方法
(2)參考依據
(3)效果展示
①扇出優化(設置post_place phy_opt)
和左側相比,右邊的白線被分割為多個起點扇出,減少了扇出延時。藍線為優化前的效果。
②布局優化
如果一些較長的關鍵路徑存在,布局工具會自動的進行從新規划布局方案使得路徑變短,從而優化時序。
③布線優化
④HOLD FIX優化
⑤Retiming優化
4、插入流水線寄存器(實實在在的辦法)
(1)除法器IP核里增大latency,會給第一個計算結果帶來延遲,但是增加了時序余量,改善了時序。
(2)組合邏輯帶來延時,采用流水線打拍來改變代碼,增大了latency,改善了時序。
`timescale 1ns / 1ps //************************************************************************** // *** 名稱 : top_encode.v // *** 作者 : xianyu_FPGA // *** 博客 : https://www.cnblogs.com/xianyufpga/ // *** 日期 : 2020-04-12 // *** 描述 : 流水線案例,流水線優化后 //************************************************************************** module top_encode //========================< 端口 >========================================== ( //input ----------------------------------------- input wire sysclk_in , input wire pkg_valid , input wire [15:0] in_data0 , input wire [15:0] in_data1 , input wire [15:0] in_data2 , input wire [15:0] in_data3 , input wire [15:0] in_data4 , input wire [15:0] in_data5 , input wire [15:0] in_data6 , input wire [15:0] in_data7 , //output ---------------------------------------- output reg o_encode_valid , output reg [31:0] o_encode ); //========================< 信號 >========================================== //reg ------------------------------------------- reg pkg_valid_r ; reg [15:0] in_data0_r ; reg [15:0] in_data1_r ; reg [15:0] in_data2_r ; reg [15:0] in_data3_r ; reg [15:0] in_data4_r ; reg [15:0] in_data5_r ; reg [15:0] in_data6_r ; reg [15:0] in_data7_r ; //pll ------------------------------------------- wire sclk ; wire clk150 ; wire clk300 ; //no pipelined ---------------------------------- wire [15:0] code_0 ; wire [15:0] code_1 ; wire [15:0] code_2 ; wire [15:0] code_3 ; wire [15:0] code_4 ; wire [15:0] code_5 ; wire [15:0] code_6 ; wire [15:0] code_7 ; wire [31:0] code_sum ; //pipelined ------------------------------------- reg [15:0] code_0_r ; reg [15:0] code_1_r ; reg [15:0] code_2_r ; reg [15:0] code_3_r ; reg [15:0] code_4_r ; reg [15:0] code_5_r ; reg [15:0] code_6_r ; reg [15:0] code_7_r ; reg [31:0] code_sum_r ; reg pkg_valid_rr ; reg pkg_valid_rrr ; //========================================================================== //== pll //========================================================================== clk_gen clk_gen ( .clk_out1 (clk150 ), .clk_out2 (clk300 ), .clk_in1 (sysclk_in ) ); assign sclk = clk150; //========================================================================== //== no pipelined //========================================================================== always @(posedge sclk) begin pkg_valid_r <= pkg_valid; in_data0_r <= in_data0; in_data1_r <= in_data1; in_data2_r <= in_data2; in_data3_r <= in_data3; in_data4_r <= in_data4; in_data5_r <= in_data5; in_data6_r <= in_data6; in_data7_r <= in_data7; end assign code_0 = in_data0_r | in_data7_r; assign code_1 = in_data1_r | in_data6_r; assign code_2 = in_data2_r | in_data5_r; assign code_3 = in_data3_r | in_data4_r; assign code_4 = in_data0_r + in_data1_r + in_data2_r + in_data3_r; assign code_5 = in_data1_r + in_data2_r + in_data3_r + in_data4_r; assign code_6 = in_data2_r + in_data3_r + in_data4_r + in_data5_r; assign code_7 = in_data3_r + in_data4_r + in_data5_r + in_data6_r; assign code_sum = code_0 + code_1 + code_2 + code_3 + code_4 + code_5 + code_6 + code_7; always @(posedge sclk) begin o_encode_valid <= pkg_valid_r; o_encode <= code_sum; end /* //========================================================================== //== pipelined //========================================================================== //一級寄存器 always @(posedge sclk) begin code_0_r <= code_0; code_1_r <= code_1; code_2_r <= code_2; code_3_r <= code_3; code_4_r <= code_4; code_5_r <= code_5; code_6_r <= code_6; code_7_r <= code_7; end //二級寄存器 always @(posedge sclk ) begin code_sum_r <= code_0_r + code_1_r + code_2_r + code_3_r + code_4_r + code_5_r + code_6_r + code_7_r; end //========================================================================== //== 信號對齊 //========================================================================== always @(posedge sclk ) begin pkg_valid_rr <= pkg_valid_r; pkg_valid_rrr <= pkg_valid_rr; end //========================================================================== //== 輸出端口 //========================================================================== always @(posedge sclk) begin o_encode_valid <= pkg_valid_rrr; o_encode <= code_sum_r; end */ endmodule
多說一點,平常寫代碼時:case別寫太深、if else里不要嵌套 case、if 條件的條件位寬盡量窄(減少不同位之間的扇出差異)......
參考資料:V3學院FPGA教程