|
Как ускорить компиляцию проекта на квартусе, при этом не уронив fmax |
|
|
|
Mar 18 2011, 20:47
|
вопрошающий
    
Группа: Свой
Сообщений: 1 726
Регистрация: 24-01-11
Пользователь №: 62 436

|
Всем привет, есть незадачка - мой системверилог проект очень долго компилится (2-5 часов) и не всегда его fmax бывает приемлим. Сам проект - всего-то около 600 строк без ниоса и наворотов, используется только мегафункции памяти (M9K, M144), altpll и altmult_add. В самом проекте есть два параметра, назову из K и M, где K - это объем кольцевого буффера памяти, M - число использующихся умножителей. Если K примерно 70% от всей доступной памяти, M - 10% от всех доступных умножителей, fmax на основной клок получается хороший (490МГц). Компилится все около часу на хорошем i5. Если 1) K примерно 10-20% от всей доступной памяти, M - любое, или 2) K и M примерно по 30%, fmax получается еще приемлимый, окло 400МГц (мне не меньше надо) но компилится уже около 2-5 часов. Если я пытаюсь задействовать почти все умножители и хотя бы 70% памяти, то обычно квартус через 1-2 часа падает со своей какой-то внутренней ошибкой или через 5-7 часов все-таки заканчивает работу, но fmax получается очень маленьким - около 300МГц. Алгоритмически все упирается в одну простую конструкцию: Код ... parameter N=42; input Clk; input [13:0] In[0:2]; ...
reg signed [13:0] D[0:2][0:1]; reg signed [13:0] Data[0:2][0:N]; wire signed [31:0] ScalY[0:8][0:N-1];
... // Generating modules
generate genvar i, j, k; for(i=0; i<N; i+=2) begin : aaa for(j=0; j<3; j++) begin : bbb for(k=0; k<3; k++) begin : ccc MultOne MultOne_Module(Clk, D[j][0], D[j][1], Data[k][i], Data[k][i+1], Clk2, ScalY[j+3*k][i], ScalY[j+3*k][i+1]); end end end endgenerate
...
module MultOne(Clk, A1, A2, B1, B2, Clk2, Res1, Res2); parameter SHR=18; input Clk, Clk2; input signed [13:0] A1, A2, B1, B2; output reg signed [31:0] Res1, Res2;
reg signed [13:0] P1, P2, Q1, Q2; reg signed [28:0] Sum; reg signed [28:0] SumR0, SumR1, SumR2, SumDM0, SumDM1; reg signed [28+SHR:0] ScalX1, ScalX2; reg signed [31:0] Z_Res1, Z_Res2;
// Sum<=P1*Q1+P2*Q2; my_madd my_madd_module(Clk, P1, Q1, P2, Q2, Sum);
always @(posedge Clk) begin P1<=A1; P2<=A2; Q1<=B1; Q2<=B2; SumR0<=Sum; SumR1<=SumR0; SumR2<=SumR1; end always @(posedge Clk2) // этот клок в два раза медленнее Clk begin SumDM0<=SumR1; SumDM1<=SumR2; ScalX1<=ScalX1+SumDM0-(ScalX1>>>SHR); ScalX2<=ScalX2+SumDM1-(ScalX2>>>SHR); Z_Res1<=ScalX1[28+SHR:SHR-3]; Z_Res2<=ScalX2[28+SHR:SHR-3]; Res1<=Z_Res1; Res2<=Z_Res2; end endmodule Как я понимаю, основная загвоздка у Квартуса возникает тогда, когда я пытаюсь поместить сотни дублей моего MultOne модуля (в мой кристал влазит 384) мне очень хочется вычислять при N=42, то есть когда задействовано 378 умножителей. Теперь мой вопрос... Могу ли я как-то помочь квартусу, чтобы он стал быстрее компилировать, например, можно ли скомпилить сколько-то этих модулей и физически куда-то в кристалле разместить? Шаманил вокруг LogicLock Regions and Design Partitions Window, но, кажется так запутался, что ничего не могу поделать сам, поэтому прошу помощи у Вас! Пожалуйста, посоветуйте, что мне сделать, чтобы увеличить fmax и не ждать по 5 часов на компиляцию этих нескольких строк кода! ЗЫ: при компиляции в квартусе стоят все опции, которые ускоряют fmaxна основе адвизора! Если их отключать, компиляция конечно за пол часа заканчивается но и fmax даже до 200МГц не дотягивает! Спасибо И
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 20)
|
Mar 18 2011, 21:26
|
Знающий
   
Группа: Свой
Сообщений: 845
Регистрация: 18-10-04
Из: Pereslavl-Zalessky, Russian Federation
Пользователь №: 905

|
Ключевое слово верное - logic lock.
С квартусом лет 6 подробно не работал, но когда-то надо было отдельно синтезировать netlist, потом один экземпляр разместить и развести, сохранить файлы и потом в основном дизайне все экземпляры расставить указывая либо все три файла, либо netlist и placement, либо только netlist. Могут быть трудности с copy-paste-ом, так как микросхема не однородна и может понадобиться не один "штамп". Во-первых, это позволяет зафиксировать fmax. Во-вторых, радикально уменьшает время разработки, даже с учетом нескольких дней на чтение документации и игры с logic lock и virtual pins, так как не только ускоряет разводку, но и уменьшает количество ненужных итераций.
|
|
|
|
|
Mar 19 2011, 09:12
|
вопрошающий
    
Группа: Свой
Сообщений: 1 726
Регистрация: 24-01-11
Пользователь №: 62 436

|
Цитата(des00 @ Mar 19 2011, 07:56)  помочь можно только в том случае, если будет видно модуль умножения сложения. И надо понимать что на таких проекта трассы перевешивают все, поэтому регистры, регистры и еще раз регистры. На входе умножителя регистр, внутри умножителя все регистры, на выходе регистр, тоже самое с памятью и т.д. С Вашим советом я полностью согласен, но, и модуль два умножения плюс сложение - это системная процедура altmult_add, и на входе по два регистра, и на выходе по два... Проверял - больше двух - уже не помогает. Это я уже прошел. Иначе 490МГц я бы не получал!!! И даже если у меня только умножительный модуль, но забитый под 70-80%, то я тоже получаю необходимые мне 400МГц, и ОТДЕЛЬНО, модуль с памятью, тоже нормально работает. Кстати, у меня память работает только на 1/6 от основного клока, то есть мне достаточно клока в 66МГц на запись, а на чтение и того меньше - всего-то 15МГц. Основная проблема возникает только при объединении двух модулей - такое чувство, что квартус не в сосотянии решить такую сложную задачу по размещению - фиттер висит по 5 часов а иногда падает с системной ошибкой. Как Вы думаете, на что еще кроме логик лок стоит обратить внимание (я уже начал разбираться с логик лок, но пока не помогает...) Спасибо И Цитата(Shtirlits @ Mar 19 2011, 01:26)  Ключевое слово верное - logic lock. Спасибо Вам большое, разбираюсь в этом направлении, надеюсь поможет!
|
|
|
|
|
Mar 19 2011, 10:49
|
Знающий
   
Группа: Свой
Сообщений: 574
Регистрация: 9-10-04
Из: FPGA-city
Пользователь №: 827

|
Цитата(iiv @ Mar 19 2011, 12:12)  Основная проблема возникает только при объединении двух модулей - такое чувство, что квартус не в сосотянии решить такую сложную задачу по размещению - фиттер висит по 5 часов а иногда падает с системной ошибкой. Можно попробовать Design Space Explorer, или как он сейчас называется в Altera. В Xilinx ISE нарвался на аналогичную проблему: на одних настройках (таблицах) MAP проект в итоге трассируется, на других - нет. Причём при минимальных правках нужно искать новую "счастливую таблицу" из 100*5 возможных. Проблема появилась при большом количестве плотных макросов с размещением (RPM) и большом количестве блоков ОЗУ. Для получения fmax пришлось навтыкать "ненужные" регистры с запасом, хотя при малом тираже макросов доп. регистры не требовались.
|
|
|
|
|
Mar 19 2011, 14:21
|
вопрошающий
    
Группа: Свой
Сообщений: 1 726
Регистрация: 24-01-11
Пользователь №: 62 436

|
Благодарю Вас за ответы и советы! Цитата(jojo @ Mar 19 2011, 17:05)  Да, и частоту в констрейнах можно уменьшить, чтобы понапрасну не ждать. и так по минимуму  Цитата(jojo @ Mar 19 2011, 17:05)  После трассировки для неправильно размещаемых элементов можно задавать (уточнять) области, где им положено быть. Это если элементы в макрос не входят. Будьте любезны, разъясните, пожалуйста, как это делается. Вот получил я, например, fmax=330MHz вместо ожидаемых 400МГц. И как я это исправлю, куда смотреть? Спасибо
|
|
|
|
|
Mar 19 2011, 15:33
|
Знающий
   
Группа: Свой
Сообщений: 574
Регистрация: 9-10-04
Из: FPGA-city
Пользователь №: 827

|
Цитата(iiv @ Mar 19 2011, 17:21)  Будьте любезны, разъясните, пожалуйста, как это делается. Вот получил я, например, fmax=330MHz вместо ожидаемых 400МГц. И как я это исправлю, куда смотреть? Нужно сопоставлять отчёт анализатора задержек (Timequest др.) и вид проблемного пути на кристалле (FloorPlan Editor и т.п.). Проблемный триггер или блок памяти может быть расположен в "левом" месте на кристалле, вдали от разумного, желаемого положения. Поскольку таких элементов может быть много, их положение можно оптом законстрейнить. Ресурсы ПЛИС расположены немонотонно, например, узкими колонками, простым констрейном размещения дело может не обойтись. В этом случае добавляем в конвейер пустые регистры, которые по алгоритму вроде не нужны, но задержку сокращают. Покажите, если можете, аналогичную картинку своего проекта с подсвечиванием сбойных путей.
Эскизы прикрепленных изображений
|
|
|
|
|
Mar 19 2011, 19:47
|
вопрошающий
    
Группа: Свой
Сообщений: 1 726
Регистрация: 24-01-11
Пользователь №: 62 436

|
Уважаемый jojo, очень Вам благодарен за классные советы и разъяснения. Я, к сожалению, новичек в квартусе (только один год опыта) и, некоторые вещи пока еще не знаю. Цитата(jojo @ Mar 19 2011, 19:33)  Покажите, если можете, аналогичную картинку своего проекта с подсвечиванием сбойных путей. вот как это сделать, не понимаю. Допустим у меня есть собранный проект. ; Logic utilization ; 50 % ; ; Combinational ALUTs ; 23,937 / 113,600 ( 21 % ) ; ; Memory ALUTs ; 84 / 56,800 ( < 1 % ) ; ; Dedicated logic registers ; 60,800 / 113,600 ( 54 % ) ; ; Total registers ; 60800 ; ; Total block memory bits ; 4,131,624 / 5,630,976 ( 73 % ) ; ; DSP block 18-bit elements ; 210 / 384 ( 55 % ) ; Это последний из максимальных, который у меня собирается, но его fmax=398MHz (85С) и 420МГц (0С), то есть чуть-чуть меньше, чем надо. Я кстати заметил, что хоть кристалл и до 60С разогревается во время работы, но данные бывают битые, если fmax меньше 420МГц, хотя у меня клок системы через плл из плиски задается и составляет ровно 400МГц. Возможно где-то нестабильность имеется, ну да ладно, главное я знаю на какую частоту мне все затачивать. По спидгрейдам кристалла, умножители могут работать до 490МГц, все остальное - совсем простое - суммы примерно 40 битных чисел, работающие на полуклоке, то есть на 200МГц от основного клока. Вот получил я Technology Map Viewver на 615 страницах  или Resource Property Editor с огромным числом информации, большая часть которой мне не понятна, или получил картинку от Chip Planner, красивая конечно, но что мне с ней делать, можно по разному ее покрасить, но путей там не видно... Если FanIn кнопку нажимаю, получается сначала какое-то мессиво, а потом квартус зависает с полной загрузкой компьютера. Это здесь именно я должен был увидеть картинку сбойных путей, подскажите, мне, если Вас не затруднит, пожалуйтса! ЗЫ: вроде и компьютер не совсем тормознутый, 2*2.2ГГц с 8 ГБ оперативки. Спасибо И
|
|
|
|
|
Mar 20 2011, 14:17
|
Частый гость
 
Группа: Свой
Сообщений: 135
Регистрация: 31-07-06
Пользователь №: 19 224

|
Цитата По спидгрейдам кристалла, умножители могут работать до 490МГц, все остальное - совсем простое - суммы примерно 40 битных чисел, работающие на полуклоке, то есть на 200МГц от основного клока. Непонятно как у вас законстрейнена времянка, цепи из цитаты должны быть ослабланы мультициклами.
|
|
|
|
|
Mar 20 2011, 14:57
|
вопрошающий
    
Группа: Свой
Сообщений: 1 726
Регистрация: 24-01-11
Пользователь №: 62 436

|
Уважаемые друзья, Jojo, Slawikg, Bogaev_Roman и все, кто помогает мне советами! Огромное вам за советы человеческое СПАСИБО! С Логиклоком я сейчас разбираюсь, и начал на мелкой кошке тренироваться. По последним Вашим замечаниям мне показалось, что я могу что-то еще не учесть. Вдруг вас не затруднит, пробегитесь, пожалуйста по тексту моего проекта, вдруг Вы сразу заметите что-то, что я делаю криво. Буду Вам очень-очень благодарен! Урезал проект до минимума, оставив только самый сложный кусок, который и тормозит ужастно и должен на большой частоте работать. Код module ...
wire [13:0] MidData[0:2]; // приходят из еще одного модуля (выход от ФИФО на МЛАБах) и синхронизованы с Clk wire [31:0] CommonTimers[0:54]; // приходят из еще одного модуля (каунтеры 55 ножек), тоже синхронизованы с Clk wire Clk;
...
DATA_Aq DATA_Aq_module(Clk, MidData, GPIO1_D[25], GPIO1_D[24], GPIO1_D[23], GPIO1_D[29], GPIO1_D[28], CommonTimers); my_pll my_pll_module1(OSC1_50, Clk); // 8-ми кратный умножитель частоты, на выходе должно быть 400МГц endmodule
module DATA_Aq(Clk, In, ClkOut, OutOn, Out, SP1, SP2, InputCounters); parameter N=42; parameter M=100; parameter LSSH=3; parameter MAXLOCBUF=(56>N*9+5)?56:N*9+5; parameter IMPULSEBITS=14; parameter IMPULSELEN=16*1024; input Clk, ClkOut, OutOn, SP1, SP2; input [13:0] In[0:2]; input [31:0] InputCounters[0:54]; output reg Out;
// Memory ////////////////////////////
reg signed [13:0] D[0:2][0:1]; reg signed [13:0] Data[0:2][0:M-1]; wire signed [31:0] ScalY[0:8][0:N-1]; reg signed [31:0] MiddleSum[0:2]; reg [31:0] LocBuf[0:MAXLOCBUF]; wire signed [31:0] ShortSumY[0:8][0:N-1];
reg signed [31+LSSH:0] LevelSumY[0:5]; reg signed [31:0] LevelSum[0:5], ShortSum[0:5]; reg [5:0] cmpres; reg [2:0] cmpton; reg cmpon; reg InDataSW; reg [255:0] OutData; reg [7:0] OutDataLen; reg [IMPULSEBITS-1:0] PosIn, PosOut; reg [31:0] OutCounter; reg [63:0] CurTimer, ImpulseTime, ReadImpulseTime; reg [17:0] NewStatus; reg [7:0] BlockLen; reg [31:0] Counters[0:54]; reg [2:0] MemCounter; reg MemClk; wire [251:0] OutDataMem; wire [251:0] InDataMem;
assign InDataMem[251:238]=Data[0][M-1]; assign InDataMem[237:224]=Data[1][M-1]; assign InDataMem[223:210]=Data[2][M-1];
assign InDataMem[209:196]=Data[0][M-2]; assign InDataMem[195:182]=Data[1][M-2]; assign InDataMem[181:168]=Data[2][M-2];
assign InDataMem[167:154]=Data[0][M-3]; assign InDataMem[153:140]=Data[1][M-3]; assign InDataMem[139:126]=Data[2][M-3];
assign InDataMem[125:112]=Data[0][M-4]; assign InDataMem[111: 98]=Data[1][M-4]; assign InDataMem[ 97: 84]=Data[2][M-4];
assign InDataMem[ 83: 70]=Data[0][M-5]; assign InDataMem[ 69: 56]=Data[1][M-5]; assign InDataMem[ 55: 42]=Data[2][M-5];
assign InDataMem[ 41: 28]=Data[0][M-6]; assign InDataMem[ 27: 14]=Data[1][M-6]; assign InDataMem[ 13: 0]=Data[2][M-6];
my_lmem my_lmem_module1(InDataMem[143: 0], PosIn, InDataSW, PosOut, ClkOut, 1, OutDataMem[143: 0]); // 16*M144 my_lmem2 my_lmem_module2(InDataMem[251:144], PosIn, InDataSW, PosOut, ClkOut, 1, OutDataMem[251:144]); // 216*M9K // Generating modules
generate genvar i, j, k; for(i=0; i<N; i+=2) begin : aaa for(j=0; j<3; j++) begin : bbb for(k=0; k<3; k++) begin : ccc MultOne MultOne_Module(Clk, D[j][0], D[j][1], Data[k][i], Data[k][i+1], InDataSW, ScalY [j+3*k][i], ScalY [j+3*k][i+1], ShortSumY[j+3*k][i], ShortSumY[j+3*k][i+1]); end end end endgenerate
// Initialization of variables
initial begin MemCounter=0; MemClk=0; cmpres=0; InDataSW=0; ImpulseTime=0; ReadImpulseTime=0; OutData=0; OutDataLen=0; PosIn=0; PosOut=0; NewStatus=0; BlockLen=0; CurTimer=0; OutCounter=0; end
// Reading Data from Channels /////// always @(posedge Clk) // клок на 400МГц begin for(int i=0; i<2; i++) for(int j=0; j<3; j++) D[j][i]<=Data[j][i+InDataSW]; for(int j=0; j<3; j++) Data[j][0]<=In[j]; for(int i=0; i<M-1; i++) for(int j=0; j<3; j++) Data[j][i+1]<=Data[j][i]; InDataSW<=~InDataSW; end
always @(posedge MemClk) // программный делитель на 3 от клока на 200МГц, то есть 66.6666МГц begin CurTimer<=CurTimer+1; if(PosIn) PosIn<=PosIn+1; else if(ReadImpulseTime==ImpulseTime && cmpon) begin ImpulseTime<=CurTimer; PosIn<=PosIn+1; for(int i=0; i<55; i++) Counters[i]<=InputCounters[i]; end end
always @(posedge InDataSW) // программный делитель на 2 от клока на 400МГц, то есть 200МГц begin for(int i=0; i<3; i++) begin ShortSum[i*2]<=ShortSumY[i][0]; ShortSum[i*2+1]<=ShortSumY[i][0]-ShortSumY[i][1]; MiddleSum[i]<=MiddleSum[i]+D[i][0]+D[i][1]-(MiddleSum[i]>>>17); end // for(int i=0; i<6; i++) cmpres[i]<=((ShortSum[i]>=LevelSum[i])?1:0); cmpton<=(cmpres==6'h3f && BlockLen!=0)?{cmpton[1:0], 1'b1}:{cmpton[1:0], 1'b0}; // if(MemCounter==2) begin MemCounter<=0; MemClk<=1; cmpon<=(cmpton==7)?1:0; end else begin MemCounter<=MemCounter+1; MemClk<=0; end // if(cmpres==6'h3f) begin for(int i=0; i<6; i++) begin LevelSumY[i]<=LevelSumY[i]-(LevelSumY[i]>>>LSSH)+ShortSum[i]; LevelSum[i]<=LevelSumY[i]>>>LSSH; end end end
always @(posedge SP1) begin NewStatus<={NewStatus[16:0], SP2}; if(NewStatus[17:13]==5'b01010 && NewStatus[4:0]==5'b01010) BlockLen<=NewStatus[12:5]; end
always @(posedge ClkOut) // медленный клок 15МГц для сбора данных с плиски, никак не синхронизован с теми клоками, которые выше, блок написан абы как, так как при этой скорости выжимать производительность не имеет смысла begin if(OutOn==0) begin begin {OutData[254:0], Out}<=OutData; if(OutDataLen>0) OutDataLen<=OutDataLen-1; else begin //////////////////////////////// if(OutCounter==0) begin OutDataLen<=63; if(ImpulseTime>ReadImpulseTime) begin OutCounter<=64-57; OutData<={32'h0000ffff, 32'h0000ffff}; LocBuf[0]<=ImpulseTime[63:32]; LocBuf[1]<=ImpulseTime[31:0]; for(int i=0; i<55; i++) LocBuf[i+2]<=Counters[i]; end else begin OutCounter<=512-N*9-5; OutData<={32'h0000ffff, 32'h0000aaaa}; LocBuf[0]<=CurTimer[63:32]; LocBuf[1]<=CurTimer[31:0]; for(int i=0; i<N*9; i++) LocBuf[i+2]<=ScalY[i%9][i/9]; for(int i=0; i<3; i++) LocBuf[i+N*9+2]<=MiddleSum[i]; end end //////////////////////////////// else if(OutCounter==63) begin OutCounter<=512; OutData<=LocBuf[0]; end //////////////////////////////// else if(OutCounter==511) begin OutCounter<=0; OutData<=LocBuf[0]; end //////////////////////////////// else if(OutCounter<511) begin OutDataLen<=31; OutCounter<=OutCounter+1; OutData<=LocBuf[0]; for(int i=1; i<MAXLOCBUF; i++) LocBuf[i-1]<=LocBuf[i]; end //////////////////////////////// else if(OutCounter<64*BlockLen+511) begin PosOut<=PosOut+1; OutCounter<=OutCounter+1; OutDataLen<=251; OutData<=OutDataMem; end else //////////////////////////////// begin PosOut<=0; OutCounter<=0; OutDataLen<=251; OutData<=OutDataMem; ReadImpulseTime=ImpulseTime; end end end end end endmodule
module MultOne(Clk, A1, A2, B1, B2, SW, Res1, Res2, PRes1, PRes2); parameter SHR=18; parameter RSH=5; input Clk, SW; input signed [13:0] A1, A2, B1, B2; output reg signed [31:0] Res1, Res2; output reg signed [31:0] PRes1, PRes2;
reg signed [13:0] P1, P2, Q1, Q2; reg signed [28:0] Sum; reg signed [28:0] SumR0, SumR1, SumR2, SumDM0, SumDM1;
// reg signed [31:0] Mul1, Mul2; reg signed [28+SHR:0] ScalX1, ScalX2; reg signed [28+RSH:0] ScalZ1, ScalZ2;
reg signed [31:0] Z_Res1, Z_Res2; reg signed [31:0] Z_PRes1, Z_PRes2;
my_madd my_madd_module(Clk, P1, Q1, P2, Q2, Sum); // мегафункция altmult_add
always @(posedge Clk) // частота 400МГц begin P1<=A1; P2<=A2; Q1<=B1; Q2<=B2; // Mul1<=P1*Q1; Mul2<=P2*Q2; Sum<=Mul1+Mul2; SumR0<=Sum; SumR1<=SumR0; SumR2<=SumR1; end always @(posedge SW) // половина частоты Clk begin SumDM0<=SumR1; SumDM1<=SumR2; // ScalX1<=ScalX1+SumDM0-(ScalX1>>>SHR); ScalX2<=ScalX2+SumDM1-(ScalX2>>>SHR); Z_Res1<=ScalX1[28+SHR:SHR-3]; Z_Res2<=ScalX2[28+SHR:SHR-3]; Res1<=Z_Res1; Res2<=Z_Res2; // ScalZ1<=ScalZ1+SumDM0-(ScalZ1>>>RSH); ScalZ2<=ScalZ2+SumDM1-(ScalZ2>>>RSH); Z_PRes1<=ScalZ1[28+RSH:RSH-3]; Z_PRes2<=ScalZ2[28+RSH:RSH-3]; PRes1<=Z_PRes1; PRes2<=Z_PRes2; end endmodule а констрейны написаны в файле так: Код set_time_format -unit ns -decimal_places 3
#************************************************************** # Create Clock #**************************************************************
derive_clocks -period "1.0" create_clock -name {GPIO1_D[29]} -period 1000. -waveform {0.0 500.} [get_ports {GPIO1_D[29]}] create_clock -name {GPIO1_D[25]} -period 60. -waveform {0.0 30.} [get_ports {GPIO1_D[25]}]
########################
create_clock "DATA_Aq:DATA_Aq_module|InDataSW" -name {DATA_Aq:DATA_Aq_module|InDataSW} -period 4.8 -waveform {0.0 2.4} create_clock "DATA_Aq:DATA_Aq_module|MemClk" -name {DATA_Aq:DATA_Aq_module|MemClk} -period 28.8 -waveform {0.0 14.4}
########################
derive_pll_clocks
#************************************************************** # Create Clock #**************************************************************
create_clock "OSC2_50" -name "CLK" -period 20
#************************************************************** # Create Generated Clock #**************************************************************
create_generated_clock -master_clock 20. -source "OSC1_50" -name "CLK_OUT" -multiply_by 8 -divide_by 1 create_generated_clock -master_clock 20. -source "OSC1_50" -name "Clk" -multiply_by 8 -divide_by 1 [get_ports {my_pll_module1|altpll_component|auto_generated|pll1|clk[0]}] Спасибо! ЗЫ несколько редактирований этого сообщения были вызваны глюком при набивке сообщения и желанием откоментарить текст для удобства восприятия
Сообщение отредактировал iiv - Mar 20 2011, 15:26
|
|
|
|
|
Mar 20 2011, 15:48
|
Профессионал
    
Группа: Свой
Сообщений: 1 088
Регистрация: 20-10-09
Из: Химки
Пользователь №: 53 082

|
Было бы гораздо удобней разбираться, если б Вы привели отчет временного анализатора: Timequest timing analyzer там report top failing paths и критичные пути. Мне лично не нравится запись: Код MiddleSum[i]<=MiddleSum[i]+D[i][0]+D[i][1]-(MiddleSum[i]>>>17); Сколько здесь будет последовательных сумматоров/вычитателей - 2 или 3? Как quartus их раскидает непонятно. D у Вас работает на частоте CLK, MiddleSum на частоте InDataSW - которая вообще есть выход триггера (пойдет по шине тактовых частот?). Здесь я так понимаю и есть косяк уж точно. Может переписать и работать так: Код always @(posedge CLK) //здесь основная чатсота if (InDataSW) //здесь разрешающий вход для триггеров begin for(int i=0; i<3; i++) begin ShortSum[i*2]<=ShortSumY[i][0]; ShortSum[i*2+1]<=ShortSumY[i][0]-ShortSumY[i][1]; MiddleSum[i]<=(MiddleSum[i]+D[i][0])+(D[i][1]-(MiddleSum[i]>>>17));//Здесь в явном виде, чтоб было наверняка 2 последовательных сумматора/вычитателя end PS/ У Вас очень много частот и нет вообще уверенности, чтоб Вы их правильно использовали и они шли именно по сетке частот. Получайте их на PLL если есть возможность или/и используйте если они кратные разрешающие сигналы на триггерах - по частоте точно уж не проиграете, а вот разводится будет быстрее гораздо. PS2/ Частота clk - 400МГц (период 2,5ns), по коду InDataSW получается в два раза меньше Цитата always @(posedge Clk) InDataSW<=~InDataSW , а в ограничениях Цитата InDataSW" -name {DATA_Aq:DATA_Aq_module|InDataSW} -period 4.8 -waveform {0.0 2.4}
Сообщение отредактировал bogaev_roman - Mar 20 2011, 15:58
|
|
|
|
|
Mar 20 2011, 16:14
|
вопрошающий
    
Группа: Свой
Сообщений: 1 726
Регистрация: 24-01-11
Пользователь №: 62 436

|
Уважаемый Роман, огромное спасибо Вам за советы и помощь! Косяк с MiddleSum - действительно мой косяк, правда который совсем, как оказалось, не влияет на получаемый результат, приходящий сигнал имеет постоянное значение, и это кривое усреднение не сказывается на получаемом результате. Уже придумал как переписать это все правильно и для работы с одним клоком. У меня к Вам два вопроса, я, к сожалению, не все до конца с понимаю с Квартусом и с терминологией, помогите, пожалуйста: Цитата(bogaev_roman @ Mar 20 2011, 19:48)  Было бы гораздо удобней разбираться, если б Вы привели отчет временного анализатора: Timequest timing analyzer там report top failing paths и критичные пути. Вот Timequest timing analyzer я в репорте имею, а вот где в нем можно найти этот report top failing paths, тыкните, пожалуйста, моим носом в точное место и простите великодушно за такой мой глупый вопрос! Цитата(bogaev_roman @ Mar 20 2011, 19:48)  PS/ У Вас очень много частот и нет вообще уверенности, чтоб Вы их правильно использовали и они шли именно по сетке частот. Получайте их на PLL если есть возможность или/и используйте если они кратные разрешающие сигналы на триггерах - по частоте точно уж не проиграете, а вот разводится будет быстрее гораздо. Правильно ли я понимаю, что если я буду использовать разрешающие сигналы на тригеррах, то этот кусок кода все еще должен констрейниться на высокой частоте. То есть если есть конструкция Код always @(posedge CLK) //здесь основная чатсота 400МГц if (InDataSW) //здесь разрешающий вход для триггеров begin .... // вот здесь могу ли я выполнять операции, которые длятся 5нс (200МГц) или все-таки только 2.5нс? end Если так, то мне подойдет решение только на ПЛЛ... Спасибо, и простите за глупые вопросы, я, пока еще только разбираюсь! Вот тут запутался в Вашем ответе, пожалуйста, помогите! Мне нужен один клок Clk для умножителей 400МГц и половинный клок InDataSW (200МГц) для сумм. Я не могу понять, что же я не правильно сделал: PS2/ Частота clk - 400МГц (период 2,5ns), по коду InDataSW получается в два раза меньше Цитата always @(posedge Clk) InDataSW<=~InDataSW, а в ограничениях Цитата InDataSW" -name {DATA_Aq:DATA_Aq_module|InDataSW} -period 4.8 -waveform {0.0 2.4} разве я не законстрейнил InDataSW на частоту 1000/4.8=208MHz? ЗЫ с одним вопросом про разрешающие сигналы - разобрался, поэтому поправил свой ответ
Сообщение отредактировал iiv - Mar 20 2011, 16:38
|
|
|
|
|
Mar 21 2011, 09:49
|
Профессионал
    
Группа: Свой
Сообщений: 1 088
Регистрация: 20-10-09
Из: Химки
Пользователь №: 53 082

|
По поводу правильного использования timequest для начала советую посмотреть блог des00 http://embedders.org/blog/des00 - очень хорошо и понятно написано Для правильного использования инкрементальной компиляции, создание partition и logic lock - перевод документации от naliwator http://www.naliwator.narod.ru/Цитата Вот Timequest timing analyzer я в репорте имею, а вот где в нем можно найти этот report top failing paths, тыкните, пожалуйста, моим носом в точное место и простите великодушно за такой мой глупый вопрос! Да не надо отчета. Все просто - окно в квартусе task, далее timequest timing analysis, вкладкой timequest timing analyzer запускаете анализатор. В анализаторе окно tasks выбираете вкладку reports->macros и два раза ЛК на report top failing paths. В окне report увидите все критические пути по частотам, которые не проходят ограничения. Далее выбирайте каждый путь и смотрите для него все задержки. Картинки, к сожалению, привести нет возможности... Цитата Правильно ли я понимаю, что если я буду использовать разрешающие сигналы на тригеррах, то этот кусок кода все еще должен констрейниться на высокой частоте. Вы должны будете только констрейнить основную тактовую частоту. Фактически будете работать именно на ней. Кстати в чем проблема на одной PLL получить частоту и 200 и 400 МГц, они же кратные? Цитата Мне нужен один клок Clk для умножителей 400МГц и половинный клок InDataSW (200МГц) для сумм. Я не могу понять, что же я не правильно сделал: На так в ограничениях Вы указываете не 200МГц, а 208. Ну и чего у Вас будет в момент их "перекрывания", т.е. когда фронты будут примерно "совпадать" - лажа будет. Мне казалось, что так должно быть: Код InDataSW" -name {DATA_Aq:DATA_Aq_module|InDataSW} -period 5.0 -waveform {0.0 2.5} И, используя pll, Вам эта запись вообще не понадобиться.
|
|
|
|
|
Apr 3 2011, 11:15
|
вопрошающий
    
Группа: Свой
Сообщений: 1 726
Регистрация: 24-01-11
Пользователь №: 62 436

|
Добрый день, Роман,
огромное Вам спасибо за советы и ссылки про таймквест и логиклок - сильно помогло.
Поставил все клоки через ПЛЛ, стало проще и нагляднее.
Есть один момент, даже не знаю как правильно объяснить, помогите, пожалуйста, советом, как правильно.
Основной клок у меня 400МГц, я его получаю из ПЛЛ на основе входной 50МГц частоты. Если у меня получаются фмакс(85С)=390-410, фмакс(0С)=400-420, то на практике имеются ошибки. Похоже где-то у меня не устойчиво частота получается. Я для этого хочу в ПЛЛ указать частоту 400МГц, а Квартус заставить компилиться на 420МГц. Этим вызвано то, что я указывал большие частоты в SDC файле. Скажите, пожалуйста, есть ли какой-то более правильный подход?
И еще сразу вопрос... Читал про таймквест, но, до конца не понял, вдруг не сложно будет, посоветуйте, пожалуйста.
Сейчас у меня есть 15 клоков. Все кроме 3-х из них - это асинхронные вводы-выводы, данные между которыми ходят через FIFO. Правильно ли я понимаю, что для всех этих клоков я должен написать в SDC такую инструкцию:
set_clock_groups -exclusive -group {GPIO1_D[29]}
А вот три клока генерятся одним ПЛЛ и имеют четко прописанные частоты 400МГц, 200МГц и 66.(6)МГц и данные между этими домейнами постоянно гуляют туда и обратно. Правильно ли я понимаю, что их как раз ни как не надо описывать?
Спасибо
И
|
|
|
|
|
Apr 4 2011, 14:59
|
Профессионал
    
Группа: Свой
Сообщений: 1 088
Регистрация: 20-10-09
Из: Химки
Пользователь №: 53 082

|
Цитата три клока генерятся одним ПЛЛ и имеют четко прописанные частоты 400МГц, 200МГц и 66.(6)МГц и данные между этими домейнами постоянно гуляют туда и обратно. Правильно ли я понимаю, что их как раз ни как не надо описывать? Входная частота у Вас 50МГц, вот ее и объявляете в качестве входной, а далее просто derive_pll_clock. Timequest сам определит для них частоту и соотношения между ними, согласно установкам мегафункции pll. Для них вроде бы больше ничего и неда объявлять. Цитата Сейчас у меня есть 15 клоков. Все кроме 3-х из них - это асинхронные вводы-выводы, данные между которыми ходят через FIFO. Если эти сигналы никак не связаны с логикой, которая работает на 3 остальных частотах, то вроде бы ничего не требуется. Цитата Основной клок у меня 400МГц, я его получаю из ПЛЛ на основе входной 50МГц частоты. Если у меня получаются фмакс(85С)=390-410, фмакс(0С)=400-420, то на практике имеются ошибки. Похоже где-то у меня не устойчиво частота получается. Я для этого хочу в ПЛЛ указать частоту 400МГц, а Квартус заставить компилиться на 420МГц. На какой практике? Возможно два варианта: 1) Заданы не все ограничения - что-то не учли, может проблем с времянкой нет от триггера до триггера, есть проблемы с ограничениями на вход/выход. 2) Идет граничная ситуация и Fmax все-таки меньше заданной, читайте внимательно отчет timequest и выведете все сигналы, непроходящие по частоте - report top failing patch. Поднять частоту на 10% можно с помощью настроек синтезатора/фиттера, если оптимизация кода не спасает и не хочется липить лишних partition, но это последнее дело. Настройки сильно зависят от проекта и все-таки замедляют скорость компиляции. Для себя выделил основные настройки следующие: физический синтез - extra, дублирование регистров analisys & synthesys - отключить удаление регистров дубликатов, оптимизация по скорости фиттер - стандарт, уровень оптимизации роутера - максимальный Может помочь и банальное изменение начальной точки разводки - seed
Сообщение отредактировал bogaev_roman - Apr 4 2011, 15:03
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|