Перейти к содержанию
    

Вывод ЧМ синусоиды на ЦАП

Здравствуйте.

Стоит задача сделать частотную модуляцию на плис. Плис - 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 МГц, хотя может быть можно поднять, но на много все равно не получиться.

Подскажите, благодарю.

Изменено пользователем Kostochkin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну если Accum <= Accum + 255 получается около 15кГц (хотя при 21битном аккумуляторе вроде как должно быть 100e6/(2^21/256) = 12кГц)

то может просто сделать Accum <= Accum + 89128 + 42 * Freq_Data;

константы только правильно подогнать, чтобы точнее в требуемые частоты попадали.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 значения..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

сделайте нормальный DDS. 1/4 синуса в таблицу 4к-16к точек, 14-16 бит фазы, 14-16 блочков памяти и все у вас будет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 minutes ago, des00 said:

сделайте нормальный DDS. 1/4 синуса в таблицу 4к-16к точек, 14-16 бит фазы, 14-16 блочков памяти и все у вас будет.

Зачем 14-16 бит фазы?

А где взять такую таблицу от 4000 до 16000 значений?

Благодарю

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 минут назад, Kostochkin сказал:

А где взять такую таблицу от 4000 до 16000 значений?

А в Matlab-е посчитать и в файл записать. Я так делал. Не для синуса только, а оконную функцию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 minutes ago, Kostochkin said:

но при 100 МГц, между крайними частотами синусоиды войдут 2 значения, так как мин шаг 10нс. Получается я могу подвинуть синусоиду на 4 положения и все,

хотелось бы больше, хотя бы 32 значения..

Математику не обманете :) При 5 MHz (округлил вверх) на выходе и 100 на входе у вас есть максимум 20 точек на период синусоиды (т.е. 5 на четверть периода). Это будет довольно 'грубая' синусоида.

Если вас такая устроит (по спектру выходного сигнала), то дальше выбираете размерность аккумулятора и величину, которую будете прибавлять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, xvr сказал:

Математику не обманете :) При 5 MHz (округлил вверх) на выходе и 100 на входе у вас есть максимум 20 точек на период синусоиды (т.е. 5 на четверть периода). Это будет довольно 'грубая' синусоида.

Если вас такая устроит (по спектру выходного сигнала), то дальше выбираете размерность аккумулятора и величину, которую будете прибавлять.

Ну и есть промежуточные варианты. Можно с блока обработки частоты - PLL или DCM взять в качестве клока сигнал, сдвинутый от основной частоты на 180 или 90 градусов. Но вот как потом его заправить в ЦАП - это надо будет решать отдельно...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

11 minutes ago, Kostochkin said:

Зачем 14-16 бит фазы?

Разрядность аккумулятора фазы  влияет на точность частоты которую вы можете генерировать  - чем  больше чем более точнее можете задавать генерируемую частоту.   А размер выходной таблицы  sin/cos влияет на величину гармоник.  Так как вход задания частоты у вас всего 8 бит  то  надо масштабировать его  перед суммированием в аккумуляторе ( Kfi = Kfin*A + B).  Ну и для уменьшения размера таблиц  sin|cos можно использовать интерполяцию . 

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 - тоже, только мне надо более точно задавать частоту синусоиды. Правильно ли я понимаю, что для этого мне надо увеличить размерность аккумулятора?

Благодарю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, RobFPGA сказал:

Ну и для уменьшения размера таблиц  sin|cos можно использовать интерполяцию . 

Можно еще в таблицу загнать не "sin|cos", а разницу между sin(x) и y=x... 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 блок будет взять гораздо проще, если только это не какая-нибудь лаба/курсовик.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 блок будет взять гораздо проще, если только это не какая-нибудь лаба/курсовик.

Благодарю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...