1.编写MATLB代码 生成ROM的数据
clc;
clear;
F1=1; %信号频率
Fs=2^12; %采样频率
P1=0; %信号初始相位
N=2^12; %采样点数
t=[0:1/Fs:(N-1)/Fs]; %采样时刻
ADC=2^7 - 1; %直流分量
A=2^7; %信号幅度
s1=A*sin(2*pi*F1*t + pi*P1/180) + ADC; %正弦波信号
s2=A*square(2*pi*F1*t + pi*P1/180) + ADC; %方波信号
s3=A*sawtooth(2*pi*F1*t + pi*P1/180,0.5) + ADC; %三角波信号
s4=A*sawtooth(2*pi*F1*t + pi*P1/180) + ADC; %锯齿波信号
%创建mif文件
fild = fopen('rom_wave.mif','wt');
%写入mif文件头
fprintf(fild, '%s\n','WIDTH=8;'); %位宽
fprintf(fild, '%s\n\n','DEPTH=16384;'); %深度
fprintf(fild, '%s\n','ADDRESS_RADIX=UNS;'); %地址格式
fprintf(fild, '%s\n\n','DATA_RADIX=UNS;'); %数据格式
fprintf(fild, '%s\t','CONTENT'); %地址
fprintf(fild, '%s\n','BEGIN'); %开始
for j = 1:4
for i = 1:N
if j == 1 %打印正弦信号数据
s0(i) = round(s1(i)); %对小数四舍五入以取整
fprintf(fild, '\t%g\t',i-1); %地址编码
end
if j == 2 %打印方波信号数据
s0(i) = round(s2(i)); %对小数四舍五入以取整
fprintf(fild, '\t%g\t',i-1+N); %地址编码
end
if j == 3 %打印三角波信号数据
s0(i) = round(s3(i)); %对小数四舍五入以取整
fprintf(fild, '\t%g\t',i-1+(2*N)); %地址编码
end
if j == 4 %打印锯齿波信号数据
s0(i) = round(s4(i)); %对小数四舍五入以取整
fprintf(fild, '\t%g\t',i-1+(3*N)); %地址编码
end
if s0(i) <0 %负1强制置零
s0(i) = 0
end
fprintf(fild, '%s\t',':'); %冒号
fprintf(fild, '%d',s0(i)); %数据写入
fprintf(fild, '%s\n',';'); %分号,换行
end
end
fprintf(fild, '%s\n','END;'); %结束
fclose(fild);
2.添加IP核并例化
rom_wave rom_wave_inst
(
.address (rom_addr ), //ROM读地址
.clock (sys_clk ), //读时钟
.q (dac_data ) //读出波形数据
3.编写DDS_Multi代码
/********************************************************************************
名称 :DDS_Multi.v
功能:四种DDS 波形发生器
作者:王世阳
创建日期:2021.04.25
修改日期1:
修改内容1:
*********************************************************************************/
module DDS_Multi
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [3:0] key ,
output wire dac_clk ,
output wire [7:0] dac_data
);
//DAC模块时钟
assign dac_clk = ~sys_clk;
parameter sin_wave = 4'b0001 ,
squ_wave = 4'b0010 ,
tri_wave = 4'b0100 ,
saw_wave = 4'b1000 ;
parameter FREQ_CTRL = 32'd42949 , //相位累加器单次累加值
PHASE_CTRL = 12'd1024 ; //相位偏移量
reg [31:0] fre_add ;
reg [11:0] rom_addr_reg;
reg [13:0] rom_addr ;
//fre_add:相位累加器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
fre_add <= 32'd0;
else
fre_add <= fre_add + FREQ_CTRL;
//rom_addr:ROM读地址
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
rom_addr <= 14'd0;
rom_addr_reg <= 11'd0;
end
else
case(key)
sin_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg;
end //正弦波
squ_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd4096;
end //方波
tri_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd8192;
end //三角波
saw_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd12288;
end //锯齿波
default:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg;
end //正弦波
endcase
rom_wave rom_wave_inst
(
.address (rom_addr ), //ROM读地址
.clock (sys_clk ), //读时钟
.q (dac_data ) //读出波形数据
);
endmodule
4.编写测试文件
`timescale 1ps/1ps
module tb_DDS_Multi();
wire dac_clk ;
wire [7:0] dac_data ;
reg sys_clk ;
reg sys_rst_n ;
reg [3:0] key ;
initial
begin
sys_clk = 1'b0;
sys_rst_n <= 1'b0;
key <= 4'b0001; //选择正弦波
#200;
sys_rst_n <= 1'b1;
end
always #10 sys_clk = ~sys_clk;
DDS_Multi DDS_Multi_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.key (key ),
.dac_clk (dac_clk ),
.dac_data (dac_data )
);
endmodule