Jump to content

    

Recommended Posts

А расскажите, почему так произошло?

Человек, что писал проект, не ПЛИСовец. Он не придавал значения аспектам архитектуры и поддержки\отладки проекта(спасибо хоть с комментариями постарался!). Получился тугой узел, развязать который сложно.

 

А как вы считаете, почему так произошло? Секрет скорее всего во временах восстановления(после асинхронного сброса). Там болтанка фронтов(асинхронных по сути) плюсуется. ТаймКвест формально это не пропускает.

Share this post


Link to post
Share on other sites

Раз тема создана, то вопрос наверное будет по теме.

Сейчас я в процессе изучения TimeQuest. Сильно не пинайте, поскольку английским я владею не очень...

Собственно никак не улавливаю разницы между get_registers и get_keepers. Ну что такое get_registers понятно: это регистры (Ваш КЭП)

А вот что такое get_keepers ? В чем разница между ними ?

UPD

А где можно достать примеры файлов SDC совместно с проектами ? На примерах как-то проще учиться...

Edited by Flip-fl0p

Share this post


Link to post
Share on other sites

По поводу keepers и registers, честно говоря было бы самому неинтересно. Сколько не читал в мануалах понять не могу. Впрочем, как я для себя решил, registers это подмножество keepers, которые могут быть ещё и портами. Тогда встаёт вопрос разницы между keepers и ports. Так что, как я понял, в принципе по этому поводу можно особо не замарачиваться и использовать лишь registers и ports (если не прав, пусть более сведущие товарищи поправят). Что касается примеров, настоятельно рекомендую проштудировать TimeQuest User Guide, написанный товарищем Ryan Scoville. Правда я его на русском не видел, (как и вообще какой либо литературы по констрейнам, кроме нескольких статей Дениса Шехалева), так что учите аглицкий. Так же рекомендую почить статьи Дениса Шехалева в КИТ, о которых я уже упоминал.

Edited by Грендайзер

Share this post


Link to post
Share on other sites
По поводу keepers и registers, честно говоря было бы самому неинтересно. Сколько не читал в мануалах понять не могу. Впрочем, как я для себя решил, registers это подмножество keepers, которые могут быть ещё и портами. Тогда встаёт вопрос разницы между keepers и ports. Так что, как я понял, в принципе по этому поводу можно особо не замарачиваться и использовать лишь registers и ports (если не прав, пусть более сведущие товарищи поправят). Что касается примеров, настоятельно рекомендую проштудировать TimeQuest User Guide, написанный товарищем Ryan Scoville. Правда я его на русском не видел, (как и вообще какой либо литературы по констрейнам, кроме нескольких статей Дениса Шехалева), так что учите аглицкий. Так же рекомендую почить статьи Дениса Шехалева в КИТ, о которых я уже упоминал.

Спасибо за ответ. Статьи Дениса Шехалева я читаю, разбираю, но вопросов возникает больше чем ответов. С английским беда. Без словаря понимаю 30-50% слов. Изучать английский еще долго, чтобы корректно воспринимать литературу на английском. Но я стараюсь. Читаю понемногу, но очень тяжко идет... С примерами как-то проще было бы изучать и понимать литературу. Очень много вопросов возникает из-за того, что почти во всех книгах\гайдах показаны совсем примитивные примеры. Ну вот к примеру что такое set_multicycle_path вроде понятно - данные пишутся не каждый такт, а раз в несколько тактов.

 

А вот наприимер у меня есть ситуация:

CASE X16CLOCK_CNT IS                                -- Анализируем состояние счетчика 16 битных интервалов
                                WHEN 7      => 
                                                SAMPLE_REG(0) <= RX_SYNC;       -- Первая выборка старт бита           
                                WHEN 8      => 
                                                SAMPLE_REG(1) <= RX_SYNC;       -- Вторая выборка старт бита
                                WHEN 9      => 
                                                SAMPLE_REG(2) <= RX_SYNC;       -- Третяя выборка старт бита
                                WHEN 10      =>                       
                                                CASE SAMPLE_REG IS                                                  -- На 10 такте проверяем состояние регистра выборки
                                                    WHEN "000" | "001" | "100" | "010" => START_BIT_FOUND <= '1';   -- Большая часть битов равна нулю - выставляем флаг старт бита
                                                    WHEN OTHERS                        => START_BIT_FOUND <= '0';   -- Иначе это была  помеха    
                                                END CASE;
                                WHEN OTHERS =>  NULL;                           -- В остальных случая ничего не делаем
                            END CASE;

Как рассматривать запись в регистры SAMPLE_REG ? С одной стороны данные в регистры пишутся не каждый такт. С другой стороны, есть промежуток когда данные в регистры пишутся каждый такт.

И справедливо ли для этих регистров указать такие констрейны как set_multicycle_path. Т.е вот так:

 

set_multicycle_path -from [get_registers {RX_SYNC}] -to [get_registers {SAMPLE_REG[0]}] -setup -end 7

set_multicycle_path -from [get_registers {RX_SYNC}] -to [get_registers {SAMPLE_REG[1]}] -setup -end 8

set_multicycle_path -from [get_registers {RX_SYNC}] -to [get_registers {SAMPLE_REG[2]}] -setup -end 9

 

Надеюсь со временем смогу разобраться в констрейнах...

Edited by Flip-fl0p

Share this post


Link to post
Share on other sites

Ммм... Мне кажется Вы не совсем понимаете назначение и как следствие суть констрейнов... Штука то не сложная. Суть состоит в том, что в процессе синтеза, соответствующий софт (тот же TimeQuet) оценивает временные задержки на пути прохождения данных и передаёт эти данные ситезатору/мапперу/роутеру. Те в свою очередь синтезируют необходимую логику в необходимом количестве, располагают её соответствующим образом на кристалле и протягивают линии данных (трассируют) так, что бы удовлетворить основным требованиям временных ограничений, а именно по setup и hold. Т.о. всем этим товарищам абсолютно всё равно куда, когда и что Вы пишете/читаете. Их заботят лишь временные соотношения между фронтами тактов. Т.о. в Вашем случае, достаточно лишь задать значение частоты тактового сигнала. set_multicycle_path используется в случае наличия более одного тактового домена (более одной тактовой частоты), что бы указать в какой момент данные изменятся на линии управляемой первой частотой и, в какой момент они должны быть защёлкнуты на линии данных управляемой второй частотой.

Share this post


Link to post
Share on other sites
Ммм... Мне кажется Вы не совсем понимаете назначение и как следствие суть констрейнов... Штука то не сложная. Суть состоит в том, что в процессе синтеза, соответствующий софт (тот же TimeQuet) оценивает временные задержки на пути прохождения данных и передаёт эти данные ситезатору/мапперу/роутеру. Те в свою очередь синтезируют необходимую логику в необходимом количестве, располагают её соответствующим образом на кристалле и протягивают линии данных (трассируют) так, что бы удовлетворить основным требованиям временных ограничений, а именно по setup и hold. Т.о. всем этим товарищам абсолютно всё равно куда, когда и что Вы пишете/читаете. Их заботят лишь временные соотношения между фронтами тактов. Т.о. в Вашем случае, достаточно лишь задать значение частоты тактового сигнала. set_multicycle_path используется в случае наличия более одного тактового домена (более одной тактовой частоты), что бы указать в какой момент данные изменятся на линии управляемой первой частотой и, в какой момент они должны быть защёлкнуты на линии данных управляемой второй частотой.

Суть то вроде понимаю - сообщить трассировщику данные о проекте, чтобы он его расположил в ячейках кристалла так, чтобы выполнялись временные ограничения. Т.е там где надо он регистры расположил подальше\или поближе.

А вот что конкретно надо сообщать трассировщику (т.е что писать в SDC файле, улавливаю слабо)

Ну понятно, что надо описать клоки, клоки порожденные PLL, нестабильность клока, задержки входных/выходных данных, и ложные пути которые нас не интересуют. А вот что ещё надо описывать ? Когда описывать. Почему ? Вот это уловить толком и не могу.

Share this post


Link to post
Share on other sites
Ну понятно, что надо описать клоки, клоки порожденные PLL, нестабильность клока, задержки входных/выходных данных, и ложные пути которые нас не интересуют.

Ну вот, Вы сами всё знаете :biggrin: Это и описывайте. Вы ведь сейчас назвали констрейны которые необходимы в 90% случаев. Понятно, что если Вас не интересуют задержки входных/выходных, то их вам и не надо описывать. А описать клоки, клоки порожденные PLL, нестабильность клока - это, можно сказать, джентельменский набор, это нужно описывать во всех проектах. Единственное, что нужно описывать не только клоки порожденные PLL, но и все порожденные (производные) клоки. Клоки ведь можно взять не только с PLL, а скажем, с обычного счётчика... Ну и не забывайте про тактовые домены (я про это уже писал). Правда существуют нюансы связанные с некоторыми примитивами на кристалле, реализованными, скажем, аппаратно. Ну например та же pll, или скажем DDR блоки, которые создаются в коргенах. В этом случае придётся читать мануал... на этот блок, к сожалению на английском.

 

Edited by Грендайзер

Share this post


Link to post
Share on other sites

Да уж, всё очень запутано. Не стал создавать отдельную тему, решил спросить в этой. Проблема банальная: не сходятся тайминги.

Итак, описание. Есть ПЛИС Cyclone V (5CEBA9F23C8), к ней подключается ЦАП, на ПЛИС заводится частота, с ПЛИС на ЦАП выводится код и частота. Соответственно внутри ПЛИС генерируется частота для ЦАП 210 МГц с помощью PLL.

Код в в ПЛИС очень простой.

module X5_DAC(
(*chip_pin = "M9"*)
input						clk_26M,

(*chip_pin = "v6, U8, U7, U6, T8, T7, R7, R6, R5, P6, P7, N6, M6, M7"*)
output reg [13:0]		        D_D,

(*chip_pin = "W8"*)
output wire				D_CLK
);
//
alt_pll alt_pll(
.refclk						(clk_26M),   //  refclk.clk
.rst							(1'b0),      //   reset.reset
.outclk_0					        (D_CLK) 		 // outclk0.clk
);
//
reg		[8:0]				        period_cnt;
reg							pulse_ena;
//
always@(posedge D_CLK) begin

period_cnt<=period_cnt+1'b1;

pulse_ena<=&period_cnt;

if (pulse_ena)
	D_D<=14'b1111_1111_1111_11;
else
	D_D<=14'h0;
end
//
endmodule

 

Собственно, каждый раз как счетчик period_cnt переполняется на ЦАП выводятся все единицы.

 

Теперь констрейны:

 


#**************************************************************
# Time Information
#**************************************************************

set_time_format -unit ns -decimal_places 3



#**************************************************************
# Create Clock
#**************************************************************

create_clock -name {clk_26M} -period 38.461 -waveform { 0.000 19.230 } [get_ports {clk_26M}]


#**************************************************************
# Create Generated Clock
#**************************************************************

create_generated_clock -name {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0]} -source [get_pins {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|refclkin}] -duty_cycle 50/1 -multiply_by 202 -divide_by 5 -master_clock {clk_26M} [get_pins {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0]}] 
create_generated_clock -name {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk} -source [get_pins {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|vco0ph[0]}
] -duty_cycle 50/1 -multiply_by 1 -divide_by 5 -master_clock {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0]} [get_pins {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] 
create_generated_clock -name {clk_210M} -source [get_pins {alt_pll|alt_pll_inst|altera_pll_i|outclk_wire[0]~CLKENA0|inclk}] -duty_cycle 50/1 -multiply_by 1 -divide_by 1 -master_clock {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk} [get_pins {alt_pll|alt_pll_inst|altera_pll_i|outclk_wire[0]~CLKENA0|outclk}] 
create_generated_clock -name {D_CLK} -source [get_pins {alt_pll|alt_pll_inst|altera_pll_i|outclk_wire[0]~CLKENA0|outclk}] -duty_cycle 50/1 -multiply_by 1 -divide_by 1 -master_clock {clk_210M} [get_ports {D_CLK}] 


#**************************************************************
# Set Clock Uncertainty
#**************************************************************

set_clock_uncertainty -rise_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -rise_to [get_clocks {D_CLK}] -setup 0.420  
set_clock_uncertainty -rise_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -rise_to [get_clocks {D_CLK}] -hold 0.130  
set_clock_uncertainty -rise_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -fall_to [get_clocks {D_CLK}] -setup 0.420  
set_clock_uncertainty -rise_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -fall_to [get_clocks {D_CLK}] -hold 0.130  
set_clock_uncertainty -rise_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -rise_to [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -setup 0.400  
set_clock_uncertainty -rise_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -rise_to [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -hold 0.070  
set_clock_uncertainty -rise_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -fall_to [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -setup 0.400  
set_clock_uncertainty -rise_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -fall_to [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -hold 0.070  
set_clock_uncertainty -fall_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -rise_to [get_clocks {D_CLK}] -setup 0.420  
set_clock_uncertainty -fall_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -rise_to [get_clocks {D_CLK}] -hold 0.130  
set_clock_uncertainty -fall_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -fall_to [get_clocks {D_CLK}] -setup 0.420  
set_clock_uncertainty -fall_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -fall_to [get_clocks {D_CLK}] -hold 0.130  
set_clock_uncertainty -fall_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -rise_to [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -setup 0.400  
set_clock_uncertainty -fall_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -rise_to [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -hold 0.070  
set_clock_uncertainty -fall_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -fall_to [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -setup 0.400  
set_clock_uncertainty -fall_from [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -fall_to [get_clocks {alt_pll|alt_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] -hold 0.070  
set_clock_uncertainty -rise_from [get_clocks {clk_210M}] -rise_to [get_clocks {clk_210M}] -setup 0.400  
set_clock_uncertainty -rise_from [get_clocks {clk_210M}] -rise_to [get_clocks {clk_210M}] -hold 0.060  
set_clock_uncertainty -rise_from [get_clocks {clk_210M}] -fall_to [get_clocks {clk_210M}] -setup 0.400  
set_clock_uncertainty -rise_from [get_clocks {clk_210M}] -fall_to [get_clocks {clk_210M}] -hold 0.060  
set_clock_uncertainty -rise_from [get_clocks {clk_210M}] -rise_to [get_clocks {D_CLK}] -setup 0.420  
set_clock_uncertainty -rise_from [get_clocks {clk_210M}] -rise_to [get_clocks {D_CLK}] -hold 0.120  
set_clock_uncertainty -rise_from [get_clocks {clk_210M}] -fall_to [get_clocks {D_CLK}] -setup 0.420  
set_clock_uncertainty -rise_from [get_clocks {clk_210M}] -fall_to [get_clocks {D_CLK}] -hold 0.120  
set_clock_uncertainty -fall_from [get_clocks {clk_210M}] -rise_to [get_clocks {clk_210M}] -setup 0.400  
set_clock_uncertainty -fall_from [get_clocks {clk_210M}] -rise_to [get_clocks {clk_210M}] -hold 0.060  
set_clock_uncertainty -fall_from [get_clocks {clk_210M}] -fall_to [get_clocks {clk_210M}] -setup 0.400  
set_clock_uncertainty -fall_from [get_clocks {clk_210M}] -fall_to [get_clocks {clk_210M}] -hold 0.060  
set_clock_uncertainty -fall_from [get_clocks {clk_210M}] -rise_to [get_clocks {D_CLK}] -setup 0.420  
set_clock_uncertainty -fall_from [get_clocks {clk_210M}] -rise_to [get_clocks {D_CLK}] -hold 0.120  
set_clock_uncertainty -fall_from [get_clocks {clk_210M}] -fall_to [get_clocks {D_CLK}] -setup 0.420  
set_clock_uncertainty -fall_from [get_clocks {clk_210M}] -fall_to [get_clocks {D_CLK}] -hold 0.120  


#**************************************************************
# Set Input Delay
#**************************************************************



#**************************************************************
# Set Output Delay
#**************************************************************

set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[0]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[0]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[1]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[1]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[2]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[2]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[3]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[3]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[4]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[4]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[5]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[5]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[6]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[6]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[7]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[7]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[8]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[8]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[9]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[9]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[10]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[10]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[11]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[11]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[12]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[12]}]
set_output_delay -add_delay -max -clock [get_clocks {D_CLK}]  2.000 [get_ports {D_D[13]}]
set_output_delay -add_delay -min -clock [get_clocks {D_CLK}]  -1.500 [get_ports {D_D[13]}]

 

Ну тут сначала описывается клок, который подаётся на ПЛИС, 26 МГц, потом клоки на PLL, потом описывается выходной клок, который идет на ЦАП (D_CLK, он же на ножке ПЛИС).

Потом идут uncertainty, их генерирует сам таймквест, как и все эти длинные, ужасные имена в pll.

Потом идут отношения выходного клока (D_CLK) с выходными данными (D_D), здесь указано все согласно с даташитом ЦАП.

И естественно после компиляции таймквест ругается, слэк в setup summary отрицательный. Картинки из таймквеста прикреплены в архиве.

Не понимаю, что еще нужно добавить к констрейнам, чтобы они выполнялись. Или неужели пятые циклоны настолько медленные, констрейны не выполняются и на 125 МГц, к слову на третьем циклоне по крайней мере на 125 МГц все в порядке.

TQ.zip

Share this post


Link to post
Share on other sites
Не понимаю, что еще нужно добавить к констрейнам, чтобы они выполнялись. Или неужели пятые циклоны настолько медленные, констрейны не выполняются и на 125 МГц, к слову на третьем циклоне по крайней мере на 125 МГц все в порядке.

Я, к примеру, архив не могу скачать и открыть, Вы так не можете картинки выложить со слэком по сетапу? Предположу, что скорее всего, данные сидят не в fast output register (соответственно программируемая задержка не задействована) и самое главное - частота реально пойдет на выход быстрее нежели установятся данные - создайте на pll сдвинутую по фазе частоту и пустите ее на выход (в зависимости от того, насколько слэк отрицательный).

А так вообще то у Вас ограничения довольно жесткие - требуется обеспечить окно, шириной 2+1.5=3.5 нс, при том что период частоты 1/210=4.76нс.

Share this post


Link to post
Share on other sites
Я, к примеру, архив не могу скачать и открыть, Вы так не можете картинки выложить со слэком по сетапу? Предположу, что скорее всего, данные сидят не в fast output register (соответственно программируемая задержка не задействована) и самое главное - частота реально пойдет на выход быстрее нежели установятся данные - создайте на pll сдвинутую по фазе частоту и пустите ее на выход (в зависимости от того, насколько слэк отрицательный).

А так вообще то у Вас ограничения довольно жесткие - требуется обеспечить окно, шириной 2+1.5=3.5 нс, при том что период частоты 1/210=4.76нс.

 

Добавил картинки

 

image.jpg

 

TQ2.jpg

 

Да, данные не fast_output register, как же я мог забыть про это. Fast_output помогает, убирает слэки по сетапу, но появились слэки по холду, хоть и намного меньше)

Думаю придется делать второй клок на PLL, сдвинутый по фазе.

 

Share this post


Link to post
Share on other sites
Да, данные не fast_output register, как же я мог забыть про это. Fast_output помогает, убирает слэки по сетапу, но появились слэки по холду, хоть и намного меньше)

Думаю придется делать второй клок на PLL, сдвинутый по фазе.

Почитайте документацию AN433. А так если ошибки по холдам, то можно попробовать пустить частоту через DDR регистр (hi=1, low=0) и тогда на частоту также можно будет задействовать программируемые задержки.

Share this post


Link to post
Share on other sites

Всем доброго времени суток!

Что бы не плодить тем решил задать вопрос здесь.

 

Использую Quartus Prime 15.1 Update 2. Есть в проекте несколько Verilog-овских модулей. Все модули соединены между собой в файле верхнего уровня. Файл верхнего уровня оформлен в схемном редакторе. Имеются файлы временных ограничений для каждого модуля. Как теперь все это дело вытащить на верхний уровень так что бы Quartus при компиляции производил разводку каждого модуля в соответствии со своим sdc файлом, и как из проекта верхнего уровня можно запускать временной анализ с помощью TimeQuest-а для каждого модуля в отдельности.

 

Углубленно TimeQuest изучаю последнюю неделю, выполнил лабу http://fpga.in.ua/fpga/cad-pld/basic-quart...iz-proekta.html, потом проштудировал от и до (кроме последнего примера) TimeQuest для чайников от Дениса Шехалева. http://embedders.org/system/files/TimeQuest_for_dummies.pdf, вернулся к своему проекту закреплять полученные навыки и сразу же появился вопрос представленный выше.

 

В связи с выше сказанным могут быть глупые вопросы. Прошу сильно не пинать.

 

 

Забыл указать что первая ссылка не работает, нужно по запросу "ЛР6 _ Временной анализ проекта" в yandex открыть сохраненную копию.

Edited by en-valb

Share this post


Link to post
Share on other sites

Насколько я понимаю, констрейны просто позволяют сообщить Квартусу, насколько он свободно может развести описанную структуру в кристалле.

Если нет описания клоков, он их видит, но не анализирует. Если клоки описаны, то он пытается развести с минимальными задержками, и выдает предупреждения.

В случае слаков, их можно убрать либо изменениями в коде, либо с помощью констрейна мультиклоков. Естественно, перед этим нужно описать пути, которые анализировать нет необходимости.

В проект можно прицепить кучу .sdc файлов и для любого модуля описать оригинальные клоки.

Поправьте меня, если ошибаюсь.

Share this post


Link to post
Share on other sites

Здравствуйте. У меня не совсем вопрос, а скорее просьба немного помочь. Написал код для Altera. Затем написал констрейны. Вроде всё хорошо, но... Понадобилось мне перенести этот код на Xilinx... на довольно старенький кристалл.

Ну и соответственно понадобилось синопсисовские констрейны переписать под ксайлинсовские ucf. И тут вообще обзац. Мог бы кто нибудь помочь переписать мои констрейны.

set_time_format -unit ns -decimal_places 3

derive_clock_uncertainty
create_clock -name CLK -period 20.000 [get_ports {CLK}]
create_generated_clock -name SCLK -source [get_ports {CLK}] -divide_by 2 [get_registers {SPI:SPI_inst|SCLK}]

set_multicycle_path -setup -from [get_clocks {CLK}] -to [get_clocks {SCLK}] -start 2
set_multicycle_path -hold -from [get_clocks {CLK}] -to [get_clocks {SCLK}] -start 1
set_false_path -from [get_clocks {SCLK}] -to [get_clocks {CLK}]
set_false_path -from [get_clocks {CLK}] -to [get_clocks {SCLK}]

set_output_delay -clock {SCLK} -max 4 [get_ports {MOSI}]
set_output_delay -clock {SCLK} -min -4 [get_ports {MOSI}]

set_output_delay -clock {SCLK} -max 7 [get_ports {CS}]
set_output_delay -clock {SCLK} -min -7 [get_ports {CS}]

create_clock -name SCLK_virt -period 40.000

set_multicycle_path -setup -from [get_clocks {CLK}] -to [get_clocks {SCLK_virt}] -start 2
set_multicycle_path -hold -from [get_clocks {CLK}] -to [get_clocks {SCLK_virt}] -start 1

set_input_delay -clock {SCLK_virt} -clock_fall -max 0.500 [get_ports {MISO}]
set_input_delay -clock {SCLK_virt} -clock_fall -min 0.500 [get_ports {MISO}]

Ну с входными и выходными задержками я разберусь, как и с мультициклами. Но как быть с синхросигналом, который является производным от данного и виртуальным клоком?

Вообщем пока всё на что меня хватило это

NET "CLK" TNM_NET = CLK;
TIMESPEC "TS_CLK" = PERIOD "CLK" 20 ns HIGH 50%;

Edited by Грендайзер

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this