CaPpuCcino 0 14 июля, 2005 Опубликовано 14 июля, 2005 · Жалоба _for (i=i_start; i<i_stop; i++) ___for (j=j_start; j>j_stop; j--) _____do_something; думается мне Уважаемая публика ни раз сталкивалась с проблемой перенесения какого-либо алгоритма, описаного в терминах последовательной интерпретации, в аппаратуру. как-то погожим весенним днём мне пришла в голову мысль - а как другие дяденьки и тётеньки (ну в основном конечно дяденьки) справляются с такой привычной простому смертному программеру, как цикл FOR, задачей? Есть ли на вооружении Уважаемой публики какие-нибудь обощённые методики - взаимодействующие счётчики, стили описания единой стэйт-машины или ещё чо-нить? в общем, кто как видит уложение цикла вверху в аппаратуру? оч интересно! :cranky: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Iouri 0 15 июля, 2005 Опубликовано 15 июля, 2005 · Жалоба vse zavisit ot togo, chto konkretnos delau, esli delau, chto tipa ustroystva sravneniya, ili ALU to staraus ne ispolzovat, tak kak to chto implimentiruetsya v zheleze, staraus delat neposredstvenno. Neskolko raz zamechal problemi s implimentaciey Fore loop v osnovnom ispolzuu dlya test bench Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bve 1 15 июля, 2005 Опубликовано 15 июля, 2005 · Жалоба Что есть "перенос в аппаратуру"? Если реалиазия на ПЛИС - то очень часто то, что записано в программе как последовательные операции, выполняется параллельно, либо организуется нечто вроде линии задержки, либо гоним импульс разрешения через сдвиговый регистр, и.т.д. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CaPpuCcino 0 15 июля, 2005 Опубликовано 15 июля, 2005 · Жалоба да, наверно нужно срау было обЪяснить, что я имею в виду под последовательной интерпритацией. ну давайте попробуем: значения переменных цикла i и j участвуют в дальнейших вычислениях каких-либо функций (при этом видно что i и j друг от друга не зависят) - наиболее распространённым примером было бы вычисление адреса памяти по какой-нибудь формуле - например mem_addr=i*const_a+j*const_b. то есть в каждый цикл системы (например каждый clock) проиcxодит следующая итерация самого глубокo вложенного цыкла FOR например: void write(int address, int value){...} ~~ for (i=10;i<1024;i++) ~~~ for (j=512;j>10;j--) ~~~~ video_memory.write(i*screen_width+j, pixel_buffer); будет записывать в память дисплея значение пиксель буфера в порядке от 10 до 1023 строки от 512 до 11 столбца. (ток не спрашивайте зачем -- это просто пример) терь по-понятней? :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pegas_ 0 16 июля, 2005 Опубликовано 16 июля, 2005 · Жалоба да, наверно нужно срау было обЪяснить, что я имею в виду под последовательной интерпритацией. ну давайте попробуем: значения переменных цикла i и j участвуют в дальнейших вычислениях каких-либо функций (при этом видно что i и j друг от друга не зависят) - наиболее распространённым примером было бы вычисление адреса памяти по какой-нибудь формуле - например mem_addr=i*const_a+j*const_b. то есть в каждый цикл системы (например каждый clock) проиcxодит следующая итерация самого глубокo вложенного цыкла FOR например: void write(int address, int value){...} ~~ for (i=10;i<1024;i++) ~~~ for (j=512;j>10;j--) ~~~~ video_memory.write(i*screen_width+j, pixel_buffer); Существует три основных стиля программирования на VHDL - структурный, поведенческий, потоковый. Для реализации вышеуказанной конструкции по моему лучше всего подойдут первые два. Структурный стиль - мы описываем в двух процессах два счетчика. Оба счетчика работают от одной тактововой. Счетчик i инкрементируется по переполнению счетчика j. Причем у обоих счетчиков задаются коэффты пересчета i_count:process(clk, rst) begin if rst='0' then i=10; elsif Rising_Edge(clk) then if j=11 then if i=511 i=10; else i=i+1; end if; end if; end if; end process; j_count: process(clk,rst) begin if rst='0' then j=512 elsif Rising_edge(clk) then if j=11 then j=512 else j=j-1; end if; end if; end process; process(clk,rst) begin ---- здесь вы пишите ваши функции от i и j, синхронно к clk end process; Вообщето некторые товарищи могут сказать что это поведенчиский стиль. Частично соглашусь. Трудно провести четкую грань. С моей точки зрения вариант на поведенческом стиле будет выглядеть так process() begin if (i.....) then if (j... ) then wait until Rising_Edge(clk); end if; end process Во.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CaPpuCcino 0 18 июля, 2005 Опубликовано 18 июля, 2005 (изменено) · Жалоба Спасибо, _pegas_ , нечто подобное делаю и я, хотя по-моему ваш вариант "более поведенческий", чем мой. вот мой код: looper.v //for (i=i_start; i<=i_stop; i++) // for (j=j_start; j=>j_stop; j--) // do_something; module looper (clk, reset_n, i_external_cycle_block, j_external_cycle_block, i_variable_reg, j_variable_reg); `include "power.v" ////////////////////////////////////////////////////////////////////// // This module is prepared for less-or-equal(<=) or higher-or-equal(=>) loops. // It is obvious that less(<) and higher(>) loops can be easily adjusted to // the form of less-or-equal(<=) or higher-or-equal(=>) loops mearly by recalculation // of the limits. ////////////////////////////////////////////////////////////////////// // cycle ranges // i-loop parameter i_start=273; parameter i_stop=361; parameter i_max=max(i_start, i_stop); // j-loop parameter j_start=55; parameter j_stop=51; parameter j_max=max(j_start, j_stop); ////////////////////////////////////////////////////////////////////// parameter i_trancation=start_stop_trancation_value (i_start, i_stop); parameter j_trancation=start_stop_trancation_value (j_start, j_stop); parameter i_cycle_reg_width=(i_trancation==0)? number_of_bits_for_value_representation(i_max):number_of_bits_for_value_represen tation(i_stop-i_start); parameter j_cycle_reg_width=(j_trancation==0)? number_of_bits_for_value_representation(j_max):number_of_bits_for_value_represen tation(j_start-j_stop); parameter i_variable_reg_width=number_of_bits_for_value_representation(i_max); parameter j_variable_reg_width=number_of_bits_for_value_representation(j_max); parameter i_hstart=i_start-i_trancation; parameter i_hstop=i_stop-i_trancation; parameter j_hstop=j_stop-j_trancation; parameter j_hstart=j_start-j_trancation; input clk; input reset_n; input i_external_cycle_block; input j_external_cycle_block; reg [i_cycle_reg_width-1:0] i_cycle_reg; reg [j_cycle_reg_width-1:0] j_cycle_reg; output reg [i_variable_reg_width-1:0] i_variable_reg; output reg [j_variable_reg_width-1:0] j_variable_reg; reg i_cycle_block; reg i_internal_cycle_block; reg j_cycle_block; wire j_internal_cycle_block; assign j_internal_cycle_block=0; // for (i=i_start;i<=i_stop;i++) { always @ (posedge clk) begin if (~reset_n) begin i_cycle_reg<=i_hstart; end else begin if (i_cycle_block==0) begin if (i_cycle_reg == i_hstop) i_cycle_reg<=i_hstart; else i_cycle_reg<=i_cycle_reg+1; end end end always @* begin i_cycle_block=i_internal_cycle_block|i_external_cycle_block; end // for (j=j_start;j>=j_stop;j--) { always @* begin if (j_cycle_reg == j_hstop) i_internal_cycle_block=0; else i_internal_cycle_block=1; end always @ (posedge clk) begin if (~reset_n) begin j_cycle_reg<=j_hstart; end else begin if (j_cycle_block==0) begin if (j_cycle_reg == j_hstop) j_cycle_reg<=j_hstart; else j_cycle_reg<=j_cycle_reg-1; end end end always @* begin j_cycle_block=j_external_cycle_block|j_internal_cycle_block; end // }//for_j // }//for_i generate if (start_stop_trancation_value (i_start, i_stop)!=0) begin reg [i_variable_reg_width-i_cycle_reg_width-1:0] i_variable_upper_bits; reg [i_variable_reg_width-1:0] i_auxilary; always @* begin i_auxilary=i_max; i_variable_upper_bits=i_auxilary[i_variable_reg_width-1:i_cycle_reg_width]; i_variable_reg={i_variable_upper_bits,i_cycle_reg}; end end else begin always @* begin i_variable_reg=i_cycle_reg; end end endgenerate generate if (start_stop_trancation_value (j_start, j_stop)!=0) begin reg [j_variable_reg_width-j_cycle_reg_width-1:0] j_variable_upper_bits; reg [j_variable_reg_width-1:0] j_auxilary; always @* begin j_auxilary=j_max; j_variable_upper_bits=j_auxilary[j_variable_reg_width-1:j_cycle_reg_width]; j_variable_reg={j_variable_upper_bits,j_cycle_reg}; end end else begin always @* begin j_variable_reg=j_cycle_reg; end end endgenerate endmodule power.v function integer max(input integer a, input integer b ); begin max = (a >= b ) ? a : b ; end endfunction function integer number_of_bits_for_value_representation (input integer value); integer temp; begin temp = 2; number_of_bits_for_value_representation = 1; while (temp<=value) begin number_of_bits_for_value_representation = number_of_bits_for_value_representation+1; temp = temp*2; end end endfunction function integer start_stop_trancation_value (input integer start, input integer stop); integer difference; integer power_diff; integer power_max; integer temp_diff; integer temp_max; integer max; integer min; integer min_masked; integer max_masked; begin temp_diff=1; temp_max=1; max=(start>stop)?start:stop; min=(start<=stop)?start:stop; difference=(start>stop)?(start-stop):(stop-start); power_diff=number_of_bits_for_value_representation(difference); power_max=number_of_bits_for_value_representation(max); repeat (power_diff) begin temp_diff=temp_diff*2; end temp_diff=temp_diff-1; temp_diff=~temp_diff; repeat (power_max) begin temp_max=temp_max*2; end temp_max=temp_max-1; min_masked=(min&temp_diff)&temp_max; max_masked=(max&temp_diff)&temp_max; if ((min_masked^max_masked)==0) start_stop_trancation_value=max&temp_diff; else start_stop_trancation_value=0; end endfunction Существует три основных стиля программирования на VHDL - структурный, поведенческий, потоковый. Для реализации вышеуказанной конструкции по моему лучше всего подойдут первые два. <{POST_SNAPBACK}> к стсати уважаемый _pegas_ - не могли бы вы как-нть простенько обЪяснить в чём разница между структурным и потоковым описанием - у меня сложилось такое впечатление что они отличаются только единицей видиния - в одном случае блок - в другом путь данных - но при реализации разница только в реализации соединений -- или я что-т не понял? Изменено 19 июля, 2005 пользователем CaPpuCcino Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
v_mirgorodsky 0 18 июля, 2005 Опубликовано 18 июля, 2005 · Жалоба A pochemu bi ne vspomnit' starika Okkama? Menee chem dva schetchika sdes' vse ravno ne budet, vichisleniye funktsii ot i, j nikuda tozhe ne denetsya, telo tsikla tozhe ostanetsya. Takim obrazom poluchaem spisok osnovnih deystvuyuschih lits etoy sceni. Kak ih soedinit' i kak rassmatrivat' s'hemu - eto uzhe vopros esteticheskih soobrazheniy, a ne inzhenernih. Voobsche govorya, chem dal'she vi uydete ot zheleza, tem menee optimal'no skompiliruet vashe opisanie sintezator. Sdes' vidna analogiya s pervimi C/C++ kompilyatorami. Poka vichislitel'naya moschnost' komp'yuterov bila slaboy ochen' chasto primenyalis' optimiziruyuschie vstavki na Assemblere, po mere rosta vichislitel'noy moschnosti processorov i ob'emov pamyati Assemblernaya optimizatsiya stanovitsya vse bolee redkim yavleniem. Nuzhno, odnako, otmetit', chto i kompilyatori stanovilis' "umnee". Tak proizoydet i s VHDL/Verilog/... i drugimi sintezatorami. Kogda schet yacheek v nebol'shoy po stoimosti PLIS poydet na desyatki tisyach, a taktovie chastoti osnovatel'no perevalyat za gigaherts, togda i mozhno budet izobretat' proekti na grani sinteziruemosti - effectivnost' PLIS v kupe s taktovoy chastotoy "s'edyat" ne optimal'nost' sintezatora, a do togo vremeni vse zhe luchshe poblizhe k zhelezu. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maxus 0 1 августа, 2005 Опубликовано 1 августа, 2005 · Жалоба Работаю с Quartus. Могу сказать, что можно перенести только операции над регистрами или связями. С помощью for описываешь алгоритм, по которому данные будут изменяться. Quartus на основании этого сгенерит комбинационую схему. В других случаях ничего не получиться. Все же нужно понимать, что в ПЛИС все делаеться паралельно. Если надо нечто последовательное, то лучше обойтись без циклов for и тд, а написать все самому. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CaPpuCcino 0 1 августа, 2005 Опубликовано 1 августа, 2005 · Жалоба Работаю с Quartus. Могу сказать, что можно перенести только операции над регистрами или связями. С помощью for описываешь алгоритм, по которому данные будут изменяться. Quartus на основании этого сгенерит комбинационую схему. В других случаях ничего не получиться. Все же нужно понимать, что в ПЛИС все делаеться паралельно. Если надо нечто последовательное, то лучше обойтись без циклов for и тд, а написать все самому. <{POST_SNAPBACK}> точно - именно поэтому, если посмотреть на оба кода, вы не заметите конструкции for - потому как она в этих языках вспомогательная в случае синтеза - препроцессорная - речь как раз и идёт о стилях, которые мы используем для получения эквивалента последовательной циклической обработки данных (людям читающим этот пост на будущее - пожалуйста не подумайте что мы мало знакомы с синтексом языков на которых пишем - для чего нужны операторы for, repeat и while в VHDL и Verilog мы догадываемся :cheers: ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться