Имеется проект, в который входят корки от альтеры DDR3 SDRAM Controller with UniPHY, PCI Express и еще куча своей логики.
Внешними клоками для проекта являются: inp_clock_50MHz - 50 МГц с кварца, inp_refclk - 100 МГц с компа по шине PCI Express.
В проекте 50 МГц подается в DDR3 контроллер, который делает из них необходимые ему клоки и выдает 200МГц (uni_DDR3_p0_pll_avl_clock).
100 МГц подается в PCI Express корку, оттуда возвращается 250 МГц (coreclkout).
Моя логика работает на 200МГц, 250 МГц, и на 100 МГц (pll1|clk[0]), которые я получаю с pll из 200 МГц.
Для TimeQuest создал такой sdc-файл:
derive_clock_uncertainty
create_clock -period "50 MHz" -name {inp_clock_50MHz} {inp_clock_50MHz}
create_clock -period "100 MHz" -name {inp_refclk} {inp_refclk}
derive_pll_clocks
set_clock_groups -exclusive -group {inp_clock_50MHz pll_inst|altpll_component|auto_generated|pll1|clk[0]}
set_clock_groups -exclusive -group {inp_clock_50MHz controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_avl_clock}
set_clock_groups -exclusive -group {inp_refclk mypciexpress_x8_inst|pcie_inst|wrapper|altpcie_hip_pipen1b_inst|stratix_iv.strat
ixiv_hssi_pcie_hip|coreclkout}
В результате получаю такой репорт по частотам:
Код
+------------------------------------------------------------------------------------------------------------------------------------------------
; Fmax Summary
+-------------+-----------------+---------------------------------------------------------------------------------------------------------------+
; Fmax ; Restricted Fmax; Clock Name ;
+-------------+-----------------+---------------------------------------------------------------------------------------------------------------+
; 44.15 MHz ; 10.0 MHz ; altera_reserved_tck ;
; 94.25 MHz ; 30.0 MHz ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_config_clock ;
; 121.8 MHz ; 121.8 MHz ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_afi_clk ;
; 131.2 MHz ; 131.2 MHz ; pll_inst|altpll_component|auto_generated|pll1|clk[0] ;
; 151.29 MHz ; 151.29 MHz ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_avl_clock ;
; 199.96 MHz ; 199.96 MHz ; inp_clock_50MHz ;
; 221.93 MHz ; 221.93 MHz ; mypciexpress_x8_inst|pcie_inst|wrapper|altpcie_hip_pipen1b_inst|stratix_iv.strat
ixiv_hssi_pcie_hip|coreclkout;
; 333.11 MHz ; 333.11 MHz ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_addr_cmd_clk ;
; 1396.65 MHz; 800.0 MHz ; mypciexpress_x8_inst|pcie_inst|serdes|pcie_serdes_alt4gxb_q3pa_component|central
_clk_div0|coreclkout ;
; 1879.7 MHz ; 800.0 MHz ; inp_refclk~input~INSERTED_REFCLK_DIVIDER|clkout ;
+-------------+-----------------+---------------------------------------------------------------------------------------------------------------+
; Fmax Summary
+-------------+-----------------+---------------------------------------------------------------------------------------------------------------+
; Fmax ; Restricted Fmax; Clock Name ;
+-------------+-----------------+---------------------------------------------------------------------------------------------------------------+
; 44.15 MHz ; 10.0 MHz ; altera_reserved_tck ;
; 94.25 MHz ; 30.0 MHz ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_config_clock ;
; 121.8 MHz ; 121.8 MHz ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_afi_clk ;
; 131.2 MHz ; 131.2 MHz ; pll_inst|altpll_component|auto_generated|pll1|clk[0] ;
; 151.29 MHz ; 151.29 MHz ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_avl_clock ;
; 199.96 MHz ; 199.96 MHz ; inp_clock_50MHz ;
; 221.93 MHz ; 221.93 MHz ; mypciexpress_x8_inst|pcie_inst|wrapper|altpcie_hip_pipen1b_inst|stratix_iv.strat
ixiv_hssi_pcie_hip|coreclkout;
; 333.11 MHz ; 333.11 MHz ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_addr_cmd_clk ;
; 1396.65 MHz; 800.0 MHz ; mypciexpress_x8_inst|pcie_inst|serdes|pcie_serdes_alt4gxb_q3pa_component|central
_clk_div0|coreclkout ;
; 1879.7 MHz ; 800.0 MHz ; inp_refclk~input~INSERTED_REFCLK_DIVIDER|clkout ;
+-------------+-----------------+---------------------------------------------------------------------------------------------------------------+
Как я понимаю, клок coreclkout=250 МГц завален до 221 МГц, а клок uni_DDR3_p0_pll_avl_clock=200 МГц до 151 МГц.
Проект при этом чаще всего работает нормально. Если после очередной компиляции проект работает нестабильно, помогает еще одна (или несколько) компиляция.
Клоковые домены развязываю двойной буферизацией (ниже в коде показано как).
Вопросов у меня куча:
1. Верно ли я задал sdc-файл для проекта?
2. Как вытянуть частоты 250 и 200 до их истинных значений? Обычно ковыряю Report Top Falling Paths, но к каким то однозначным методам так и не пришел - сплошное шаманство с бубном для меня).
Например, репорт выдает такую запись:
; -3.210 ; Nimp[18]~_Duplicate_2 ; ddr_i_begin_addr[29] ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_afi_clk ; controller_ddr3_inst|writer_reader_pm|compDDR3_pm|dev_ddr3_inst|uni_ddr3_inst|un
i_DDR3_p0_pll_afi_clk ; 5.000 ; 0.000 ; 8.120 ;
Исходный код при этом упрощенно такой:
Код
inp_clk_200MHz <= uni_DDR3_p0_pll_afi_clk;
process(inp_clk_200MHz)
begin
if (rising_edge(inp_clk_200MHz)) then
-- двойная буферизация
DAM_Nimp_z0 <= DAM_Nimp;
DAM_Nimp_z1 <= DAM_Nimp_z0;
...
if (logic_state = 0) then
if (flag = '1') then
if (TO_INTEGER( unsigned (DAM_Nimp_z1)) < par_Nimp_min) then
Nimp <= par_Nimp_min;
else
Nimp <= TO_INTEGER( unsigned (DAM_Nimp_z1));
end if;
end if;
end if;
...
if (mode = 1) then
if (step = 0) then
ddr_i_begin_addr <= std_logic_vector( TO_SIGNED( Nimp,32));
...
end if;
...
end if;
...
end if;
end process;
process(inp_clk_250MHz)
begin
if (rising_edge(inp_clk_250MHz)) then
...
DAM_Nimp <= pcie_data;
end if;
end process;
process(inp_clk_200MHz)
begin
if (rising_edge(inp_clk_200MHz)) then
-- двойная буферизация
DAM_Nimp_z0 <= DAM_Nimp;
DAM_Nimp_z1 <= DAM_Nimp_z0;
...
if (logic_state = 0) then
if (flag = '1') then
if (TO_INTEGER( unsigned (DAM_Nimp_z1)) < par_Nimp_min) then
Nimp <= par_Nimp_min;
else
Nimp <= TO_INTEGER( unsigned (DAM_Nimp_z1));
end if;
end if;
end if;
...
if (mode = 1) then
if (step = 0) then
ddr_i_begin_addr <= std_logic_vector( TO_SIGNED( Nimp,32));
...
end if;
...
end if;
...
end if;
end process;
process(inp_clk_250MHz)
begin
if (rising_edge(inp_clk_250MHz)) then
...
DAM_Nimp <= pcie_data;
end if;
end process;
Nimp и ddr_i_begin_addr крутятся в одном клоковом домене. И куда здесь можно копать? Даже предположений нет.