基于FPGA實現頻率、幅度、相位可調的DDS
1 摘要
直接數字合成器( DDS ) 是一種通過生成數字形式的時變信號并進行數模轉換來產生模擬波形(通常為正弦波)的方法,它通過數字方式直接合成信號,而不是通過模擬信號生成技術。DDS主要被應用于信號生成、通信系統中的本振、函數發生器、混頻器、調制器、聲音合成器以及作為數字鎖相環的一部分。
2 DDS技術優點
(1)頻率分辨率較高,一般在0.01Hz左右,有的能做到1uHz,甚至更小;
(2)轉換時間快,系統無反饋環節,其開環結構使得頻率轉換時間很短,最快可以達到納秒級;
(3)具有輸出任意波形的能力,只要將任意波形數據加載到ROM中,通過DAC輸出,即可得到ROM存儲的任意波形;
(4)具有調制能力,DDS是相位控制系統,有利于各種調制功能。DDS技術的這些優點,使它成為衛星定位、移動通信、數字通信等系統中信號源的首選。
3 功能原理
3.1 模型結構
DDS 是從相位出發,直接采用數字技術產生波形的一種頻率合成技術。基本模型如圖所示,主要由時鐘頻率源、相位累加器、波形存儲器、及后級數模轉換器(DAC)、低通濾波器(LPF)組成。頻率控制字M和相位控制字分別控制DDS輸出正(余)弦波的頻率和相位。每來一個時鐘脈沖,相位寄存器以步長M遞增。相位寄存器的輸出與相位控制字相加,其結果作為正(余)弦查找表的地址。正(余)弦查找表的數據存放在ROM中,內部存有一個周期的正弦波信號的數字幅度信息,每個查找表的地址對應于正弦波中 0°~360°范圍內的一個相位點。查找表把輸入的址信息映射成正(余)弦波的數字幅度信號,同時輸出到數模轉換器DAC的輸入端,DAC 輸出的模擬信號經過低通濾波器 (LPF),可得到一個頻譜純凈的正(余)弦波。
(1)累加器:通過頻率控制字和相位控制字的累加,來取出波形數據表中相對應位置的數據。
(2)波形數據表:存儲波形數據(我們主要采取matllab工具生成波形數據)
(3)數模轉換器:將離散數據變成連續的。
(4)低通濾波器:對數模轉換器出來的波形進行濾波,達到一個平滑波形的作用。
3.2 DDS原理
1、工作原理頻率字B,數值大小控制輸出信號的頻率大小,數值越大輸出信號頻率越高,反之越小。
假設ROM的深度的位寬為N,所以ROM一共有 2N 個數據。讀取ROM的時鐘為fclk ,如果一個時鐘周期讀地址+1,那么讀出一個完整的波形需要的時間為:
則讀出的波形頻率fout為
如果每一個時鐘周期讀地址+B,那么讀出一個完整的波形需要的時間為
頻率控制字B,由上述式計算得
2、工作原理相位字P,數值大小控制輸出信號的相位偏移,主要用于相位的信號調制。
我們用一個矢量圖來描述相位,已知我們整個波形的采樣點是2N個,當改變讀rom的起始地址,就能改變讀出來的波形相位,假設每次相位變換為1°,則相位控制字p_word
根據矢量圖計算相位分辨率
當需要對信號改變N°時,則計算出相應的相位字P為
3、波形數據表 ROM波形數據表 ROM 以相位調制器傳入的相位碼為 ROM 讀地址,將地址對應存儲單元中的電壓幅值數字量輸出。
4、波形DAC輸出自波形數據表 ROM 輸出的波形數據傳入 D/A 轉換器轉換為模擬信號。D/A 轉換器即數/模轉換器指將數字信號轉換為模擬信號的電子元件或電路。
4 DDS的現實
4.1 ROM波形數據生成
使用MATLAB來生成正弦波、方波、三角波、鋸齒波的波形,通過FPGA ROM IP核加載COE文件存儲相應的波形數據,MATLAB代碼
%*****************************************square_wave *******************************%
%參數設置
% bitWidth = 14; % 位寬
% depth = 2048; % 深度
% maxValue = 2^bitWidth - 1; % 無符號數的最大值
%
% % 生成方波
% t = linspace(0, 1, depth);
% halfCycle = depth / 2; % 半個周期的樣本數
% squareWave = zeros(1, depth); % 初始化方波數組
%
% % 生成方波
% for i = 1:depth
% if i <= halfCycle
% squareWave(i) = maxValue; % 高電平
% else
% squareWave(i) = 0; % 低電平
% end
% end
%
% % 將方波限制在無符號范圍內
% squareWave = uint16(squareWave);
% plot(squareWave)
% % 打開文件以寫入
% fileID = fopen('square_wave.coe', 'w');
%
% % 寫入COE文件頭
% fprintf(fileID, 'memory_initialization_radix=10;\n');
% fprintf(fileID, 'memory_initialization_vector=\n');
%
% % 寫入數據
% for i = 1:depth
% fprintf(fileID, '%d', squareWave(i));
% if i < depth
% fprintf(fileID, ',\n');
% else
% fprintf(fileID, ';\n');
% end
% end
%
% % 關閉文件
% fclose(fileID);
%
% disp('COE文件生成成功!');%*****************************************sin_wave *******************************%
% % 參數設置
% bitWidth = 14; % 位寬
% depth = 2048; % 深度
% maxValue = 2^bitWidth - 1; % 無符號數的最大值
% offset = maxValue / 2; % 為了將正弦波移動到無符號范圍內
%
% % 生成正弦波
% t = linspace(0, 2 * pi, depth); % 生成一個周期
% sineWave = offset + round((maxValue / 2) * sin