DDS直接數字式頻率合成器(Direct Digital Synthesizer)
下面是使用MATLAB生成正弦波、三角波、方波的代碼,直接使用即可。
1 t=0:2*pi/2^12:2*pi 2 y=0.5*sin(t)+0.5; 3 r=ceil(y*(2^8-1)); %將小數轉換為整數,ceil是向上取整。 4 fid = fopen('sin.coe','w'); %寫到sin.coe文件,用來初始化sin_rom 5 fprintf(fid,'MEMORY_INITIALIZATION_RADIX=10;\n'); 6 fprintf(fid,'MEMORY_INITIALIZATION_VECTOR=\n'); 7 for i = 1:1:2^12 8 fprintf(fid,'%d',r(i)); 9 if i==2^12 10 fprintf(fid,';'); 11 else 12 fprintf(fid,','); 13 end 14 if i%15==0 15 fprintf(fid,'\n'); 16 end 17 end 18 fclose(fid); 19 t=1:1:2^12; 20 y=(t<=2047); 21 r=ceil(y*(2^8-1)); 22 fid = fopen('square.coe','w'); %寫到square.coe,用來初始化rom_square 23 fprintf(fid,'MEMORY_INITIALIZATION_RADIX=10;\n'); 24 fprintf(fid,'MEMORY_INITIALIZATION_VECTOR=\n'); 25 for i = 1:1:2^12 26 fprintf(fid,'%d',r(i)); 27 if i==2^12 28 fprintf(fid,';'); 29 else 30 fprintf(fid,','); 31 end 32 if i%15==0 33 fprintf(fid,'\n'); 34 end 35 end 36 fclose(fid); 37 t=1:1:2^12; 38 y=[0.5:0.5/1024:1-0.5/1024, 1-0.5/1024:-0.5/1024:0, 0.5/1024:0.5/1024:0.5]; 39 r=ceil(y*(2^8-1)); 40 fid = fopen('triangular.coe','w'); %寫到triangular.coe,初始化三角波rom 41 fprintf(fid,'MEMORY_INITIALIZATION_RADIX=10;\n'); 42 fprintf(fid,'MEMORY_INITIALIZATION_VECTOR=\n'); 43 for i = 1:1:2^12 44 fprintf(fid,'%d',r(i)); 45 if i==2^12 46 fprintf(fid,';'); 47 else 48 fprintf(fid,','); 49 end 50 if i%15==0 51 fprintf(fid,'\n'); 52 end 53 end 54 fclose(fid);
設計DDS的核心就是調用IP ROM,vivado調用ROM的方法和ISE相類似,都是加載.coe文件,我這里特地做筆記,以防忘記。
這是DDS的原理圖,DDS並沒有像它的名字一樣說的那么玄乎,它的核心便是控制頻率的fword字輸入,和相位字pword輸入,最后調用IP核查找表即可,代碼也十分簡單,下面給出DDS design代碼。

1 module DDS( 2 input mclk, 3 input rst_n, 4 input [31:0]fword,//frequency control 5 input [11:0]pword,//phase control 6 7 output [9:0]da_data 8 ); 9 10 reg [31:0]r_fword; 11 reg [11:0]r_pword; 12 reg [31:0]fcnt; 13 14 wire [11:0]addr_rom; 15 16 //同步寄存器 17 always @(posedge mclk) 18 begin 19 r_fword <= fword; 20 r_pword <= pword; 21 end 22 23 always @(posedge mclk or negedge rst_n) 24 begin 25 if(!rst_n) 26 fcnt <= 32'd0; 27 else 28 fcnt <= fcnt + r_fword; 29 end 30 31 assign addr_rom = fcnt[31:20] + r_pword; 32 33 //custom sin_rom 34 sin_rom sin_rom ( 35 .clka(mclk), // input wire clka 36 .addra(addr_rom), // input wire [11 : 0] addra 37 .douta(da_data) // output wire [9 : 0] douta 38 ); 39 40 endmodule
使用vivado調用IP核ROM教程如下
點擊IP catalog
選擇block memory,然后雙擊
將show disabled ports 選項勾選掉
輸入ROM名,我這里為了演示重新配置一個方波ROM,命名為square_rom
這里選擇single ports ROM
按如上圖所示勾選參數,port width是數據寬度,我們根據代碼要求設置為10位,
port width是數據深度,即有多少個這樣的數據,我打開生成的square.coe文件可以清楚的看到一共有4096這樣的數據。
always enable是ROM一直處於工作狀態,不需要使能信號。
這里是加載.coe文件,勾選load init file 然后點擊browse將剛才生成的square.coe文件加載到ROM中,最后點擊OK。
選擇generate生成IP核
打開如圖所示文件,
將生成的IP核實例化,即可
最后編寫測試文件進行測試
最后右鍵點擊da_data選擇wave style選擇analog,將會看到模擬波形,但是有時候還是需要設置一下模擬波形的顯示,同樣右鍵點擊da_data選擇wave style選擇analog setting,選擇如下圖所示參數。
最后便大功告成,即可得打方波的波形圖
大家還可以按照這種方法將其他兩種波形都做出來。
轉載請注明出處:NingHeChuan(寧河川)
個人微信訂閱號:NingHeChuan
如果你想及時收到個人撰寫的博文推送,可以掃描左邊二維碼(或者長按識別二維碼)關注個人微信訂閱號
知乎ID:NingHeChuan
微博ID:NingHeChuan