Matlab与FPGA数字信号处理系列——DDS信号发生器——Quartus ii 原理图法利用 ROM 存储波形实现DDS
本文参考了以上文章
DDS原理
将一个完整的正弦信号,按一定的频率进行采样,量化,进行一个查找表存入ROM中。通过修改ROM中数据的访问步进和初始位置可以控制生成波形的频率和相位。
创建步骤
这里使用了Guagle_wave小工具进行正弦信号的产生,这个工具可以在我们没有Matlab的情况下,快速得生成采样点,但是有个缺陷,就是生成的采样点只能是2的幂次方。
Guagle_wave的使用方法,开头的链接里有说明,不再详述,以下是本次实例的创建步骤
- 使用Guagle_wave生成一个采样深度为512的查找表
- 在Vivado中创建BLOCK RAM IP核,将以上查找表以初始化文件的形式存入ROM中
由于Guagle_wave生成的是mif文件,而vivado只能识别.coe文件,因此对Mif文件按照coe文件的格式,做一点修改,《pg058-blk-mem-gen.pdf》中简单介绍了一些coe格式。 - ROM中存储一个完整的采样波形,采样点数为512,即采样时钟频率与被采样信号频率为512倍关系,与两者绝对频率无关
- 对ROM中的数据依次寻址访问,即可以得到一个完整的波形,循环访问,即得到连续的波形
- 修改寻址步进为2,则可以得到二倍频的波形
工程实现
IP核例化
因为不需要对ROM进行写操作,ROM中的数据是固件在里面的,因此我们只需要例化一个单端口的ROM,这里没有写数据和写使能,只有读数据和地址端口
代码设计
工程比较简单,只用了一层,dds_rom为实例化的8位位宽512深度ROM IP核
addra为rom的地址累加器,step为累加步进。
为了对比,使用了两种累加步进。
module dds_gen(
input clk,
input rst,
input [7:0] addr_step,
output wire [7:0] samp_data1,
output wire [7:0] samp_data2
);
reg [8:0] addra1 = 0;
reg [8:0] addra2 = 0;
always @(posedge clk) begin
addra1 <= addra1 + addr_step;
addra2 <= addra2 + (addr_step<<1);
end
rom_8x512 dds_rom1 (
.clka (clk ),
.addra (addra1 ),
.douta (samp_data1 )
);
rom_8x512 dds_rom2 (
.clka (clk ),
.addra (addra2 ),
.douta (samp_data2 )
);
endmodule
仿真
仿真文件
module dds_gen_tb;
reg clk;
reg rst;
reg [7:0] addr_step;
wire [7:0] samp_data1;
wire [7:0] samp_data2;
initial
begin
rst = 0;
addr_step = 1;
end
initial
begin
clk = 0;
forever
#5 clk = ~clk;
end
dds_gen uut (
.clk (clk ),
.rst (rst ),
.addr_step (addr_step ),
.samp_data1 (samp_data1 ),
.samp_data2 (samp_data2 )
);
endmodule