Kostochkin 0 14 января, 2020 Опубликовано 14 января, 2020 (изменено) · Жалоба Здравствуйте. Стоит задача сделать частотную модуляцию на плис. Плис - spartan 6. На вход подается значение 8-бит - частота, фаза и амплитуда заданы жестко. На выходе нужна частотно-модулированная синусоида. Модуляция в общих чертах понятна, но у меня следующие требования: минимальная частота синусоиды - 4.25 МГц; максимальная частота синусоиды - 4.756 МГц; следовательно в этот промежуток мне надо уложить 256 шагов. Вот есть алгоритм DDS library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use IEEE..std_logic_unsigned.all; -------------------------------------------------- Entity DDFS is -------------------------------------------------- Port ( CLK : in std_logic; Freq_Data : in std_logic_vector (7 downto 0); Dout : out std_logic_vector (7 downto 0) ); end DDFS; -------------------------------------------------- Architecture RTL of DDFS is -------------------------------------------------- signal Result : signed (7 downto 0); signal Accum : unsigned (20 downto 0) := (others=>'0'); signal Address : integer range 0 to 63; signal RomAddr : integer range 0 to 63; signal Quadrant : std_logic; signal Sign : std_logic; type Rom64x8 is array (0 to 63) of signed (7 downto 0); constant Sinus_Rom : Rom64x8 := ( x"02", x"05", x"08", x"0b", x"0e", x"11", x"14", x"17", x"1a", x"1d", x"20", x"23", x"26", x"29", x"2c", x"2f", x"32", x"36", x"39", x"3c", x"3e", x"40", x"43", x"46", x"48", x"4b", x"4d", x"50", x"52", x"54", x"57", x"59", x"5b", x"5d", x"5f", x"62", x"64", x"65", x"67", x"69", x"6b", x"6d", x"6e", x"70", x"71", x"73", x"74", x"75", x"76", x"77", x"79", x"79", x"7a", x"7b", x"7c", x"7d", x"7d", x"7e", x"7e", x"7f", x"7f", x"7f", x"7f", x"7f"); begin -- Phasenakkumulator process begin wait until rising_edge(CLK); Accum <= Accum + unsigned(Freq_Data); end process; -- BROM process begin wait until rising_edge(CLK); RomAddr <= Address; -- getaktete Adresse --> BRAM end process; Result <= signed(Sinus_Rom(RomAddr)); Quadrant <= Accum(Accum'left-1); Address <= to_integer(Accum(Accum'high-2 downto Accum'high-7)) when (Quadrant='0') else 63-to_integer(Accum(Accum'high-2 downto Accum'high-7)); -- 1 Takt Latency wegen BROM process begin wait until rising_edge(CLK); Sign <= Accum(Accum'left); end process; Dout <= std_logic_vector( Result) + x"7f" when (Sign='1') else std_logic_vector(0-Result) - x"7f"; end RTL; Но этот алгоритм по тактировании 100 МГц выдает максимальную частоту синусоины порядка 15 кГц. А мне надо от 4.25 МГц до 4.756МГц. Как вариант делать огромную таблицу на допустим 4096 значений, и при большой частоте синусоиды считывать не каждое значение а каждое 16 допустим, это относительно точности. А какие-то не табличные быстрые методы получения чм синусоиды есть? В моем проекте тактирование вывода синусоиды - 108 МГц, хотя может быть можно поднять, но на много все равно не получиться. Подскажите, благодарю. Изменено 14 января, 2020 пользователем Kostochkin Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба ну если Accum <= Accum + 255 получается около 15кГц (хотя при 21битном аккумуляторе вроде как должно быть 100e6/(2^21/256) = 12кГц) то может просто сделать Accum <= Accum + 89128 + 42 * Freq_Data; константы только правильно подогнать, чтобы точнее в требуемые частоты попадали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kostochkin 0 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 1 hour ago, _pv said: ну если Accum <= Accum + 255 получается около 15кГц (хотя при 21битном аккумуляторе вроде как должно быть 100e6/(2^21/256) = 12кГц) то может просто сделать Accum <= Accum + 89128 + 42 * Freq_Data; константы только правильно подогнать, чтобы точнее в требуемые частоты попадали. Благодарю. но при 100 МГц, между крайними частотами синусоиды войдут 2 значения, так как мин шаг 10нс. Получается я могу подвинуть синусоиду на 4 положения и все, хотелось бы больше, хотя бы 32 значения.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба сделайте нормальный DDS. 1/4 синуса в таблицу 4к-16к точек, 14-16 бит фазы, 14-16 блочков памяти и все у вас будет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kostochkin 0 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 6 minutes ago, des00 said: сделайте нормальный DDS. 1/4 синуса в таблицу 4к-16к точек, 14-16 бит фазы, 14-16 блочков памяти и все у вас будет. Зачем 14-16 бит фазы? А где взять такую таблицу от 4000 до 16000 значений? Благодарю Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 11 минут назад, Kostochkin сказал: А где взять такую таблицу от 4000 до 16000 значений? А в Matlab-е посчитать и в файл записать. Я так делал. Не для синуса только, а оконную функцию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 23 minutes ago, Kostochkin said: но при 100 МГц, между крайними частотами синусоиды войдут 2 значения, так как мин шаг 10нс. Получается я могу подвинуть синусоиду на 4 положения и все, хотелось бы больше, хотя бы 32 значения.. Математику не обманете :) При 5 MHz (округлил вверх) на выходе и 100 на входе у вас есть максимум 20 точек на период синусоиды (т.е. 5 на четверть периода). Это будет довольно 'грубая' синусоида. Если вас такая устроит (по спектру выходного сигнала), то дальше выбираете размерность аккумулятора и величину, которую будете прибавлять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 2 минуты назад, xvr сказал: Математику не обманете :) При 5 MHz (округлил вверх) на выходе и 100 на входе у вас есть максимум 20 точек на период синусоиды (т.е. 5 на четверть периода). Это будет довольно 'грубая' синусоида. Если вас такая устроит (по спектру выходного сигнала), то дальше выбираете размерность аккумулятора и величину, которую будете прибавлять. Ну и есть промежуточные варианты. Можно с блока обработки частоты - PLL или DCM взять в качестве клока сигнал, сдвинутый от основной частоты на 180 или 90 градусов. Но вот как потом его заправить в ЦАП - это надо будет решать отдельно... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба Приветствую! 11 minutes ago, Kostochkin said: Зачем 14-16 бит фазы? Разрядность аккумулятора фазы влияет на точность частоты которую вы можете генерировать - чем больше чем более точнее можете задавать генерируемую частоту. А размер выходной таблицы sin/cos влияет на величину гармоник. Так как вход задания частоты у вас всего 8 бит то надо масштабировать его перед суммированием в аккумуляторе ( Kfi = Kfin*A + B). Ну и для уменьшения размера таблиц sin|cos можно использовать интерполяцию . Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kostochkin 0 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 2 hours ago, _pv said: ну если Accum <= Accum + 255 получается около 15кГц (хотя при 21битном аккумуляторе вроде как должно быть 100e6/(2^21/256) = 12кГц) то может просто сделать Accum <= Accum + 89128 + 42 * Freq_Data; константы только правильно подогнать, чтобы точнее в требуемые частоты попадали. 20 точек на период меня устраивает, пока. И решение Accum <= Accum + 89128 + 42 * Freq_Data - тоже, только мне надо более точно задавать частоту синусоиды. Правильно ли я понимаю, что для этого мне надо увеличить размерность аккумулятора? Благодарю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 6 минут назад, RobFPGA сказал: Ну и для уменьшения размера таблиц sin|cos можно использовать интерполяцию . Можно еще в таблицу загнать не "sin|cos", а разницу между sin(x) и y=x... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
litv 0 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба В Xilinx DDS готовый блок есть. пара блок рам и , выбор sfdr ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 1 hour ago, Kostochkin said: но при 100 МГц, между крайними частотами синусоиды войдут 2 значения, так как мин шаг 10нс. Получается я могу подвинуть синусоиду на 4 положения и все, хотелось бы больше, хотя бы 32 значения.. ничего не понял, какие 2 значения, какие 4 положения, если freq_data == 0, частота на выходе = 100e6/(2^21/(89128)) = 4249954,2 Гц если freq_data == 1, частота на выходе = 100e6/(2^21/(89128+42*1)) = 4252004,6 Гц ... если freq_data == 255, частота на выходе = 100e6/(2^21/(89128 + 42*255)) = 4760694,5 Гц если надо абсолютную частоту точнее задавать чтобы не 4249954,2 а 4250000,0 то да, увеличивайте аккумулятор, но 8 бит Freq_Data всё равно будет делить заданный диапазон частот на 256 значений. и как уже подсказали таблицу тоже надо бы привести в соответствии с выходными 8 битами данных, то есть как минимум 256*2*Pi/4 ~512, а не 64 - раз в 8 побольше сделать. делается даже не в матлабе, а достаточно экселя =ROUND(255*SIN(A1*2*PI()/2048);0). но готовый DDS блок будет взять гораздо проще, если только это не какая-нибудь лаба/курсовик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kostochkin 0 14 января, 2020 Опубликовано 14 января, 2020 · Жалоба 1 hour ago, _pv said: ничего не понял, какие 2 значения, какие 4 положения, если freq_data == 0, частота на выходе = 100e6/(2^21/(89128)) = 4249954,2 Гц если freq_data == 1, частота на выходе = 100e6/(2^21/(89128+42*1)) = 4252004,6 Гц ... если freq_data == 255, частота на выходе = 100e6/(2^21/(89128 + 42*255)) = 4760694,5 Гц если надо абсолютную частоту точнее задавать чтобы не 4249954,2 а 4250000,0 то да, увеличивайте аккумулятор, но 8 бит Freq_Data всё равно будет делить заданный диапазон частот на 256 значений. и как уже подсказали таблицу тоже надо бы привести в соответствии с выходными 8 битами данных, то есть как минимум 256*2*Pi/4 ~512, а не 64 - раз в 8 побольше сделать. делается даже не в матлабе, а достаточно экселя =ROUND(255*SIN(A1*2*PI()/2048);0). но готовый DDS блок будет взять гораздо проще, если только это не какая-нибудь лаба/курсовик. Благодарю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться