Jump to content

    
Sign in to follow this  
ZED

Реализация БПФ на ПЛИС

Recommended Posts

Увы, в сумме стало хуже. Поправляя ошибки Вы поравили и там, где было правильно. В приложении схема с помеченными участками где неправильно и где было правильно пока не поправили.

 

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

 

Как минимум, Вы должны были заметить, что записанная на предыдущем этапе точка на следующем должна быть прочитана из того же самого места. Т.е. если на 3-ем этапе Вы 32 точку записали в банк №1 по адресу 0, то на 4-ом этапе, когда она Вам понадобится Вы должны ее прочитать строго из того же места, а Вы ее читаете из банка №1 по адресу 32. Разница между записью на предыдущем этапе и чтением на текущем заключается лишь в том, какие именно точки и в какой момент времени Вы пишете/читаете, но адрес конкретной точки при чтении такой же как и при записи. Это должно быть очевидно.

 

Должно всегда соблюдаться следующее:

1) все 512 данных в каждом банке памяти должны быть прочитаны и все 2048 результатов записаны во все банки памяти на свои уникальные места.

2) из 1 следует, что комбинация №банка и адрес на каждом этапе может встречаться только один раз (разумеется, один раз при чтении и один раз при записи).

 

Еще должно помочь то, что я не даром разделил бабочки на блоки.

 

Дерзайте.

FFT_2048_a09_05_08.rar

Share this post


Link to post
Share on other sites

Замечательно! Так бы сразу!

 

Проблемы 6-го этапа давайте пока отложим и по горячим следам займемся реализацией управления для 1 - 5 этапов. Кодом просьба пока не увлекаться. Чтобы я сразу смог увидеть направление мысли и поправить, если пойдете не туда и чтобы Вы не тратили зря время, напишите, буквально в двух словах, как или с помощью чего Вы собираетесь реализовывать выявленную закономерность адресов для банков памяти и номеров банков для миксера.

Share this post


Link to post
Share on other sites

Про счетчики с переменным модулем счета все понятно - это для формирования ядресов памяти и стробов для управления миксерами, "поворачивающими" банки памяти . А каким образом и с помошью чего Вы собираетесь формировать начальные значения для счетчиков и сам модуль счета?

 

Про назначение мультиплексоров не совсем понятно. Если для реализации миксеров для "поворота" банков, то замечу, что код такого миксера удобно описать с помощью одного case и в качестве управления достаточно 2-х "проводов". Если для чего-то другого, то расскажите подробнее - мне кажется, что для другого они не нужны.

 

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

 

Напишите, пожалуйста, код миксера на входе в бабочку и миксера на выходе умножителей с использованием одного case и 2-х бит управления. Модуль пусть будет чисто комбинаторный.

Share this post


Link to post
Share on other sites
Про назначение мультиплексоров не совсем понятно. Если для реализации миксеров для "поворота" банков, то замечу, что код такого миксера удобно описать с помощью одного case и в качестве управления достаточно 2-х "проводов". Если для чего-то другого, то расскажите подробнее - мне кажется, что для другого они не нужны.

Ну так case и сгегнерит мультиплексоры.

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

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

Про счетчики с переменным модулем счета все понятно - это для формирования ядресов памяти и стробов для управления миксерами, "поворачивающими" банки памяти . А каким образом и с помошью чего Вы собираетесь формировать начальные значения для счетчиков и сам модуль счета?

Не знаю, то или не то вы от меня ждали, но прилагаю код (mixer).

А каким образом и с помошью чего Вы собираетесь формировать начальные значения для счетчиков и сам модуль счета?

Попробовал написать код, несколько запутался, сейчас голова не варит уже, то, что получилось также прилагаю(gen_addr).

 

http://webfile.ru/3617925

Share this post


Link to post
Share on other sites
Ну так case и сгегнерит мультиплексоры.

 

Я имел ввиду, что не нужно писать код для четырех отдельных мультиплексоров, а можно все в одном case объединить. Кстати сказать, case не во всех случаях ведет к мультиплексорам.

 

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

 

С gen_addr, наоборот, все плохо. Даже прокомментировать сложно :).

 

Во-первых, т.к. работает он абсолютно неправильно, то неясно для чего он предназначен. Для генерации адресов для чтения данных или для записи?

 

Во-вторых, что при чтении, что при записи, инкремент адреса всегда 1. Поэтому выражение addr_in_0_sig <= addr_in_0_sig + 1 + dec_block + 6*dec_bank; в корне не верно хотябы потому, что инкремент в нем = 1 + dec_block + 6*dec_bank.

 

В-третьих, написав

 

if (count_point(to_integer(i)) = '1') then

count_block <= count_block + dec_block;

count_mix <= count_mix + 1;

end if;

 

Вы, очевидно, хотели, чтобы через каждые 2^(i+1) тактов у Вас происходил инкремент счетчика блоков и менялось управление миксером. Но Вы явно упустили из виду одно свойство count_point(i) – это не единичный импульс происходящий 1 раз в 2^(i+1). Этот сигнал представляет собой меандр - 2^(i) тактов = '0' и потом 2^(i) тактов = '1' потом все повторяется. Таким образом count_block и count_mix стоят намертво 2^(i) тактов, а затем на протяжении 2^(i) тактов на каждом фронте клока инкрементируются, потом опять стоят, потом опять молотят.

 

Придется сначала объяснить Вам как сделать управляющую логику. Жаль… Я надеялся, что поняв логику формирования адресов и управления миксерами Вам не составит труда описать это на VHDL.

Share this post


Link to post
Share on other sites
Вот новый вариант, так сказать вторая попытка, более продуманная генерации адресов на чтение:

http://webfile.ru/3634105

 

Что же, так значительно лучше! Но... есть 2 ошибки и 1 недостаток.

 

Начнем с недостатка. Плохо, когда в схеме управления нет сигнала, приводящего ее в исходное состояние из любого положения.

 

Если предполагается, что логика управления будет сбрасываться только вместе со всей схемой, то на нее заводится глобальный сигнал сброс, а синхронный или асинхронный решается в зависимости от ситуации. Если регистры ПЛИС имеют только отдельную "ножку" асинхронного сброса, то в большинстве случаев целесообразно использовать асинхронный сброс, не забыв сам сигнал сброса подсоединить к глобаьлному "проводу". В случае выбора асинхронного сброса необходимо обеспечить задержку между окончанием сброса и первым фронтом(спадом) клока.

 

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

 

В нашем случае управление сбрасываться должно независимо от остальной части схемы. Соответственно сброс (в нашем случае правильнее сказать инициализация) д.б. синхронным.

 

Теперь про ошибки.

 

При чтении диапазон адресов меняется один раз на 4 блока бабочек и записан 4-мя строчками, но если Вы внимательно посмотрите на схему БПФ, то должны будете заметить, что против одной и той же строчки в разных блокак разный номер банка памяти. Т.е. при чтении, адреса, как и данные, нужно "вращать" относительно банков. Возьмем для примера 3-ий этап. У Вас addr_rd_0 четыре раза подряд считает 0 ... 31. Посмотрите на схему в блоке №0 addr_rd_0 действительно д.б. 0...31, но в блоке бабочек №1 из 0-го банка нужно вычитать данные по адресам 96...127, в блоке бабочек №2 диапазон адресов для 0-го банка уже 64...95. Поскольку миксеры предусматривают "вращение" только данных, то "вращением" адресов должна заняться логика управления. В принципе, ничто не мешает дополнить миксер, но в учебных целях я объясню как это можно сделать красиво прямо в логике управления без лишних затрат.

 

Следующая ошибка заключается в том, что Вы не учли, что ваша реализация схемы управления не только синхронная, но и "двухступенчатая". Первая "ступень" содержит формирование инкрементов и базовый счетчик адресов, а вторая на основе инкрементов и базовых значений вычисляет адреса для банков и управление для миксера. Получается, что после смены этапа первый такт уйдет на обновление инкрементов и только на втором такте у них будут значения, соответствуюшие текущему этапу. Получается, что вычисление адресов для банков и управления для миксера отстает на один такт от смены этапа и в первом такте нового этапа Вы вычисляете адреса с инкрементами от предыдущего. Вот фрагмент вашей симуляции.

 

post-7537-1243285301_thumb.jpg

 

На последнем такте 2-го этапа (значение etap = 1) у Вас addr_rd_0-3 = 127, 255, 383, 511 (кстати, должно было бы быть 255, 383, 511, 127). На первом такте 3-го этапа у Вас должно было бы быть 0, 32, 64, 96, но т.к. инкременты и базовый адрес отстают на такт от смены этапа Вы имеете адреса с базовым адресом и инкрементами предыдущего этапа 0, 128, 256, 384.

 

Что касается сигнала управления миксером, то его значение правильно только благодаря его особенностям.

 

Над ошибками подумайте, осознайте, но код исправлять не спешите - я Вам объясню все управление целиком, тогда и код напишите начисто. Т.к. времени у меня сейчас очень мало и за 1 день управление мне не описать, поломайте голову над проблемой записи данных на 5-м этапе и чтения/записи на 6-м. Я где-то выше уже задавал этот вопрос.

Share this post


Link to post
Share on other sites
По этой же причине (неправильная разрядность), видимо, Вы для округления прибавляете 4, вместо 2 - это приведет к неправильным вычислениям.

(-32 + 2)/4 = -7.5, отбрасываем младшие разряды получаем -7, а должны получить -8. При сумме больше нуля прибавление двойки перед делением на 4 дает нужный результат, а вот когда сумма меньше нуля, то появляется ошибка. Я что-то упустил?

Share this post


Link to post
Share on other sites
(-32 + 2)/4 = -7.5, отбрасываем младшие разряды получаем -7, а должны получить -8. При сумме больше нуля прибавление двойки перед делением на 4 дает нужный результат, а вот когда сумма меньше нуля, то появляется ошибка. Я что-то упустил?

 

Да. Отбрасывать надо двоичные разряды у двоичного числа. Дело в том, что если у числа в дополнительном коде отбросить дробные разряды то, оно округлится к меньшему из соседних целых чисел (независимо от того, положительное оно или отрицательное). Так что если Вы число -7.5 переведете в двоичный вид (1000.1b) и отбросите дробные биты (.1b), то получите -8 (1000b).

 

Смотрите: -32 (100000b в двоичном дополнительном коде), прибавляем 2 (10b), получаем -30 (100010b) теперь делим на 4 - т.е отбрасываем 2 младших двоичных разряда (или сдвигаем на 2 разряда вправо - как Вам больше нравится) и получаетм 1000, что для числа в дополнительном коде с разрядностью 4 означает -8, если хотим сохранить разрядность исходного числа, то расширяем знак и получаем 111000, что для числа с разрядностью 6 все равно -8.

 

:)

Share this post


Link to post
Share on other sites
Да. Отбрасывать надо двоичные разряды у двоичного числа. Дело в том, что если у числа в дополнительном коде отбросить дробные разряды то, оно округлится к меньшему из соседних целых чисел (независимо от того, положительное оно или отрицательное). Так что если Вы число -7.5 переведете в двоичный вид (1000.1b) и отбросите дробные биты (.1b), то получите -8 (1000b).

 

Смотрите: -32 (100000b в двоичном дополнительном коде), прибавляем 2 (10b), получаем -30 (100010b) теперь делим на 4 - т.е отбрасываем 2 младших двоичных разряда (или сдвигаем на 2 разряда вправо - как Вам больше нравится) и получаетм 1000, что для числа в дополнительном коде с разрядностью 4 означает -8, если хотим сохранить разрядность исходного числа, то расширяем знак и получаем 111000, что для числа с разрядностью 6 все равно -8.

 

:)

я не совсем удачно пример выбрал и, в попыхах, посчитал неправильно :unsure:

вот, набросал небольшую програмку, и получил вот такой результат:

a = -31 (11100001b) a+2 = -29 (11100011b) (a+2)>>2 11111000 = -8; a/4= -7.75 - правильно

a = -30 (11100010b) a+2 = -28 (11100100b) (a+2)>>2 11111001 = -7; a/4= -7.50 - неправильно?

a = -29 (11100011b) a+2 = -27 (11100101b) (a+2)>>2 11111001 = -7; a/4= -7.25 - правильно

a = -28 (11100100b) a+2 = -26 (11100110b) (a+2)>>2 11111001 = -7; a/4= -7.00 - правильно

a = -27 (11100101b) a+2 = -25 (11100111b) (a+2)>>2 11111001 = -7; a/4= -6.75 - правильно

a = -26 (11100110b) a+2 = -24 (11101000b) (a+2)>>2 11111010 = -6; a/4= -6.50 - неправильно?

a = -25 (11100111b) a+2 = -23 (11101001b) (a+2)>>2 11111010 = -6; a/4 = -6.25 - правильно

a = -24 (11101000b) a+2 = -22 (11101010b) (a+2)>>2 11111010 = -6; a/4 = -6.00 - правильно

...

a = 24 (00011000b) a+2 = 26 (00011010b) (a+2)>>2 00000110 = 6; a/4 = 6.00 - правильно

a = 25 (00011001b) a+2 = 27 (00011011b) (a+2)>>2 00000110 = 6; a/4 = 6.25 - правильно

a = 26 (00011010b) a+2 = 28 (00011100b) (a+2)>>2 00000111 = 7; a/4 = 6.50 - правильно

a = 27 (00011011b) a+2 = 29 (00011101b) (a+2)>>2 00000111 = 7; a/4 = 6.75 - правильно

a = 28 (00011100b) a+2 = 30 (00011110b) (a+2)>>2 00000111 = 7; a/4 = 7.00 - правильно

a = 29 (00011101b) a+2 = 31 (00011111b) (a+2)>>2 00000111 = 7; a/4 = 7.25 - правильно

a = 30 (00011110b) a+2 = 32 (00100000b) (a+2)>>2 00001000 = 8; a/4 = 7.50 - правильно

a = 31 (00011111b) a+2 = 33 (00100001b) (a+2)>>2 00001000 = 8; a/4 = 7.75 - правильно

 

Получается ошибки при округлении отрицательных чисел все-таки будут?

Share this post


Link to post
Share on other sites
я не совсем удачно пример выбрал и, в попыхах, посчитал неправильно :unsure:

вот, набросал небольшую програмку, и получил вот такой результат:

...

a = -30 (11100010b) a+2 = -28 (11100100b) (a+2)>>2 11111001 = -7; a/4= -7.50 - неправильно?

...

a = -26 (11100110b) a+2 = -24 (11101000b) (a+2)>>2 11111010 = -6; a/4= -6.50 - неправильно?

 

Получается ошибки при округлении отрицательных чисел все-таки будут?

 

Нет, ошибок в округлении нет - Вы ошиблись, решив, что -7.5 должно округляться к -7. Нарисуем числовую ось:

 

post-7537-1244101590_thumb.jpg

 

Когда значение попадает строго посередине между двух целых чисел, то его округляют к большему. Соответственно, для +7.5 большим является 8, а вот для -7.5 большим является -7. Так что никакой ошибки округления тут нет.

 

 

Что-то от Вас не слышно никаких соображений про чтение/запись на последнем этапе...

Share this post


Link to post
Share on other sites
Нет, ошибок в округлении нет - Вы ошиблись, решив, что -7.5 должно округляться к -7. Нарисуем числовую ось:

 

post-7537-1244101590_thumb.jpg

 

Когда значение попадает строго посередине между двух целых чисел, то его округляют к большему. Соответственно, для +7.5 большим является 8, а вот для -7.5 большим является -7. Так что никакой ошибки округления тут нет.

 

А разве числовая ось не должна быть зеркальной относительно нуля? Если мы будем отрицательные числа с дробной частью равной 0.5 округлять до большего по абсолютной величине, то мы получем смещение.

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