Pull to refresh

Comments 17

2 порядок больше подходит для звена БИХ фильтра. Сколько варнингов у такого описания? Еще, что бросилось в глаза: если стоит условный оператор, то условия перечисляются через логическое и/или (&& ||). А вообще классно, было интересно читать!
Спасибо. Вылитает 16 варнингов, причем 2 относятся к тому что не используется объявленная переменная outsum, 4 к тому, что не дал внутримодульные названия мегафункциям. Это самые критичные вроде, остальные — мелочь какая-то. Насчет условного оператора, вы правы конечно, но я во всех проектах использую подобную запись, и, кажется, никаких проблем с этим не возникало. Может быть стоит начать писать правильно, мало ли где выплавит. А что вы имели ввиду по поводу звена БИХ фильтра? Нашел фразу:«БИХ-фильтры обычно реализуются с помощью звеньев второго порядка, которые называются биквадратными фильтрами». Но вроде бы эти биквадратные формы используются для упрощений расчетов фильтров больших порядков, определения нулей и полюсов фильтров. Влияет ли это на конечную реализацию устройства, например в Verilog? Всегда казалось что для повышения порядка, достаточно добавить дополнительные слагаемые в конечное разностное уравнение.
А посмотрите в проекте этот сумматор: COUNT[5:0] + 1. Просто интересно, скольки он разрядный. Просто «1» по дефолту int и преображается в 32 разряда, поэтому сумматор может получится страшным, а может и нет, если оптимизацию пройдет.
Лично один раз спотыкался об & и && по части интерфейсов, теперь стараюсь следить.
И да, большие БИХ фильтры можно строить звеньями, что облегчает анализ этих фильтров. Это эквивалентно последовательному включению фильтров меньшего порядка, что реализацию, в принципе, не меняет.
Хм… Да, вы правы, по этому счетчику выдавал одно предупреждение. Но, по-видимому, компилятор приводит его к 6-и разрядному виду сам. Внес изменения в код на всякий случай. Спасибо.
Спасибо, учту…
Вы не принимайте близко к сердцу, я с благими намерениями :)
Я нормально отношусь к конструктивной критике и ничего обидного здесь не вижу. До вашего комментария я даже не задумывался об этом вопросе и как-то неудобно даже стало перед читателями за такой просчет, поэтому мое «спасибо» действительно искренне.
хм…
а это у Вас вообще-то работает? пробовали ли в железе или симулировали?
Что-то меня смущает несколько моментов.
1) похоже все операции делаются над положительными числами, это так? Не вижу signed reg или $signed… Если все числа положительны, то на выходе будет все возрастающее число — посмотрите на свою структуру: сложение многих положительных компонентов дает большее число и с каждой новой входящей выборкой число на выходе будет увеличиваться…
2) вы как-то смело используете для всех переменных 32х битные регистры. При этом вообще-то при перемножении двух 32х битных чисел получится 64х битное число, ведь так? Почему Вы пренебрегаете этим?
3) и как оно синтезируется для ПЛИС? для какой конкретно ПЛИС? операция умножения довольно расточительная функция и занимает много места, если только не используются встроенные умножители
3)
Да, все хорошо работает в железе.
1) Дело в том что при вычислениях используется формат числа с плавающей запятой. Я указал в пояснениях к модулю, что функция int18_to_float32 преобразует числа к этому виду.Вот ознакомьтесь пожалуйста Число одинарной точности.Старший бит этой 32-х битной структуры как раз и отвечает за знак числа. И числа конечно же не все положительные. Переменные С0… С2, заведомо умножены на -1, т.е. они отрицательные.
2) Все правильно, если бы это были целые числа, то так бы оно и было. Но я использую числа с плавающей запятой, поэтому результат остается 32-х разрядный.
3)Конкретно в этом проекте я использую Cyclone III EP3C25Q240C8.Там есть встроенные умножители. У меня там 4 таких фильтра и еще процессор Nios II, места на все хватает.
Вот пара моментов, которые прям бросились в глаза:
1) Входы-выходы объявляются в заголовке модуля обычно. Вы объявляете регистры и цепи в процессе их появления в тексте. Мелочь, конечно, но для меня странно выглядит.
2) Для каждого блока always используете один оператор. Почему не в операторных скобках в одном блоке always?
3) У вас все повторяющиеся условия ( которые отрабатывают счетчик) можно свести в один case ( автомат получится). Вы это делаете, чтоб синтезировалась обработка условий через enable в триггерах вместо мультиплексора, которым реализуется автомат? Насколько это эффективнее?
4) Я бы параметризовал многие вещи. Для гибкости. Вдруг пригодится.
5) На какой частоте все работает? Имеется в виду оценка Тime quest'а.

Извините, если несуразные вопросы. Стаж у самого чуть больше года. Может я что-то важное упускаю?
Eщё нескромный вопрос. Не пробовали генерировать фильтр из матлаба?
1) Мне так удобнее ориентироваться в программе. Когда простыня на несколько экранов я ищу нужное мне место по объявлениям регистров.
2) Ну тут много причин:
a)Ключевое слово always указывает на процесс. Процесс — это такой кусок кода, внутри которого все операции выполняются ПОСЛЕДОВАТЕЛЬНО. Зачем мне ограничиваться, выстраивая последовательные расчеты, если я могу выполнять их ПАРАЛЛЕЛЬНО.
b)Эти процессы зачастую тактируются по-разному. Если в этой маленькой программе этого нет (везде одна частота), то есть проекты, в которых условия срабатывания в разных процессах разные. Поэтому я привык разграничивать различные по смыслу процессы.
3)Это такой же мультиплексор, не важно как его задавать, case-ом или if-ом. Реализация не вентильно-тригерном уровне не меняется. В case вроде бы нельзя задать выбор по диапазону, а только по конкретному значению, как в if, а раз смысл одинаковый, а функциональности больше у if, я пользуюсь обычно if. Хотя иногда, когда много условий, могу использовать и case.
4)Да, можно было бы. А то какой-то говнокод получается:)
5)По данным Тime quest'а максимальное значение частоты mhz_clk = 63.4MHz, но эта частота определяется частотой дискритизации АЦП. В моем проекте это 600кГц, поэтому mhz_clk я выбрал 30МГц.
С матлабом пока дела не имел, но начинаю к нему приглядываться. Скоро опять будет проект, где нужно будет синтезировать фильтр по заданной АЧХ, причем весьма сложной. Без матлаба видимо не обойтись…
1) Вы работаете один? Я работаю в команде и стилистика, хоть и на словах, но имеется и обсуждается.
2) а) Например блок
Always @(posedge clk)
begin
a=x+y;
b=q+g;
c=n+m;
end
Все присвоения в таком случае сработают параллельно.
5) Маловата частота конечно для такой плис, но если запас в 2 раза, то проблем нет.

Matlab, кстати, очень рекомендую. Весь ЦОС всегда полностью моделирую, но вот генерацией HDL кода пока не занялся.
1) Нет, не один, но у нас все также пишут:)
2)Нет, последовательно. Это можно сделать параллельно, если вместо begin...end использовать fork...join. Либо можно еще ускорить процесс присвоения регистра. Дело в том, что операция установки регистра занимает определенное время. Можно использовать неблокирующее присваивание(a<=x+y;b<=q+g), при котором перескок на следующую операцию идет сразу после того, как регистр начнет устанавливаться.
Понял, спасибо.
Как-то не обращал на это внимания, прям жил во лжи.
Я делал фильтры из fdatool в matlab, получааетсся очень громоздко и нечитабельно. Именно по этой причине я и написал этот пост, где брал из матлаба коэффициента фильтра, а все умножения с накоплением делал сам. Когда доделал фильтр сравнил результаты: дизайн из матлаба не влез в Cyclone2 не помню какую, мой дизайн занял 1% кристалла, аккуратно разложив сдвиговый регистр и коэффициенты в ram, которой было более чем достаточно
Sign up to leave a comment.

Articles