Jump to content

    
Sign in to follow this  
porty

Генератор синуса на FPGA Altera

Recommended Posts

1. Вообще, насколько я себе представляю, 16 разрядов мало для 110 дБ. Вот вроде бы по науке соотношение сигнал/ошибка будет, если правильно помню, порядка 2 дБ + 6 дБ * N, где N - число разрядов. Как следствие, 16 разрядов дадут что-то около 98 дБ, а для 110 нужно не менее 18 разрядов. Я бы сделал для подстраховки разрядов 20, чтобы иметь небольшой запас на точность вычислений.

 

2. Так частота "плавает" или просто неточно задается? Как я уже написал, нужно так выбрать частоту дискретизации, чтобы у сигнала был ощутимый набег фазы, порядка 45-60 градусов. В этом случае округление значения косинуса не приведет к заметным изменениям задающей частоты. Чтобы было понятнее, поясню на примере. Вот есть частота синусоиды 200 Гц. А частота дискретизации, скажем, 56000 Гц.

cos(2*pi*200/56000) будет 0,999748235. Приведение к Q0.16 даст 65519,50033. Обрезание до целого даст 65519, что эквивалентно значению косинуса 0,999740601, или исходной частоте 203,0098173 Гц.

 

Если все то же самое проделать с частотой дискретизации 1600 Гц, на которой 200 Гц дает набег фазы в 1/8 периода, то частота составит 200,0052204 Гц. Если же взять частоту под набег фазы в 1/6 периода, 1200 Гц, то косинус будет равен половинке и вообще не даст погрешности.

 

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

 

1. Нормально вышло. Точность достаточная для наших практических целей. Хоть и реально меньше, но соответствует 16 разрядам.

2. Частота задаётся статически не правильно, но я с этим разобрался, был формат Q16.16 на предыдущее значение синуса и Q16.16 на коэффициент умножения, сделал коэффициент в Q1.31 стало гораздо точнее.

Но частота по времени плавает чуток - на доли герца, примерно плавает на 0.5Гц с периодом в 0.5-1 секунду при 12345.567Гц требуемой на 192кГц дискретизации. Но это уже не критично, просил для саморазвития. Просто, интересно стало почему плавает. =)

 

 

NСО не приемлем из за большого потребления ресурсов (по памяти не влезло). Всё-таки нужно 18 каналов сделать с разными частотами и фазами каждый. На канал 15-25кбит требуется, в 200кбитный Циклон никак не влазило.

Edited by Porty

Share this post


Link to post
Share on other sites

А как проверяли, что плавает то? Может, если через FFT проверяли, то из за плавающего окна FFT плавает результат самого FFT. У меня такое бывало, как раз с DTMF детекторами.

Share this post


Link to post
Share on other sites
А как проверяли, что плавает то? Может, если через FFT проверяли, то из за плавающего окна FFT плавает результат самого FFT. У меня такое бывало, как раз с DTMF детекторами.

 

Да, это FFT себя так ведёт когда разница фаз синусоиды относительно окна FFT почти совпадает с разницей в 2 герца, отсюда и колебания по частоте. Повезло значит =) Когда писал компонент для ФФТ не парился и взял готовые генераторы и окна с готовыми примерами которые были вылезаны и отшлифованы так чтоб при параметрах в примере было всё ну идеальнее некуда. :biggrin:

Share this post


Link to post
Share on other sites
А с алгоритмом CORDIC - не знакомы? занимает не более 2к ячеек

алгоритмом ньютона я вписался в 200 ячеек на каждый индивидуальный канал + 200 ячеек на мультиплексор с умножителем из 8 дсп блоков на 4 канала, итого на 18 каналов вышло 4 916 ячеек и 36 умножителей. Точность каждого канала -130дб, THD - 0.0001%

Кордик изначально пробовал в NCO - изначально он мне не понравился из за размеров потребляемых ресурсов

Share this post


Link to post
Share on other sites
алгоритмом ньютона я вписался в 200 ячеек на каждый индивидуальный канал + 200 ячеек на мультиплексор с умножителем из 8 дсп блоков на 4 канала, итого на 18 каналов вышло 4 916 ячеек и 36 умножителей. Точность каждого канала -130дб, THD - 0.0001%

Кордик изначально пробовал в NCO - изначально он мне не понравился из за размеров потребляемых ресурсов

 

У меня в корлике разрядность данных была 16. соответственно конвейер состоял из 16 звеньев. Использовал только операции суммирование/вычитание и сдвиг регистров - занимает ресурсов 1700 ячеек (Cyclone I)

Share this post


Link to post
Share on other sites
У меня в корлике разрядность данных была 16. соответственно конвейер состоял из 16 звеньев. Использовал только операции суммирование/вычитание и сдвиг регистров - занимает ресурсов 1700 ячеек (Cyclone I)

16 звеньев это 16 независимых по частоте и фазе каналов?

Что такое звено?

Share this post


Link to post
Share on other sites
16 звеньев это 16 независимых по частоте и фазе каналов?

Что такое звено?

 

Советую ознакомиться с алгоритмом CORDIC - там каждая итерация рассчета фазы - одно звено.

Кордик рпссчитывает значение синуса и косинуса для заданного угла...

Share this post


Link to post
Share on other sites

Cделал такой же генератор, на 14 бит целочисленный с подставкой.

 

Как вы SNR считаете? Я получил сигнал в ModelSim

взял от него DFT (без всяких окон) и просуммировал все по модулю

отфитинговал сигнал синусом

Нашел разницу между синусом и сигналом с ModelSim

Взял DFT от этой разницы и тоже просуммировал модули

Поделил одно на другое 10log(S/N) получилось 16дБл

10 - потомучто интегрирую

 

Как же правильно оценить мой синус?

 

Share this post


Link to post
Share on other sites

Вот мой пример

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

use ieee.numeric_std.all;

 

entity sinnw is

port (

clk : in std_logic;

reset : in std_logic;

en : in std_logic;

sine : out std_logic_vector(13 downto 0));

 

end sinnw;

 

architecture behave_sine_cos of sinnw is

 

signal sine_s : unsigned(13 downto 0);

 

begin -- behave_sine_cos

 

registers: process (clk, reset)

variable y_1, y_2, sine_m : integer;

variable sine_d : integer;

 

begin -- process registers

if reset = '0' then -- asynchronous reset (active low)

y_1 := 0;

y_2 := -103;

sine <= "00000000000000";

elsif clk'event and clk = '1' then -- rising clock edge

if (en = '1') then

sine_d := 16383*y_1;

sine_m := sine_d/8192-y_2;

y_2 := y_1;

y_1 := sine_m;

sine_s <= to_unsigned(sine_m,14)+ 8192;

sine <= std_logic_vector((sine_s)); --

end if;

end if;

end process registers;

 

end behave_sine_cos;

 

Но только синтезится без встроеного умножителя, поэтому 170 логических элементов

Квартус пишет

Share this post


Link to post
Share on other sites

2+6*14=86ДБл

Такое примерно число получается если от основной гармоники

генератора отнять палку от референтного синуса и поделить

на референтный синус.

Или то же самое в 3-х сигмах.

Но мне кажется, что честнее весь спектр учитывать. Нет?

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