Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Генератор синуса на FPGA Altera
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
Porty
Добрый день

Для проверки 18 ультразвуковых трактов нужен любой точный (побочные гармоники не более -110дб) генератор отсчётов синусов произвольной частоты внутри ПЛИС с периодом не кратным целому числу и степени двойки. Поэтому заранее рассчитанная таблица в памяти не пригодна. Частота дискретизации от 100кГц до 500кГц. Как проще сделать?
Теорию прямого цифрового синтеза я знаю, и примерно представляю как реализовать, но вряд ли я сделаю чистый синус сразу затратив минимум времени и хотелось бы сразу получить результат т.к. это нужно исключительно для отладки (Подставить вместо АЦП в качестве источника сигнала).

ПЛИС - Аltera Cyclon II 20k
Разрядность 16 бит целые.
Частота дискр. от 100 до 500кГц.

Какие есть готовые решения для создания такого генератора?
Или как самому быстро накидать достаточно точный генератор?
Есть готовые компоненты в Квартусе для генерации синуса или реализующую функцию синуса?

Заранее спасибо.
soldat_shveyk
Тут квартус с его компонентами не важны.
Вы заявили требования до 500 кГц с SFDR 110 дБ.
Нужен ЦАП с такими параметрами, через который Вы будете выдавать синус из FPGA. Есть что-то похожее на примете?
Porty
Мне нужно получить внутри ПЛИС цифровые отсчёты якобы полученые из АЦП для отладки. Т.е. генератор данных который бы заменил АЦП и качество работы которого не вызывало бы сомнений. Это нужно чтоб проверить надёжность всей системы сбора данных в целом.
iosifk
Цитата(Porty @ Aug 29 2011, 16:07) *
Разрядность 16 бит целые.


На самом деле, Вам нужна в таблице четвертинка периода, да и то, не полный синус, а разница между синусом и линейной частью.
Porty
Цитата(iosifk @ Aug 29 2011, 16:32) *
На самом деле, Вам нужна в таблице четвертинка периода, да и то, не полный синус, а разница между синусом и линейной частью.

Спасибо, я это всё понимаю, но мне нужно 18 каналов, т.е. 18 генераторов с определёнными фиксированными характеристиками и высокой точностью, но к сожалению у меня вышел низкоточный т.к. мало точек и линейная интерполяция между ними. Либо высокоточный но не влазит ни по количеству ячеек ни по памяти т.к. нужно место для основного алгоритма. Я хочу найти готовый т.к. не хочу тратить время, и не вижу сысла вести исследования ради отладочной функции (с тем же успехом можно наделать пилу но с помощью её ряд ошибок в каналах данных и мультиплексорах не проверишь), в добавок мне не требуется мегаскорость. Достаточно 100кГц за глаза. Мне интересно как это сделать и как получить быстро результат не потратив кучу времени на изучение интерполяций и способов и разрабатывая самому генератор его ещё нужно проверять и тд. Интереснее готовый или из минимального числа готовых блоков.
Как впихнуть в 7.5к бит памяти и 9к ячеек 18 более менее точных 16 битных генераторов выборок синусов затратив максимум неделю, вот в чём вопрос.
=SSN=
Цитата(iosifk @ Aug 29 2011, 16:32) *
На самом деле, Вам нужна в таблице четвертинка периода...

И как с её помощью получить "генератор отсчётов синусов произвольной частоты внутри ПЛИС с периодом не кратным целому числу и степени двойки" ?

Или к табличке ещё и Фэрроу прилагается?
Porty
Цитата(=SSN= @ Aug 29 2011, 16:46) *
И как с её помощью получить "генератор отсчётов синусов произвольной частоты внутри ПЛИС с периодом не кратным целому числу и степени двойки" ?

Или к табличке ещё и Фэрроу прилагается?

получить можно, и я ошибся - нужны любые фиксированные частоты так чтоб выборки как можно дольше не повторялись. Смысл отладки такой таблицей в том что если в каналах связи потеряется пакет любой длинны в любом положении фазы, то ФФТ на это среагировало и резко подпрыгнули боковые лепестки или выскочили побочные гармоники и прочие артифакты (выше 100дб) и была возможность продетектировать это. Если сигнал берётся из таблицы темболее степени двойки то большой шанс того что период целиком выпадет и на ФФТ это не продетектируется.
iosifk
Цитата(Porty @ Aug 29 2011, 16:44) *
Спасибо, я это всё понимаю, но мне нужно 18 каналов, т.е. 18 генераторов с определёнными фиксированными характеристиками и высокой точностью,

Что-то типа этого:
http://www.chipovod.ru/plis/dds-generator-na-plis/

А 18 каналов делаются из одного, если его заставить работать в 18 раз быстрее и при смене канала перезагружать регистры... в моем "кратком курсе" есть раздел "многопоточность"...
=SSN=
Цитата(Porty @ Aug 29 2011, 16:51) *
нужны любые фиксированные частоты так чтоб выборки как можно дольше не повторялись.

А решить систему дифференциальных уравнений:

W*cos(Wt) = sin(Wt)'
W*sin(Wt) = -cos(Wt)'

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

Или CORDIC на ПЛИС?
Hoodwin
Нда... Количество советов по вариантам цифровой генерации синуса скоро превысит число доказательств теоремы Пифагора sm.gif

Вот самый простой способ, описан тут:
http://www.ti.com/lit/an/spra096a/spra096a.pdf, раздел A.1 на странице 16.

Для совсем ленивых описываю суть алгоритма:

y(i+1) = 2*cos(phi)*y(i) - y(i-1), где:

y(i) - последовательность целочисленных значений синусоиды
cos(phi) - отвечает за частоту, phi - это приращение фазы синусоиды за один период частоты дискретизации. phi = 2*pi*f / f0.

начальные значения y(0) и y(-1) определяют фазу и амплитуду генерируемого сигнала. Если на начальную фазу плевать, то подойдут такие значения: y(0) = 0, y(-1) = -A * sin(phi), где А - амплитуда синусоиды.

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


Если Вам будет жалко тратить целый умножитель на каждый из 18 каналов, то Вы можете организовать конвейер и контексты на большей частоте, которые будут кормить общий умножитель. Контекст каждого канала полностью определяется тремя величинами y(i), y(i-1) и cos(phi), последняя, впрочем, константа и допускает некоторую оптимизацию.

Успехов!




mse
Цитата(=SSN= @ Aug 29 2011, 16:46) *
И как с её помощью получить "генератор отсчётов синусов произвольной частоты внутри ПЛИС с периодом не кратным целому числу и степени двойки" ?
Дык... "Просто"...
Текущую фазу сигнала "произвольной частоты" грузить в табличку, а выгружать амплитуду сигнала "произвольной частоты". И так стопицот тыщ раз в секунду.
eugen_pcad_ru
Используйте ядро NСО из состава встроенных ядер - по моему это самый простой путь.
Правда не знаю сколько ресурсов у Вас это всё дело скушает, но можно не генерить сразу полную разрядность. Или сделать только один генератор и его частоту потом крутить, не вариант?
P.S.: А может синус вообще необязателен? Может и треугольника или меандра с головой хватит?
Мур
Цитата(eugen_pcad_ru @ Aug 30 2011, 08:58) *
Используйте ядро NСО из состава встроенных ядер - по моему это самый простой путь.
Правда не знаю сколько ресурсов у Вас это всё дело скушает, но можно не генерить сразу полную разрядность. Или сделать только один генератор и его частоту потом крутить, не вариант?
P.S.: А может синус вообще необязателен? Может и треугольника или меандра с головой хватит?


Присоединяюсь к NCO. Мощная вещь! Для пробы то что надо! Там, кстати, можно вытянуть ваши 110дб, если заказать....
Porty
Цитата(Hoodwin @ Aug 29 2011, 17:38) *
Нда... Количество советов по вариантам цифровой генерации синуса скоро превысит число доказательств теоремы Пифагора sm.gif

Вот самый простой способ, описан тут:
http://www.ti.com/lit/an/spra096a/spra096a.pdf, раздел A.1 на странице 16.

Для совсем ленивых описываю суть алгоритма:

y(i+1) = 2*cos(phi)*y(i) - y(i-1), где:

y(i) - последовательность целочисленных значений синусоиды
cos(phi) - отвечает за частоту, phi - это приращение фазы синусоиды за один период частоты дискретизации. phi = 2*pi*f / f0.

начальные значения y(0) и y(-1) определяют фазу и амплитуду генерируемого сигнала. Если на начальную фазу плевать, то подойдут такие значения: y(0) = 0, y(-1) = -A * sin(phi), где А - амплитуда синусоиды.

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


Если Вам будет жалко тратить целый умножитель на каждый из 18 каналов, то Вы можете организовать конвейер и контексты на большей частоте, которые будут кормить общий умножитель. Контекст каждого канала полностью определяется тремя величинами y(i), y(i-1) и cos(phi), последняя, впрочем, константа и допускает некоторую оптимизацию.

Успехов!


Спасибо, эта штука заработала, и как я только умудрился забыть то что сдавал давным давно в универе когда только пришли комплекты "Умка" на базе КР580, я тогда с преподом наспор за зачот сделал расчёт таблицы синусов по этой итерационной формуле ньютона если не ошибаюсь с названием.
Штука заработала но я не осилил расчёт погрешностей статических и динамических в итоге чуток частота плавает и не точно задаётся, например задал pi*200 = 628.318531Hz, а вышла pi*203=637.743309Hz в арифметике с фикс. запятой 16/16. 16 бит на числа после запятой по идее должно хватить, странно что частота не точно выставлена оказалось, умножитель 64 битный, округляю правильно по правилам арифметики округления.
Hoodwin
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 Гц, то косинус будет равен половинке и вообще не даст погрешности.

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

Porty
Цитата(Hoodwin @ Aug 30 2011, 12:37) *
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кбитный Циклон никак не влазило.
Hoodwin
А как проверяли, что плавает то? Может, если через FFT проверяли, то из за плавающего окна FFT плавает результат самого FFT. У меня такое бывало, как раз с DTMF детекторами.
Porty
Цитата(Hoodwin @ Aug 30 2011, 14:01) *
А как проверяли, что плавает то? Может, если через FFT проверяли, то из за плавающего окна FFT плавает результат самого FFT. У меня такое бывало, как раз с DTMF детекторами.


Да, это FFT себя так ведёт когда разница фаз синусоиды относительно окна FFT почти совпадает с разницей в 2 герца, отсюда и колебания по частоте. Повезло значит =) Когда писал компонент для ФФТ не парился и взял готовые генераторы и окна с готовыми примерами которые были вылезаны и отшлифованы так чтоб при параметрах в примере было всё ну идеальнее некуда. biggrin.gif
dde29
А с алгоритмом CORDIC - не знакомы? занимает не более 2к ячеек
Porty
Цитата(dde29 @ Sep 1 2011, 18:59) *
А с алгоритмом CORDIC - не знакомы? занимает не более 2к ячеек

алгоритмом ньютона я вписался в 200 ячеек на каждый индивидуальный канал + 200 ячеек на мультиплексор с умножителем из 8 дсп блоков на 4 канала, итого на 18 каналов вышло 4 916 ячеек и 36 умножителей. Точность каждого канала -130дб, THD - 0.0001%
Кордик изначально пробовал в NCO - изначально он мне не понравился из за размеров потребляемых ресурсов
dde29
Цитата(Porty @ Sep 2 2011, 08:41) *
алгоритмом ньютона я вписался в 200 ячеек на каждый индивидуальный канал + 200 ячеек на мультиплексор с умножителем из 8 дсп блоков на 4 канала, итого на 18 каналов вышло 4 916 ячеек и 36 умножителей. Точность каждого канала -130дб, THD - 0.0001%
Кордик изначально пробовал в NCO - изначально он мне не понравился из за размеров потребляемых ресурсов


У меня в корлике разрядность данных была 16. соответственно конвейер состоял из 16 звеньев. Использовал только операции суммирование/вычитание и сдвиг регистров - занимает ресурсов 1700 ячеек (Cyclone I)
Porty
Цитата(dde29 @ Sep 3 2011, 07:43) *
У меня в корлике разрядность данных была 16. соответственно конвейер состоял из 16 звеньев. Использовал только операции суммирование/вычитание и сдвиг регистров - занимает ресурсов 1700 ячеек (Cyclone I)

16 звеньев это 16 независимых по частоте и фазе каналов?
Что такое звено?
dde29
Цитата(Porty @ Sep 3 2011, 12:56) *
16 звеньев это 16 независимых по частоте и фазе каналов?
Что такое звено?


Советую ознакомиться с алгоритмом CORDIC - там каждая итерация рассчета фазы - одно звено.
Кордик рпссчитывает значение синуса и косинуса для заданного угла...
anatolich
Cделал такой же генератор, на 14 бит целочисленный с подставкой.

Как вы SNR считаете? Я получил сигнал в ModelSim
взял от него DFT (без всяких окон) и просуммировал все по модулю
отфитинговал сигнал синусом
Нашел разницу между синусом и сигналом с ModelSim
Взял DFT от этой разницы и тоже просуммировал модули
Поделил одно на другое 10log(S/N) получилось 16дБл
10 - потомучто интегрирую

Как же правильно оценить мой синус?
Maverick
Цитата(anatolich @ Jul 4 2013, 16:24) *

поделились бы реализациями, может другим полезно будет wink.gif
anatolich
Вот мой пример
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 логических элементов
Квартус пишет
anatolich
2+6*14=86ДБл
Такое примерно число получается если от основной гармоники
генератора отнять палку от референтного синуса и поделить
на референтный синус.
Или то же самое в 3-х сигмах.
Но мне кажется, что честнее весь спектр учитывать. Нет?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.