Jump to content

    

Krys

Свой
  • Content Count

    2000
  • Joined

  • Last visited

Everything posted by Krys


  1. Положение точки в числах с фиксированной точкой - понятие чисто условное, которое существует только в головах разработчиков, чтобы понимать, какое реальное число представлено в коде из скажем 8 битов. Например, дана переменная 8 битов со значением битов 48. Сказано, что эта переменная имеет формат s3.5. Какое же реальное число закодировано в этих 8 битах? Закодировано 1,5. А если это s4.4 - закодировано 3. Внутри вычислителя положение точки никак не фигурирует, для него это всегда полностью целые числа, без дробной части. Но разработчик, зная, что входной 8-битный знаковый поток он представил в уме, скажем, как нормализованный к 1 (т.е. s1.7 - это реальные числа сдвинутые влево на 7 битов), понимает, что результат ему надо задвинуть обратно на те же 7 битов, чтобы получить правильный результат в его реальных числах, которые он представлял в уме. Т.е. у нас есть инструмент, который оперирует только целыми числами. И у нас есть реальные числа, которые никак не укладываются в диапазон этого инструмента. Нам надо сначала в уме растянуть наши числа на полную шкалу инструмента, а затем результат (он опять в целых числах) обратно сжать на столько же битов. Для 8-битных чисел, например, инструмент понимает числа до 127, а реальные числа у нас не больше 1. Поэтому все наши реальные числа надо умножить на 127, чтобы влезть в полную шкалу инструмента. Возвращаясь к ответу на исходный вопрос: На входе предполагается (в уме) формат 1.15, а на выходе 2.14. Как это понять? Отвлечённый пример: пусть на входе формат 1.15 и на выходе формат 1.15. Это означает, что положение точки в одном и том же месте. Если на входе мы свои числа растянули на полную шкалу, сдвинув влево на 15 разрядов, то на выходе нужно сдвинуть вправо. А если мы на входе ничего не сдвигали (это всё равно мысленная операция в конце концов), то и на выходе ничего сдвигать не надо. Теперь вернёмся к конкретно нашим цифрам: на входе 1.15, на выходе 2.14. Даже если мы вход мысленно не сдвигали, то выход будет всё равно сдвинут функцией на 1 бит, при том вправо. Чтобы получить число в том же масштабе, что и входное, потребуется сдвинут результат на 1 бит влево. Вот Вам и ответ. Т.е. вход сдвигать не надо вообще, а выход - на 1 бит влево. Понятно, Вы методом научного тыка решили, что сдвигать всё же надо ))) Я придерживаюсь мнения, что сдвигать вообще не надо никуда, функция БПФ и так всё сделала за Вас, оно и логично по-идее с точки зрения разработки юзер-френдли интерфейса, чтобы пользователь не парил голову, сколько стадий бабочки прошло, ему нужен только готовый результат. Однако вот тут мне непонятно: Откуда у Вас после сдвига влево спектр приобретает "нижние маленькие тычки", если без сдвига их нет? До сдвига эта информация должна быть уже заложена в несдвинутый сигнал. А если она заложена, то как она обрезается отсутствием каких-либо действий (случай без сдвига)? Не должно такого быть. Подумайте, может, где-то ошибка. Другое дело. Вот с этого сразу и надо было начинать. К стати, по картинке спектра: левая и правая палки имеют разный уровень. Этого быть не должно. Уж не знаю, откуда взялось. Может, функция кривая, может, мнимая часть где-то пролезла (хотя почти не реально). Может, другие участники форума подскажут, откуда берётся этот эффект. Если не найдётся причина - предлагаю входные числа затолкать в матлаб один к одному, и над ними проделать fft(). Там должно быть одинаково.
  2. К счастью, в доп.коде операции делаются идентично, поэтому указание знака необязательно. Лично я ставлю reg signed или wire signed только для того, чтобы в симуляторе наблюдать сразу знаковые значения.
  3. Мы говорим про функцию, которая рассчитывает амплитуду частотных составляющих по их мнимой и действительной частям? Ну я Вам про форматы пытался выше объяснить. Если что - спрашивайте конкретные вопросы, поясню более детально. В рамках конкретной функции такие форматы можно объяснить: если каждую квадратуру выхода БПФ считать пронормированным к 1, то амплитуда в корень из 2 будет больше 1, поэтому при сохранении входного формата возникнет переполнение, следовательно положение точки нужно сдвинуть. Но на самом деле этого не требуется конкретно для БПФ, т.к. заранее известно, что комплексные числа - это вращающиеся вектора, которые не могут выходить за единичную окружность, тогда и модуль не может превышать 1. А надо-то вправо. БПФ усилил на гейн. Надо вернуть обратно. А частота дискретизации тогда какая? По этим картинкам видно, что частота сигнала у Вас не кратна частоте дискретизации. Подайте кратную частоту, так гораздо удобнее сначала разбираться, почему БПФ не дал ожидаемую амплитуду.
  4. Спасибо, теперь всё гораздо понятнее. А входной сигнал выложите, пожалуйста. И Вы пишете, что подали 500мВ, а какое напряжение полной шкалы? АЦП двухполярный? Т.е. 1 бит под знак, а значения в доп.коде на выходе? И вообще, лучше давайте продолжать работать не с живыми данными АЦП. Сначала надо отладить всё на идеальной модели входного сигнала, где всё точно. С какой разрядностью на входе и выходе работает функция arm_cmplx_mag_q15()? И ещё Вы пишете: Если не будет выхода за предела разрядной сетки, сдвиг можно сделать хоть до, хоть после функции. Но Вы ещё не назвали разрядность, поэтому как будет известно - будем думать. И сдвиг вправо, а не влево. Это ошибка в Ваших расчётах или просто опечатка? Если ошибка, то прошу все вышеприведённые цифры повторить заново после исправления.
  5. Я не программист, поэтому в Ваши исходники копаться не полезу, спрашиваю так: вход с АЦП у Вас как переменная описан с плавающей точкой или с фиксированной? Каким конкретно типом, какой разрядности? И что значит "сместил на 10 разрядов", какой операцией? Сместил вход или выход БПФ? Покажите, пожалуйста, полный получившийся спектр. Вы приводили выше картинку, но она похоже неполная, там нет отрицательной частоты. И вот Вы пишете, что "значения даже не близкие". Напишите прямо: подал столько-то, поэтому по расчётам (как рассчитывал?) ожидаю получить столько-то, но по рисунку спектра видно столько-то. А Вы на вход подавали просто 12-битные отсчёты АЦП? Тогда если результат поделить на 1024, то должна получиться половинная амплитуда входной синусоиды в попугаях входного 12-битного сигнала.
  6. Я уже сам запутался, кому и что надо )) Вы напишите ещё раз, что хотите рассчитать и что не срастается? А вообще, Вам бы книжку почитать по БПФ. Мне нравится пример на стр. 151 в книжке Лайонс_-_ЦОС_2е_издание_русский_перевод_2006 (можно скачать в местных закромах). Там хотя бы понятно, как образуются амплитуды и отсчёты, откуда берутся такие числа. Хорошо всё разжёвано. У Вас должно получиться также, как в примере. Да и вообще в этой книжке хорошо даётся материал касаемо данного вопроса.
  7. Мне "как отдельный компонент" не хочется - нарушается читабельность. У меня этих DSP-шек в одном файле описывается несколько, и умещается всё это в один экран кода, читабельность на высоте ))) Если уж делается "отдельный компонент", то можно и макроблок вставить, а там уже резвиться и использовать полный функционал, который, например, я не смог реализовать на RTL в первом сообщении этой темы.
  8. А какую частоту синусоиды взяли? Можете файл прикрепить с отсчётами? Фактически интересует, сколько сэмплов период повторения. Но файл лучше ) А в чём Ваша ошибка была? Вы вообще неправильно данные на вход подали? Да, для вещественного синуса комплексная часть равна нулю. Почитайте на вики про бабочку в операциях БПФ, тогда все вопросы исчезнут. В 2х словах: формат 1.15 означает 16-битное представление, 1 бит под целую часть (он же знак, поэтому под целую часть нет ничего, и число должно быть меньше 1), а 15 битов - под дробную часть. Грубо говоря, в таком формате все числа пронормированы к 1. Бабочка выполняет умножение входного числа (отсчёта синуса) на поворачивающий множитель. Поворачивающий множитель по определению не превышает 1, поэтому его формат тоже выбран 1.15 (хотя, это чуть-чуть некорректно, и в своей реализации я выбрал честный формат). После умножения бабочка делает сложение. Отсюда разрядность должна увеличиться на 1 бит. Разрядная сетка у нас фиксирована 16 битами, поэтому приходится отбросить младший бит дробной части, чтобы не словить переполнение. Отсюда получается результирующий формат на выходе бабочки 2.14. Бабочка выполняется над массивом данных 1024 сэмпла 10 раз, поэтому в результате точка съезжает аж на 10 разрядов вправо, про это говорят "гейн БПФ". Чтобы получить правильную амплитуду, нужно результат поделить на вышеупомянутый гейн. Можно и не делить физически, а "держать в уме" наличие усиленного результата. Так что делить или не делить - от этого качественно картинка меняться не должна, кривая спектра всё равно будет выглядеть одинаково внешне, и палки частот всё равно должны быть в нужных местах. Вы сначала добейтесь правильного положения палок, а затем уже думайте о правильном измерении абсолютного уровня амплитуды палки.
  9. А математически вычислить никак? )) По крайней мере не для живого сигнала и для кратных частот. Я думаю, с этого надо начать. А для живого сигнала, конечно, уже, как написано тут:
  10. Ну я что и предлагал - тесты на заранее подготовленных данных, а не на "живых" ))
  11. обучается наверное человек. Он же в конце написал, что потом и умножитель с аккумулятором затолкал туда ))
  12. Ну об этом я уже хвастался тут Я не о том. А вот о чём. Если открыть доку на DSP48, то там будет параметр, задающий синхронный или асинхронный сброс в DSP48. Чисто теоретически, синтезатор имел возможность понять по Вашему коду, что этот параметр надо при синтезе выставить в асинхронный режим. Другое дело, что он этого асинхронного сброса почему-то не распознал... Это уже недостатки синтезатора. Возможность у него была.
  13. там вроде был где-то параметр указания типа сброса: синхронный или нет. Хотя могу путать. Ну и конечно ничто не мешает всё равно на этом месте синтезатору спотыкаться. Просто не умеет корректно обрабатывать, возможно. Так что Вы может быть очень даже правы ))
  14. Одной из причин может быть то, что подаваемая частота 50Гц не строго синхронна частоте выборок АЦП, поэтому возникает размытие спектра. Попробуйте тест вашего БПФ не на реальных данных с АЦП, а на заранее подготовленном в Matlab буфере данных, где частота сигнала строго синхронна получится. Можно даже в симуляторе прогнать наверное.
  15. навскидку: положительное значение fractional bitwidth говорит о том, что десятичный разделитель (точка, отделяющая целую и дробную часть) находится левее на столько-то битов по сравнению с положением этой точки ровно после самого младшего бита разрядной сетки данной переменной. А отрицательное значение - соответственно, что десятичный разделитель находится правее. Это однозначно означает, что разрядная сетка вашей переменной содержит только целую часть, и то не всю, а начиная с какого-то разряда (указанного в отрицательном значении fractional). Вот пример: разряды вообще : 9 8 7 6 5 4 3 2 1 0.-1 -2 -3 разрядная сетка : 4 3 2 1 0 конкретной переменной В данном примере у конкретной переменной bitwidth = 5, а fractional bitwidth = -4. Это говорит о том, что нулевой разряд вашей переменной он на самом деле не нулевой, а 4.
  16. решили проблему? В чём была ошибка?
  17. Выигрыш ещё и в том, что на последующих этапах децимации тактовая частота поступления отсчётов снижается, и фильтры могут работать в т.н. "полифазном" режиме, т.е. когда на одном и том же умножителе обсчитывается сразу несколько коэффициентов последовательно, а на умножитель подаётся повышенная тактовая частота.
  18. Короче завёл полностью тот же текст под функцию - проблема исчезла. Так что такой вот workarround этого бага. Если кому-то допустимо менять таск на функцию.
  19. а, ну тогда в любом брандмауэре отрубить ему вообще под ноль доступ к инету. Или есть проги (для андроида это называется adaway), которые все рекламные адреса добавляют в файл hosts, после чего эти адреса не грузятся ))
  20. А вообще в Вашей конструкции DSP48 хоть в каком-то виде вставляется, но без PREG? Или он вообще ни в каком виде не вставляется, а суммирование делается на рассыпухе? Возможно, его смущает "after td". А возможно, ena. Попробуйте для начала убрать оба. Возможно, тип сигнала data должен быть signed, а прибавляемая величина - ту же разрядность (т.е. надо единичку расширить), хотя последнее - вряд ли должно влиять.
  21. Спасибо за версию. Насколько я понял, всё, что не указано в шапке task, не является подставляемыми параметрами и берётся из переменных, объявленных вне task (как глобальные). Таким образом, rst в таск заходить должен, как и куча других сигналов, которые я в шапке таска не объявил (куча других сигналов у меня используется в "боевой версии", а когда я сюда выкладывал пример - упростил его до предела, чтобы выявить суть). То, что rst заходит в таск, косвенно подтверждает и то, что всё работает, как надо, если поменять условие в нижней ветви на определённое, скажем, 1'b0. Использую pure verilog.
  22. Здравствуйте. Хочу поделиться багой Aldec Active HDL: неверно симулирует условия с неопределёнными состояниями (x) в task. Ну или у меня лыжи не едут ))) Условия задачи: Код с таском: task ovfl_proc; output res; input inp; if(rst) begin res <= 1'b1; end else begin if(1'bx) begin res <= 1'b0; end else begin res <= inp; end end endtask always @(*) begin ovfl_proc(fifo_ovfl, fifo_ovfl_r); // output value, old value end и без таска: always @(*) begin if(rst) begin fifo_ovfl <= 1'b1; end else begin if(1'bx) begin fifo_ovfl <= 1'b0; end else begin fifo_ovfl <= fifo_ovfl_r; end end end В момент действия сигнала rst код с таском даёт неопределённое состояние: А код без таска даёт единицу, как и должно быть (или у меня лыжи не едут?). Как я понимаю, согласно коду, в момент действия rst работает верхняя ветвь условия, поэтому должно быть пофигу, какие условия (определённые или нет) находятся в нижней ветви. Если неопределённое состояние в условии заменить на любое определённое, то отрабатывает корректно в обоих случаях.