Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: попытка создания спектроанализатора
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
andreichk
Привет народ. Вот вымучил ФФТ на корке , получилось что-то похожее на спектр. Во всяком случае на изменение частоты реагирует переползанием пиков сигнала по экрану. Только вот никак не соображу, как сделать так, чтобы пики сигнала располагались только сверху, а не вращались как умалишённые вверх-вниз.
http://www.youtube.com/watch?v=Vy1yDr5oZU8...eature=youtu.be

прилагаю куски кода по частям.
1. корка ФФТ в ИЗЕ

Код
reg [8:0]xn_re;
always @ (posedge CLK_A)
xn_re <= signal;

FFT FFT_A (
  .clk(CLK_A),         // input clk
  .start(1),           // input start
  .unload(1),          // input unload
  .xn_re(xn_re[8:0]),  // input [8 : 0] xn_re min+max
  .xn_im(0),           // input [8 : 0] xn_im
  .fwd_inv(1),         // input fwd_inv
  .fwd_inv_we(1),      // input fwd_inv_we
  .rfd(rfd),           // output rfd
  .busy(busy),         // output busy
  .dv(dv),             // output dv
  .xk_re(xk_re),       // output [8 : 0] xk_re
  .xk_im(xk_im)        // output [8 : 0] xk_im
);


далее блок математики , в котором сигналы с ФФТ обрабатываются и выводятся далее на экран

Код
wire [8:0]out_math;
math math (// математика
          .clk(CLK_A),
             .dv(dv),
          .real_(xk_re),
          .imaginary(xk_im),
          .out_(out_math)
         );

и собственно сама математика

Код
module math (
input clk,
input dv,
input [7:0]real_,
input [7:0]imaginary,
output reg[9:0]out_
);
wire [15:0] real_re;
wire [15:0] imaginary_;
//модуль комплексного числа.    
multiplexor m_re (
  .clk(clk), // input clk
  .a(real_), // input [7 : 0] a
  .b(real_), // input [7 : 0] b
  .ce(dv),  
  .p(real_re) // output [15 : 0] p
);
multiplexor m_im (
  .clk(clk),     // input clk
  .a(imaginary), // input [7 : 0] a
  .b(imaginary), // input [7 : 0] b
  .ce(dv),  
  .p(imaginary_) // output [15 : 0] p
);
reg [16:0] summe;
always @ (posedge clk)
begin
summe <= real_re[15:0] + imaginary_[15:0];
end
wire [8:0]out_m;
sqrt sqrt (
  .clk(clk), // input clk
  .ce(dv),
  .x_in(summe), // input [15 : 0] x_in
  .x_out(out_m) // output [8 : 0] x_out
);
//------------------------ ищем max ----------------------------------
wire [8:0] max = (dv == 1'b1) ? 1'b1: (( max < out_m ) ?  out_m : 1'b1);    
//----------------------- нормировка по max
wire [8:0] max_2;  
divider d_max (
    .clk(clk),         // input clk
    .ce(dv),           // input ce
    .dividend(max),    // input [8 : 0] dividend
    .divisor(2),       // input [8 : 0] divisor
    .fractional(max_2) // output[8 : 0] fractional
    );
wire [8:0] res;      
divider d_res (
    .clk(clk),       // input clk
    .ce(dv),         // input ce
    .dividend(out_m),// input [8 : 0] dividend
    .divisor(max_2), // input [8 : 0] divisor
    .fractional(res) // output[8 : 0] fractional
    );

always @ (posedge clk)
begin
      out_ <= res[7:0] - 118;//двигаем по высоте. меньше - выше
end

endmodule

поскажите, что надо сделать, чтобы устранить это вращение.Спасибо заранее и всех с наступающим Новым годом ! santa2.gif
Xenia
Действительную и мнимую части надо не суммировать (для вывода графика), а получать из них "гипотенузу", т.е. корень квадратный из суммы их квадратов.

На первом этапе можно временно обойтись без корня, а только вычислить сумму квадратов реальной и мнимой частей. Это уже будет число сугубо положительное и дрыгаться вниз оно не будет. Ну, а корень из него нужен лишь для физического смысла амплитуды гармоники.
andreichk
а вы разве не заметили? вот извлечение кв.корня из суммы квадратов

Код
wire [8:0]out_m;
sqrt sqrt (
  .clk(clk), // input clk
  .ce(dv),
  .x_in(summe), // input [15 : 0] x_in
  .x_out(out_m) // output [8 : 0] x_out
);
Xenia
Цитата(andreichk @ Dec 30 2012, 02:15) *
а вы разве не заметили? вот извлечение кв.корня из суммы квадратов


А как вы сами объясняете отрицательные значения у себя на графике, если честно складываете квадраты?
andreichk
Простите, я по ходу вас неверно понял. Вы хотели сказать, что извлечение кв.корня из суммы квадратов вообще можно исключить и тогда значения будут только положительными? Я проверю это прямо сейчас и выложу фото того, что получилось.
Xenia
Цитата(andreichk @ Dec 30 2012, 02:44) *
Простите, я по ходу вас неверно понял. Вы хотели сказать, что извлечение кв.корня из суммы квадратов вообще можно исключить и тогда значения будут только положительными? Я проверю это прямо сейчас и выложу фото того, что получилось.


Именно! Однако и корень квадратный из положительного числа не должен приобретать отрицательный знак.

А то у вас сумма 17-разрядная:
reg [16:0] summe;
а корень берется только от 16 разрядов:
.x_in(summe), // input [15 : 0] x_in
Мне трудно предсказать, что от этого бывает. Вдруг функция sqrt() воспринимает бит 15, как знаковый и выдает от этого фигню?
Сдвинули бы вы summe на разряд вправо (или поделили на 2) перед тем, как извлекать корень. Хотя б для "очистки совести".
... в, впрочем, не поможет. Ведь если число воспринимается как отрицательное, то при сдвиге и делении знак сохранится.
andreichk
блин, как это я проглядел? теперь я на распутье или выкинуть извлечение корня или переделать корку корня на 17 разрядов... хорошо, что есть выбор...Спасибо за подсказку.ночь длинная, буду копать..
исключил извлечение кв.корня и вот что получилось:
осталось только развернуть и дело в шляпе. спасибо за подсказку. santa2.gif
Xenia
Цитата(andreichk @ Dec 30 2012, 02:56) *
блин, как это я проглядел? теперь я на распутье или выкинуть извлечение корня или переделать корку корня на 17 разрядов... хорошо, что есть выбор...Спасибо за подсказку.ночь длинная, буду копать..


Вы лучше переделайте так, чтобы корень извлекался из беззнакового числа, т.е. не считал старший бит за признак отрицательности.
Ведь оба квадрата у вас - числа положительные. Значит, у обоих разряд 15 пустой. Заполниться он может лишь при сложении. Но даже и в этом случае, разряд 16 не нужен, т.к. он с гарантией останется пустым.

Поэтому для суммы вам достаточно 16-разрядного числа, но только с той оговоркой, что оно беззнаковое. И корень должен это как-то понимать, всегда воспринимая аргумент беззнаковым. Общность от этого не теряется, т.е. из отрицательных чисел корень все равно извлекать нельзя.
andreichk
вымучил наконец smile3046.gif
RobFPGA
Приветствую!

Вы вобще то не сосвсем коректно вычисляете значения спектра. Поскольку если я правильно понял sqrt(|Re|+|I'm|) не является корректным значением

Для правильного вывода спектра желательно реализовывать 10*log10(Re*Re + I'm*I'm) Вэтом случае отсуствуют тяжело гелизуемые в железе функция sqrt и деления да и результат сразу в dB что увеличивает дин диапазон при отображении

Также есть возможность получения приблизительного значения sqrt( Re*Re + I'm*I'm) используя апроксимацию max(|Re|,|Im|)+min (|Re|,|Im|)*K при этом ошибка апроксимации ~5% что для отображения на экране впоне нормально .

Успехов! Rob.

andreichk
в последней интерпретации я вообще исключил извлечение кв. корня и нормируюсь по МАХ просто суммой квадратов.
Получилось намного красивее, во всяком случае пики задираются в одну сторону.
Код
module math (
input clk,
input dv,
input [8:0]real_,
input [8:0]imaginary,
output reg[8:0]out_
);
wire [17:0] real_re;
wire [17:0] imaginary_;
//модуль комплексного числа.    
multiplexor m_re (
  .clk(clk), // input clk
  .a(real_), // input [8 : 0] a
  .b(real_), // input [8 : 0] b
  .ce(dv),  
  .p(real_re) // output [17 : 0] p
);
multiplexor m_im (
  .clk(clk),     // input clk
  .a(imaginary), // input [8 : 0] a
  .b(imaginary), // input [8 : 0] b
  .ce(dv),  
  .p(imaginary_) // output [17 : 0] p
);
reg [18:0] summe;
always @ (posedge clk)
begin
summe <= real_re[17:0] + imaginary_[17:0];
end
//------------------------ ищем max ----------------------------------
wire [8:0] max = (dv == 1'b1) ? 1'b0: (( max < summe[8:0] ) ?  summe[8:0] : 1'b0);  
//----------------------- нормировка по max
wire [8:0] max_2;  
divider d_max (
    .clk(clk),         // input clk
    .ce(dv),           // input ce
    .dividend(max),    // input [8 : 0] dividend
    .divisor(1),       // input [8 : 0] divisor
    .fractional(max_2) // output[8 : 0] fractional
    );
wire [8:0] res;      
divider d_res (
    .clk(clk),       // input clk
    .ce(dv),         // input ce
    .dividend(summe[8:0]),// input [8 : 0] dividend
    .divisor(max_2), // input [8 : 0] divisor
    .fractional(res) // output[8 : 0] fractional
    );

always @ (posedge clk)
begin
      out_ <= res[8:0] - 305;//двигаем по высоте. меньше - выше
end

endmodule

Хочется конечно логарифм встроить как вы советуете, только вот не могу найти готовых решений на верилоге. Мож у кого завалялось, поделитесь, если не жалко.... rolleyes.gif

правда как обычно какая-то фигня на экран полезла в виде зеркальных повторов. как от этого избавиться, вот ещё задачка..... smile3046.gif
Lmx2315
QUOTE (andreichk @ Dec 30 2012, 21:25) *
Хочется конечно логарифм встроить как вы советуете, только вот не могу найти готовых решений на верилоге. Мож у кого завалялось, поделитесь, если не жалко.... rolleyes.gif


..не жалко :
CODE
log10 log10(
  .clk(clk), // input clk
  .ce(dv),
  .x_in(summe), // input [15 : 0] x_in
  .x_out(out_m) // output [8 : 0] x_out
);


..пользуйтесь, всегда рады помочь.
andreichk
Цитата(Lmx2315 @ Dec 30 2012, 18:47) *
..не жалко :
Код
log10 log10(
  .clk(clk), // input clk
  .ce(dv),
  .x_in(summe), // input [15 : 0] x_in
  .x_out(out_m) // output [8 : 0] x_out
);


..пользуйтесь, всегда рады помочь.

спасибо, только обьясните как ей пользоваться. это же какая-то готовая корка и у меня такой нет. просто так она ИЗЕй не распознаётся.
Lmx2315
QUOTE (andreichk @ Dec 30 2012, 22:01) *
спасибо, только обьясните как ей пользоваться. это же какая-то готовая ф-ция. просто так она ИЗЕй не распознаётся.


..даа ладно! а у меня так работает, странно.
andreichk
RROR:HDLCompilers:87 - "math.v" line 86 Could not find module/primitive 'log10'
Lmx2315
QUOTE (andreichk @ Dec 30 2012, 22:09) *
RROR:HDLCompilers:87 - "math.v" line 86 Could not find module/primitive 'log10'


..сарказм вам неведом.
Сделайте табличную реализацию логарифма - если обойдётесь шагом в 3 дБ вам понадобится всего примерно 60 значений в табличке, вряд-ли больше.
А захотите шаг 1 дБ - уместитесь в 180 строк, вам хватит за глаза.
Flood
Цитата(Lmx2315 @ Dec 30 2012, 21:47) *
..не жалко :
Код
log10 log10(
  .clk(clk), // input clk
  .ce(dv),
  .x_in(summe), // input [15 : 0] x_in
  .x_out(out_m) // output [8 : 0] x_out
);


..пользуйтесь, всегда рады помочь.


Со стороны как-то некрасиво выглядит, да и смысл жеста не понятен...
andreichk
будем считать это новогодней шюткой santa2.gif
novchok
Мне просто интересно, а как сигнал вводится в систему для анализа. Насколько я понимаю, качество съема сигнала и перевода его в цифру играет решающую роль при анализе спектра. Можете рассказать что именно анализируется, какие АЦП используются, какие фильтры стоят и т.д.
andreichk
да вот собственно входная часть, никаких спецфильтров, только ОУ и всё. в коде тоже нет никакой цифровой фильтрации, окон и всего того, что в принципе там должно быть. я пока ещё далёк от правильного понимания построения правильных измерительных приборов.Сьём данных,согласно графикам из даташита на корку ФФТ
novchok
Спасибо, схема интересная, единственное, чего могу сказать, OPA2652 честно отработает усиление в 30 не выше 10MHz, а судя по делителю, максимальное усиление как раз 30. Поэтому если будете пытаться получить реальный спектр сигнала, учтите, что операционники заваливают высокочастотный сигнал.
andreichk
ну дык скоп , да и спектр тоже, более , чем на 10-15 МГц и не расчитывался.
Timmy
Входную часть я бы делал примерно так:Нажмите для просмотра прикрепленного файла
Грубый/тонкий регуляторы смещения объединёны и регулятор упрощён с учётом того, что ОУ имеет по входу не меньший размах, чем по выходу, поэтому может использоваться в качестве буфера. Вход получится стандартный под осциллографический щуп с делителем.
На схеме от andreichk ассиметрично включён драйвер АЦП, так он не будет держать постоянное синфазное напряжение. И ещё, резисторы регулятора усиления выбраны очень странно, которые с малыми номиналами, если вспомнить, чему равно усиление такой схемы. А триггерную схему можно вообще сделать в цифре, или подключать к выходу IC2, чтобы не грузить высокоомный вход.
UPD:По драйверу АЦП возражение снимаю, его можно и так включать. И тонкое смещение действительно имеет смысл ставить после усилителя, чтобы его регулировка не зависела от коэффициента усиления.
MaverickDSP
Цитата(andreichk @ Dec 30 2012, 20:25) *
правда как обычно какая-то фигня на экран полезла в виде зеркальных повторов. как от этого избавиться, вот ещё задачка..... smile3046.gif

Очень похоже на спектр меандра
Либо сигнал на входе АЦП очень мощный, либо ошибка в типах данных.
В каком режиме работает АЦП ? signed или unsigned ? (ножка DF)
Я так понимаю, ядро БПФ ждет signed.
Uuftc
Цитата(andreichk @ Jan 1 2013, 20:41) *
да вот собственно входная часть, никаких спецфильтров, только ОУ и всё.

Фильтровать по аналогу перед ADC надо обязательно!
Алиасинг иначе никак не победить потом.
Aner
Если счетные ресурсы есть, то фильтровать по аналогу перед ADC не обязательно. Алиасинг никто уже и не побеждает, его используют. Как вторую, третью и тд. зоны Найквиста. Ну будет поболее шумов в этих зонах, появятся инскажения в сигналах, до приемлемого уровня фильтруется. Хотя не понятно для чего создавать такой спектроанализатор сегодня? Пройденный этап. При нынешних компах + 20 баксов за модуль (RTL2832+FC0013 или E4000) не e-bay получите неплохой спектроанализатор ~50...2200 Мгц.
Uuftc
Цитата(Aner @ Jan 10 2013, 22:31) *
Если счетные ресурсы есть, то фильтровать по аналогу перед ADC не обязательно. Алиасинг никто уже и не побеждает, его используют. Как вторую, третью и тд. зоны Найквиста.

Очень интересно, как можно разделить сигналы из разных диапазонов, например из первого и из второго, оцифрованных одновременно?
andreichk
Цитата(MaverickDSP @ Jan 10 2013, 13:32) *
В каком режиме работает АЦП ? signed или unsigned ? (ножка DF)
Я так понимаю, ядро БПФ ждет signed.

assign ADC_DF_DCS = 0;//Offset binary data, duty cycle correction on
при желании можно переключить на
assign ADC_DF_DCS = 1;//2's complement data, duty cycle correction on


Цитата(Uuftc @ Jan 10 2013, 16:14) *
Фильтровать по аналогу перед ADC надо обязательно!
Алиасинг иначе никак не победить потом.

а разве R86,R87,C30 не являются ФНЧ ?

Цитата(Aner @ Jan 10 2013, 19:31) *
Хотя не понятно для чего создавать такой спектроанализатор сегодня
знаете, если бы речь шла о том , где купить подешевле, то тема так бы и называлась, а так, отвечая на ваш вопрос - чтобы окончательно с ума не сойти - ...
Victor®
Цитата(Uuftc @ Jan 10 2013, 23:20) *
Очень интересно, как можно разделить сигналы из разных диапазонов, например из первого и из второго, оцифрованных одновременно?


Вот-вот... и мне интересно...
Просветите, плз! Жаль Найквиста тут нет...
andreichk
Народ, для загрузки скопа в припаянную к спартану флеш, сдули у кого-то из сети и адаптировали под наш модуль(с изменением пинов и тактовой частоты) проект загрузчика флеш. загрузчик собрался и откомпилировался без проблем.Но не хочет грузиться в спартан из за этого сообщения:
WARNING:MapLib:701 - Signal RS232_RXD connected to top level port RS232_RXD has been removed.

Получается, что он отрубил линию загрузки в спартан прямо на входе, ссылаясь , что этот сигнал никуда не идёт.
Весь проект перерыли , но найти обрыв не смогли. Может ктось глянет из опытных, если не влом. smile3046.gif
a123-flex
Цитата(andreichk @ Feb 4 2013, 16:04) *
Народ, для загрузки скопа в припаянную к спартану флеш, сдули у кого-то из сети и адаптировали под наш модуль(с изменением пинов и тактовой частоты) проект загрузчика флеш. загрузчик собрался и откомпилировался без проблем.Но не хочет грузиться в спартан из за этого сообщения:
WARNING:MapLib:701 - Signal RS232_RXD connected to top level port RS232_RXD has been removed.

Получается, что он отрубил линию загрузки в спартан прямо на входе, ссылаясь , что этот сигнал никуда не идёт.
Весь проект перерыли , но найти обрыв не смогли. Может ктось глянет из опытных, если не влом. smile3046.gif


то что трассировщик ругается на ногу, вовсе не означает, что всего лишь только с этой ногой проблема. Рассмотрите technology view после синтезатора - наверняка похерилось несколько блоков в результате оптимизации)
Kuzmi4
2 andreichk
Глянул одним глазом на проект - сложилось впечатление что у вас там нелады с инициализацией ваших примитивов типа LUT3 и так далее. Например ваш RS232_TX это вообще тригер который выводит константу, но имеет синхроный сброс.
Загнал в синплифай 2009, потом P&R ISE 13.2 - входной тракт так как описываете до stop_bit, дальше не смотрел. RS232_TX тоже не константу зашёлкивает, но у него какая то хитрая система с предустановкой. Так что думаю нужно ковырять эти ваши примитивы (коих у вас там море) и их инициализацию (после синтезатора там у вас кстати всё красиво - так что ещё один пункт за INIT).
andreichk
немного поковыряли сами и обнаружили следующее:
первоначально этот загрузчик расчитывался на такт.частоту 66МГц,
constant UARTDIV : std_logic_vector(5 downto 0) := "100011";
а мы решили изменить на 80 МГц и сделали так:
constant UARTDIV : std_logic_vector(5 downto 0) := "101010"; -- 43 / 80MH
так вот именно из за этого он и не компилится, но почему? какая ему разница?

Товарищи !!! Помогите кто чем может. Возникла идея добавить в проект модуль с применением ДЦМ и изменить частоту тактирования с 80 МГц до 66 МГц. Выглядит извращением конечно, но кв.генератора на 66 МГц нет и не предвидится.
На верилоге я бы сам справился, а на ВХДЛ не знаю как правильно описать сие действо....
andreichk
проблема решена заменой кварца на на 60 МГц. пересчитал коэф. деления и весь проект и всё получилось !!!

constant UARTDIV : std_logic_vector(5 downto 0) := "100000"; -- 32 / 60MHz

Ура товарищи, спасибо за помощь и содействие... disco.gif
compoa
Цитата(andreichk @ Dec 30 2012, 22:09) *
RROR:HDLCompilers:87 - "math.v" line 86 Could not find module/primitive 'log10'

Здравствуйте andreichk. Можно пару вопросов по первому осциллографу SED1335, PIC18F4685 ? Собрал я его, работает нормально, но - 1. Синхронизация не работает. 2. кнопки управления А, В, АВ, SPECTR - работают, остальные нет, при нажатии А^ - фиксируется изображение. 3. На одном канале сильно рисуются вертикальные линии при отсутствии сигнала на входе. Где примерно искать причину. Спасибо. С уважением Александр.
andreichk
мне кажется , что я уже писал, что не занимаюсь давно этим проектом, поэтому ничем помочь не могу.
compoa
Цитата(andreichk @ May 25 2013, 15:49) *
мне кажется , что я уже писал, что не занимаюсь давно этим проектом, поэтому ничем помочь не могу.

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.