fpga如何约束走线_FPGA时序约束实战篇之多周期路径约束
多周期路徑約束
多周期路徑,我們一般按照以下4個步驟來約束:
1. 帶有使能的數(shù)據(jù)
首先來看帶有使能的數(shù)據(jù),在本工程中的Tming Report中,也提示了同一個時鐘域之間的幾個路徑建立時間不滿足要求
其實這幾個路徑都是帶有使能的路徑,使能的周期為2倍的時鐘周期,本來就應該在2個時鐘周期內去判斷時序收斂。因此,我們添加時序約束:
set_multicycle_path 2 -setup -from [get_cells {cmd_parse_i0/send_resp_data_reg[*]} -include_replicated_objects] -to [get_cells {resp_gen_i0/to_bcd_i0/bcd_out_reg[*]}]
set_multicycle_path 1 -hold -from [get_cells {cmd_parse_i0/send_resp_data_reg[*]} -include_replicated_objects] -to [get_cells {resp_gen_i0/to_bcd_i0/bcd_out_reg[*]}]
也可以寫為:
set_multicycle_path -from [get_cells {cmd_parse_i0/send_resp_data_reg[*]} -include_replicated_objects] -to [get_cells {resp_gen_i0/to_bcd_i0/bcd_out_reg[*]}] 2
set_multicycle_path -hold -from [get_cells {cmd_parse_i0/send_resp_data_reg[*]} -include_replicated_objects] -to [get_cells {resp_gen_i0/to_bcd_i0/bcd_out_reg[*]}] 1
這兩種寫法是等價的。
我們也可以直接點擊右鍵通過GUI的方式進行約束,效果都是一樣的。
在工程的uart_tx_ctl.v和uart_rx_ctl.v文件中,也存在帶有使能的數(shù)據(jù),但這些路徑在未加多路徑約束時并未報出時序錯誤或者警告。
在接收端,捕獲時鐘頻率是200MHz,串口速率是115200,采用16倍的Oversampling,因此使能信號周期是時鐘周期的200e6/115200/16=108.5倍。
在接收端,捕獲時鐘頻率是166667MHz,串口速率是115200,采用16倍的Oversampling,因此使能信號周期是時鐘周期的166.667e6/115200/16=90.4倍。
因此,時序約束如下:
# 串口接收端
set_multicycle_path -from [get_cells uart_rx_i0/uart_rx_ctl_i0/* -filter IS_SEQUENTIAL] -to [get_cells uart_rx_i0/uart_rx_ctl_i0/* -filter IS_SEQUENTIAL] 108
set_multicycle_path -hold -from [get_cells uart_rx_i0/uart_rx_ctl_i0/* -filter IS_SEQUENTIAL] -to [get_cells uart_rx_i0/uart_rx_ctl_i0/* -filter IS_SEQUENTIAL] 107
# 串口發(fā)送端
set_multicycle_path -from [get_cells uart_tx_i0/uart_tx_ctl_i0/* -filter IS_SEQUENTIAL] -to [get_cells uart_tx_i0/uart_tx_ctl_i0/* -filter IS_SEQUENTIAL] 90
set_multicycle_path -hold -from [get_cells uart_tx_i0/uart_tx_ctl_i0/* -filter IS_SEQUENTIAL] -to [get_cells uart_tx_i0/uart_tx_ctl_i0/* -filter IS_SEQUENTIAL] 89
約束中的filter參數(shù)也將在下一章節(jié)具體講解。
2. 兩個有數(shù)據(jù)交互的時鐘之間存在相位差
在本工程中,沒有這種應用場景,因此不需要添加此類約束。
3. 存在快時鐘到慢時鐘的路徑
在本工程中,沒有這種應用場景,因此不需要添加此類約束。
4. 存在慢時鐘到快時鐘的路徑
在本工程中,沒有這種應用場景,因此不需要添加此類約束。
綜上,我們所有的時序約束如下:
# 主時鐘約束
create_clock -period 25.000 -name clk2 [get_ports clk_in2]
# 衍生時鐘約束
create_generated_clock -name clk_samp -source [get_pins clk_gen_i0/clk_core_i0/clk_tx] -divide_by 32 [get_pins clk_gen_i0/BUFHCE_clk_samp_i0/O]
create_generated_clock -name spi_clk -source [get_pins dac_spi_i0/out_ddr_flop_spi_clk_i0/ODDR_inst/C] -divide_by 1 -invert [get_ports spi_clk_pin]
create_generated_clock -name clk_tx -source [get_pins clk_gen_i0/clk_core_i0/inst/mmcm_adv_inst/CLKIN1] [get_pins clk_gen_i0/clk_core_i0/inst/mmcm_adv_inst/CLKOUT1]
create_generated_clock -name clk_rx -source [get_pins clk_gen_i0/clk_core_i0/inst/mmcm_adv_inst/CLKIN1] [get_pins clk_gen_i0/clk_core_i0/inst/mmcm_adv_inst/CLKOUT0]
# 設置異步時鐘
set_clock_groups -asynchronous -group [get_clocks clk_samp] -group [get_clocks clk2]
# 延遲約束
create_clock -period 6.000 -name virtual_clock
set_input_delay -clock [get_clocks -of_objects [get_ports clk_pin_p]] 0.000 [get_ports rxd_pin]
set_input_delay -clock [get_clocks -of_objects [get_ports clk_pin_p]] -min -0.500 [get_ports rxd_pin]
set_input_delay -clock virtual_clock -max 0.000 [get_ports lb_sel_pin]
set_input_delay -clock virtual_clock -min -0.500 [get_ports lb_sel_pin]
set_output_delay -clock virtual_clock -max 0.000 [get_ports {txd_pin {led_pins[*]}}]
set_output_delay -clock virtual_clock -min -0.500 [get_ports {txd_pin {led_pins[*]}}]
set_output_delay -clock spi_clk -max 1.000 [get_ports {spi_mosi_pin dac_cs_n_pin dac_clr_n_pin}]
set_output_delay -clock spi_clk -min -1.000 [get_ports {spi_mosi_pin dac_cs_n_pin dac_clr_n_pin}]
# 偽路徑約束
set_false_path -from [get_clocks clk_rx] -to [get_clocks clk_tx]
set_false_path -from [get_ports rst_pin]
# 多周期約束
set_multicycle_path 2 -setup -from [get_cells {cmd_parse_i0/send_resp_data_reg[*]} -include_replicated_objects] -to [get_cells {resp_gen_i0/to_bcd_i0/bcd_out_reg[*]}]
set_multicycle_path 1 -hold -from [get_cells {cmd_parse_i0/send_resp_data_reg[*]} -include_replicated_objects] -to [get_cells {resp_gen_i0/to_bcd_i0/bcd_out_reg[*]}]
# 串口接收端
set_multicycle_path 108 -setup -from [get_cells uart_rx_i0/uart_rx_ctl_i0/* -filter IS_SEQUENTIAL] -to [get_cells uart_rx_i0/uart_rx_ctl_i0/* -filter IS_SEQUENTIAL]
set_multicycle_path 107 -hold -from [get_cells uart_rx_i0/uart_rx_ctl_i0/* -filter IS_SEQUENTIAL] -to [get_cells uart_rx_i0/uart_rx_ctl_i0/* -filter IS_SEQUENTIAL]
# 串口發(fā)送端
set_multicycle_path 90 -setup -from [get_cells uart_tx_i0/uart_tx_ctl_i0/* -filter IS_SEQUENTIAL] -to [get_cells uart_tx_i0/uart_tx_ctl_i0/* -filter IS_SEQUENTIAL]
set_multicycle_path 89 -hold -from [get_cells uart_tx_i0/uart_tx_ctl_i0/* -filter IS_SEQUENTIAL] -to [get_cells uart_tx_i0/uart_tx_ctl_i0/* -filter IS_SEQUENTIAL]
重新Synthesis并Implementation后,可以看到,已經沒有了時序錯誤
僅有的兩個warning也只是說rst沒有設置input_delay,spi_clk_pin沒有設置output_delay,但我們已經對rst設置了偽路徑,而spi_clk_pin是我們約束的輸出時鐘,無需設置output_delay。
到這里,教科書版的時序約束教程就基本講完了。但我們平時的工程中,跟上面這種約束還是有差異的:
? ? 首先是虛擬時鐘,這個約束在平時的工程中基本不會用到,像需要設置虛擬時鐘的場景,我們也都是通過設計來保證時序收斂,設置虛擬時鐘的意義不大。
? ? 第二就是output delay,在FPGA的最后一級寄存器到輸出的路徑上,往往都使用了IOB,也就是IO block,因此最后一級寄存器的位置是固定的,從buffer到pad的走線延時是確定的。在這種情況下,是否滿足時序要求完全取決于設計,做約束只是驗證一下看看時序是否收斂。所以也基本不做。但是input delay是需要的,因為這是上一級器件輸出的時序關系。
? ? 第三個就是多周期路徑,我們講了那么多多周期路徑的應用場景,但實際我們是根據(jù)Timing report來進行約束的,即便那幾種場景都存在,但如果Timing report中沒有提示任何的時序 warning,我們往往也不會去添加約束。
? ? 第四個就是在設置了多周期后,如果還是提示Intra-Clocks Paths的setup time不過,那就要看下程序,是否寫的不規(guī)范。比如
如果設置了多周期路徑后,還是提示Intra-Clocks Paths的setup time不過,那就要看下程序,是否寫的不規(guī)范。比如
always @ (posedge clk)
begin
regA <= regB;
if(regA != regB)
regC <= 4'hf;
else
regC <= {regC[2:0], 1'b0};
if((&flag[3:0]) && regA != regB)
regD <= regB;
end
這么寫的話,如果時鐘頻率稍微高一點,比如250MHz,就很容易導致從regB到regD的setup time不滿足要求。因為begin end里面的代碼都是按順序執(zhí)行的,要在4ns內完成這些賦值與判斷的邏輯,挑戰(zhàn)還是挺大的。因此,我們可以改寫為:
always @ (posedge clk)
begin
regA <= regB;
end
always @ (posedge clk)
begin
if(regA != regB)
regC <= 4'hf;
else
regC <= {regC[2:0], 1'b0};
end
always @ (posedge phy_clk)
begin
if((&flag[3:0]) && regA != regB)
regD <= regB;
end
把寄存器的賦值分開,功能還是一樣的,只是分到了幾個always中,這樣就不會導致時序問題了。
本文轉自:科學計算technomania,作者:貓叔,轉載此文目的在于傳遞更多信息,版權歸原作者所有。
總結
以上是生活随笔為你收集整理的fpga如何约束走线_FPGA时序约束实战篇之多周期路径约束的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux摄像头内核驱动开发,怎么在Li
- 下一篇: php调用美图接口,网易美图 API 接