ZED 0 7 апреля, 2009 Опубликовано 7 апреля, 2009 · Жалоба Во-первых, подправьте код умножителей под диапазон коэффициентов -1024 ... +1024, поскольку после умножения делить нам надо теперь на 1024. Поправил, прилагается; о-вторых, теперь, когда мы разобрались с умножением, нужен ли нам 0-ой умножитель в блоке умножителей? Думаю нет, зачем нам постоянно умножать на 1? В-третьих, в начале было решено, что вычисление бабочки и умножение на коэф. делаем за один такт. В таком случае, регистры на выходе бабочки нужно перенести на выход умножителей. Вот тут я не совсем понял, получается мне код для умножителей нужно впихнуть в код для бабочки? Код бабочки прилагаю: http://webfile.ru/3392071 В-четвертых, все блоки нашего БПФ имеют на входе и выходе один и тот же набор сигналов (относящийся к данным БПФ) и эти сигналы представляют собой комплексные числа. Я предлагаю воспользоваться такой возможностью языка как record и задать тип complex_data и complex_coef для данных и коэффициентов. Еще задать тип complex_data_vector и complex_coef_vector с параметризованной размерностью, чтобы не "таскать" везде по четыре сигнала данных и по три сигнала с коэффициентами. Все это, для удобства, объявить в package - скажем fft_pkg. Все сказанное в это пункте никак не влияет на работоспособность, поэтому если не хотите, то можете этого не делать. Сделаю позже, пока нужно с 3 пунктом разобраться. Вы с ModelSim работали? Работал немного. complex_multiplier.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 7 апреля, 2009 Опубликовано 7 апреля, 2009 · Жалоба Вот тут я не совсем понял, получается мне код для умножителей нужно впихнуть в код для бабочки? С чего Вы это взяли? Никто никого не обязывает ставить регистры на выходе блока. Чисто комбинаторный блок это вполне нормально. Я имел ввиду, что бабочка у нас не будет содержать регистров - будет чисто комбинаторной, а умножители будут иметь регистры на выходе. Впрочем, если хотите, то можете поставить регистры на выходе и бабочки и умножителей - это увеличит pipeline на 1 и практически никак не повлияет на скорость вычисления самого БПФ (ну будет БПФ вычисляться на 6 тактов дольше, ну и что...) Кстати, о бабочке. Пока Вы не убрали из нее регистры, объясните мне пожалуйста, почему бабочка тратит на вычисления аж 2 такта вместо 1? Зачем Вы сделали двойное защелкивание? Бабочка (в отличие, например, от умножителей, особенно если их синтезировать на обычных ячейках, а не на DSP-блоках) выполняет настолько простые операции, что защелкивать промежуточный результат абсолютно бессмысленно - лишняя трата регистров :). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 8 апреля, 2009 Опубликовано 8 апреля, 2009 · Жалоба Чисто комбинаторный блок это вполне нормально. Я имел ввиду, что бабочка у нас не будет содержать регистров - будет чисто комбинаторной, а умножители будут иметь регистры на выходе. Да, но бабочка содержит процесс, а это уже регистр. процесс убрать нельзя, т.к. конструкция if последовательная, а значит может содержаться только в процессе. Тут вижу выход только описывать эти 2 бабочки как компоненты, а затем применять конструкцию if generate. Ну можно в процесс засунуть тупо все сигналы, чтобы он запускался при изменении каждого из них. Кстати, о бабочке. Пока Вы не убрали из нее регистры, объясните мне пожалуйста, почему бабочка тратит на вычисления аж 2 такта вместо 1? Зачем Вы сделали двойное защелкивание? Я его не хотел делать, так вышло=)) Но тем не менее Quartus ставит промежуточный регистр. Это происходит как раз из-за различных назначений сигналам yi_re_sig/yi_im_sig, i=0,1,2,3 при конструкции if else/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 9 апреля, 2009 Опубликовано 9 апреля, 2009 · Жалоба На счет if generate я погорячился, даже сказал бы тупанул, можно просто каждый сигнал yi_re_sig/yi_im_sig, i=0,1,2,3 посадить на case/ Таким образом уберется процесс и сгенеряться мультиплексоры. бабочка станет чисто комбинационной. Вечером попробую... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 9 апреля, 2009 Опубликовано 9 апреля, 2009 · Жалоба Да, но бабочка содержит процесс, а это уже регистр. На счет if generate я погорячился, даже сказал бы тупанул, можно просто каждый сигнал yi_re_sig/yi_im_sig, i=0,1,2,3 посадить на case/ Таким образом уберется процесс и сгенеряться мультиплексоры. бабочка станет чисто комбинационной. Вечером попробую... Спокойствие... только спокойствие. process никогда и ни при каких обстоятельствах не является признаком регистра. Покажите мне того человека, который сказал Вам, что "process - это регистр" ? Синтезатор "детектирует" наличие регистра по конструкциям вида CLK'event and CLK = '1', rising_edge(clk) и т.д. Если Вы напишите такой, например, код process(SEL,B,C,D,E) begin if SEL = '0' then A <= B or C; else A <= C and D; end if; end process то получите обычную комбинаторную логику - никаких регистров синтезатор и не подумает поставить. Причем, если вместо process(SEL,B,C,D,E) Вы напишите process(SEL,B,C), то синтезатор все сделает правильно, но вот симулятор просимулирует неправильно. Если вне всякого процесса Вы напишите A <= B when rising_edge(CLK) else A; то получите регистр и без использования process. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 9 апреля, 2009 Опубликовано 9 апреля, 2009 (изменено) · Жалоба process никогда и ни при каких обстоятельствах не является признаком регистра. Я знаю. Я в принципе так и указал: Ну можно в процесс засунуть тупо все сигналы, чтобы он запускался при изменении каждого из них. Просто сигналов уж больно много. Вот проект: http://webfile.ru/3398933 Изменено 9 апреля, 2009 пользователем ZED Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 9 апреля, 2009 Опубликовано 9 апреля, 2009 · Жалоба Я переправил, просто исправил позже, чем вы ответили... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 9 апреля, 2009 Опубликовано 9 апреля, 2009 · Жалоба Ok. А как обстоят дела с введением record? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 9 апреля, 2009 Опубликовано 9 апреля, 2009 · Жалоба В процессе, сейчас хочу все соединить поскорее, а recordом я не пользовался, нужно почитать, постараюсь завтра сделать. Соеденил: http://webfile.ru/3399176 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 10 апреля, 2009 Опубликовано 10 апреля, 2009 · Жалоба Прошу прощения забыл регистры, на выходе для отсчетов y0_re, y0_im: http://webfile.ru/3400144 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 12 апреля, 2009 Опубликовано 12 апреля, 2009 · Жалоба наконец-то выдалось немного свободного времени - посмотрел Ваш код. 1) Зачем, всетаки, приставка but к портам бабочки ? 2) Зачем в умножителе Вы ввели еще один промежуточный сигнал result_re_buf ? Чем Вам не нравится такой код :) ? process(CLK) begin if (rising_edge(CLK)) then result_re <= std_logic_vector(result_re_sig(b_size + w_size - 3 downto w_size - 2 )); result_im <= std_logic_vector(result_im_sig(b_size + w_size - 3 downto w_size - 2)); end if; end process; 3) Зачем Вам resize в умножителе? Если бы это был просто умножитель предназначенный для чего угодно, то требуется учесть возможность переполнения при +/-. Но тогда и выход должен уже быть не 17 разрядов, а 18. Наш умножитель он только для нашего БПФ годится, а в нашем БПФ в умножителе уже не будет переполнения при +/-. Кстати, объясните почему? 4) Зачем в бабочке регистр на y0? Очень плохая идея и стиль выравнивать задержки не там где создается "перекос". У нас регистры стоят в умножителях, 0-ой умножитель удален за ненадобностью, но раз имменно в нем был регистр, то именно вместо него в блоке умножителей и надо поставить регистр для выравнивания, а не в бабочке. Пока мы разбираемся с кодом бабочки и умножителя и вводим record (как там дела? ) давайте параллельно подумаем про память - нам скоро ей заниматься. Посмотрите, пожалуйста, на последнюю версию блок схемы. Согласно блок-схеме у нас получаются два совершенно разных блока памяти. Что нужно добавить на блок схеме, чтобы блоки памяти у нас были совершенно одинаковыми? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 13 апреля, 2009 Опубликовано 13 апреля, 2009 · Жалоба 1) Зачем, всетаки, приставка but к портам бабочки ? Чтобы не запутаться, убрал... 2) Зачем в умножителе Вы ввели еще один промежуточный сигнал result_re_buf Опять же, чтобы не запутаться, убрал...=) 3) Зачем Вам resize в умножителе? Если бы это был просто умножитель предназначенный для чего угодно, то требуется учесть возможность переполнения при +/-. Но тогда и выход должен уже быть не 17 разрядов, а 18. Наш умножитель он только для нашего БПФ годится, а в нашем БПФ в умножителе уже не будет переполнения при +/-. Кстати, объясните почему? Resize не нужен т.к. мы расширили до 17 разрядов отчсеты и до 12 разрядов поворачивающие множители, убрал... 4) Зачем в бабочке регистр на y0? Очень плохая идея и стиль выравнивать задержки не там где создается "перекос". У нас регистры стоят в умножителях, 0-ой умножитель удален за ненадобностью, но раз имменно в нем был регистр, то именно вместо него в блоке умножителей и надо поставить регистр для выравнивания, а не в бабочке. Перенес регистр из бабочки в блок умножителей. Пока мы разбираемся с кодом бабочки и умножителя и вводим record (как там дела? ) Не было времени разобраться. Посмотрите, пожалуйста, на последнюю версию блок схемы. Согласно блок-схеме у нас получаются два совершенно разных блока памяти. Что нужно добавить на блок схеме, чтобы блоки памяти у нас были совершенно одинаковыми? Не хватает мультиплексора, исправил, прилагаю: http://webfile.ru/3409277 Код полной бабочки: http://webfile.ru/3409275 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 14 апреля, 2009 Опубликовано 14 апреля, 2009 · Жалоба Никак не пойму, что нужно с записью сделать, как она должна выглядеть, вот до чего я пока додумался: library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; package fft_pkg is constant b_size: natural := 17; constant w_size: natural := 12; type complex_data is record x_re: std_logic_vector(b_size - 1 downto 0); x_im: std_logic_vector(b_size - 1 downto 0); end record; type complex_coef is record w_re: std_logic_vector(w_size - 1 downto 0); w_im: std_logic_vector(w_size - 1 downto 0); end record; type complex_data_vector is record x0: complex_data; x1: complex_data; x2: complex_data; x3: complex_data; end record; type complex_coef_vector is record w1: complex_coef; w2: complex_coef; w3: complex_coef; end record; end package fft_pkg; Акак же тогда с проектом быть придется задавать только входной сигнал x, сигнал для коэффициентов w и оперировать типа так: x.x0.x_re это будет x0_re? и с компонентами тогда как получится можно ли будет сделать так: entity full_butterfly is generic (b_size: natural := 17; w_size: natural := 12); port ( CLK: in std_logic; switch: in std_logic; x : in complex_data_vector; w : in complex_coef_vector; y0_re: out std_logic_vector(b_size - 1 downto 0); y0_im: out std_logic_vector(b_size - 1 downto 0); y1_re: out std_logic_vector(b_size - 1 downto 0); y1_im: out std_logic_vector(b_size - 1 downto 0); y2_re: out std_logic_vector(b_size - 1 downto 0); y2_im: out std_logic_vector(b_size - 1 downto 0); y3_re: out std_logic_vector(b_size - 1 downto 0); y3_im: out std_logic_vector(b_size - 1 downto 0) ); end full_butterfly; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . component butterfly_complex is generic (b_size: natural := 17); port( CLK: in std_logic; switch: in std_logic; x: in complex_data_vector; y0_re: out std_logic_vector(b_size - 1 downto 0); y0_im: out std_logic_vector(b_size - 1 downto 0); y1_re: out std_logic_vector(b_size - 1 downto 0); y1_im: out std_logic_vector(b_size - 1 downto 0); y2_re: out std_logic_vector(b_size - 1 downto 0); y2_im: out std_logic_vector(b_size - 1 downto 0); y3_re: out std_logic_vector(b_size - 1 downto 0); y3_im: out std_logic_vector(b_size - 1 downto 0) ); end component butterfly_complex; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . butterfly: butterfly_complex port map( CLK => CLK, switch => switch, x => x; y0_re => y0_re_connect, y0_im => y0_im_connect, y1_re => y1_re_connect, y1_im => y1_im_connect, y2_re => y2_re_connect, y2_im => y2_im_connect, y3_re => y3_re_connect, y3_im => y3_im_connect ); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 16 апреля, 2009 Опубликовано 16 апреля, 2009 · Жалоба Resize не нужен т.к. мы расширили до 17 разрядов отчсеты и до 12 разрядов поворачивающие множители, убрал... К сожалению, объяснить отсутствие переполнения только лишь увеличением разрядности недостаточно. Представьте, к примеру, что x_re = 32768, x_im = 32768, w_re = 1024 и w_im = 1024. В этом случае result_im = (x_re *w_im + x_im *w_re)/1024 = 65536 - однозначно переполнение... Здесь дело в свойствах БПФ. Если все реализовано правильно, то точки, поступающие на вход БПФ всегда находятся внутри единичной окружности на комплексной плоскости. Коеффициенты - это точки лежащие на краю единичной окружности ( w_re = cos(a), w_im = sin(a) ). Так что если w_re = 1024, то w_im неизбежно будет = 0. Поворачивающими их называют не случайно - при умножении на них точка всего лишь поворачивается на угол a. Она никогда не выйдет за пределы этой единичной окружности - это и есть главная причина отсутствия переполнения. Таким образом, если все сделано правильно, то случай x_re = x_im = 32768 исключен так же как и w_re = w_im = 1024. С record Вы все сделали правильно за исключением ненужных услохнений с именами членов record. Достаточно так: type complex_data is record re: std_logic_vector(b_size - 1 downto 0); im: std_logic_vector(b_size - 1 downto 0); end record; Что касается complex_data_vector / complex_coef_vector, то я имел ввиду следующее: type complex_data_vector is array (natural range <>) of complex_data; type complex_coef_vector is array (natural range <>) of complex_coef; Впрочем, (natural range <>) – это больше для тренировки в освоении языка. При таком задании типа complex_data_vector Вы размерность указываете при использовании. т.е. Вы можете написать entity full_butterfly is port ( CLK : in std_logic; switch : in std_logic; x : in complex_data_vector(3 downto 0); w : in complex_coef_vector(3 downto 1); y : out complex_data_vector(3 downto 0) ); end full_butterfly; В нашем случае, я, все же, склоняюсь задать размерность жестко. Т.е. type complex_data_vector is array (3 downto 0) of complex_data; type complex_coef_vector is array (3 downto 1) of complex_coef; тогда entity full_butterfly is port ( CLK : in std_logic; switch : in std_logic; x : in complex_data_vector; w : in complex_coef_vector; y : out complex_data_vector ); end full_butterfly; обратите внимание, что y, являясь выходным сигналом, тоже может быть complex_data_vector. К сожалению, в record не возможно параметризовать размерность членов (как можно параметризовать размерность самого array) - ее приходится задавать жестко или с помощью констант. Поэтому, что касается внутренних сигналов в бабочке, то ввиду необходимости сделать их на 2 разряда больше не остается ничего другого, как прямо внутри бабочки задать "служебный" тип complex_data_p2_vector: architecture beh_butter of butterfly_complex is type complex_p2 is record re : std_logic_vector(complex.re'high + 2 downto 0); im : std_logic_vector(complex.im'high + 2 downto 0); end record complex_p2; type complex_data_p2_vector is array (complex_data_vector'range) of complex2; Выносить его в общий package нет никакого смысла т.к. нигде кроме бабочки он не будет востребован. В результате вместо замысловатого x.x0.x_re будет x(0).re, что по-моему, весьма читаемо и удобно. Про память. Т.к. память у нас не тривиальная, то нарисуйте, пожалуйста, блок-схему ее реализации, как Вы ее себе представляете. Могу сразу сказать, что т.к. мы должны вычитывать/сохранять по 4 точки за такт, то без четырех блоков памяти не обойтись, но и 4 блока это далеко не все. Чтобы понять что там еще нужно посмотрите внимательно схему вычисления БПФ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 19 апреля, 2009 Опубликовано 19 апреля, 2009 · Жалоба Ну, если предположить, что каждая память состоит из 4 блоков памятей, то нам нужны 4 самих этих блока + схема, которая будет преобразовывать адреса для каждого блока памяти: If (addr_in_0 >= 0) and (addr_in_0 <= 511) then addr_out_0 <= addr_in_0; elsif (addr_in_0 >= 512) and (addr_in_0 <= 1023) then addr_out_0 <= addr_in_0 - 512; elsif (addr_in_0 >= 1024) and (addr_in_0 <= 1535) then addr_out_0 <= addr_in_0 - 1024; else addr_out_0 <= addr_in_0 - 1536; end if Вот что-то типа этого я думаю и так для каждого сигнала: addr_in_1, addr_in_2, addr_in_3. Т.е. получатся схемы сравнения (компараторы) и мультиплексоры... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться