基于FPGA的DDS信号发生器的设计仿真


本文主要介绍利用FPGA和matlab实现任意频率信号发生器的功能,并进行仿真,使用Quartus Ⅱ+modelsim+matlab实现功能,以正弦波为例说明,开发芯片频率50MHz

产生正弦波sin信号的mif文件

采用matlab产生mif文件,具体的代码如下:

clear;
clc;

width=8;
depth=256;

fid =fopen ('sin.mif','w');
fprintf(fid,'WIDTH=%d;\n',width);
fprintf(fid,'DEPTH=%d;\n',depth);
fprintf(fid,'ADDRESS_RADIX=UNS;\n');
fprintf(fid,'DATA_RADIX=UNS;\n');
fprintf(fid,'CONTENT BEGIN\n');


for i=0:depth-1
    sin_data=floor((sin(2*pi*i/depth)+1)*0.5*(2^width-1));
    data=sin_data;
    fprintf(fid,'%d  :  %d;\n',i,data);
end

fprintf(fid,'END;\n');
fclose (fid);

通过运行.m文件可以产生一个sin.mif文件用作rom的初始状态

建立工程并调用ipcore

首先创建工程
在这里插入图片描述
调用单个端口的ROM IPcore,位宽为8,深度为256,RTL视图如下
在这里插入图片描述
顶层文件如下

module	dds_v3(
		input		wire					clk,
		input		wire					rst_n,
		output		wire		[7:0]		wave
);
		wire		[7:0]		addr ;
	roml256x8	roml256x8_inst (
			.address ( addr ),
			.clock 	( clk ),
			.q 		( wave )
	);

	dds_ctrl dds_ctrl_inst(
			.clk(clk),
			.rst_n(rst_n),
			.addr_sin(addr)
);
endmodule

dss_ctrl代码如下

module	dds_ctrl(
	input			wire				clk,
	input			wire				rst_n,
	output			wire	[7:0]		addr_sin
);
	parameter	P_word		=	0;			//xiangwei
	parameter	FREQ		= 123456; 		//f
	
	localparam	[63:0]	F_word = FREQ*(2**32)*20/(10**9);
	reg			[31:0]	cnt;
	assign	addr_sin=cnt[31:24]+P_word;
	always	@(posedge clk)begin
		if(rst_n==1'b0)
			cnt<=32'd0;
		else
			cnt<=cnt+F_word[31:0];
	end
	
endmodule

主要思路

由于开发芯片频率为50MHz,可以知道单个周期的时间为20ns,由于选择的cnt的位宽是32位,所以存满一个周期所需要的时间为
T=2^32✖20ns
f=1/T
f=(10^9) / (2^32✖20)
假设我们一步的步长为F_word,那么
f=F_word✖(10^9) / (2^32✖20)
F_word=f ✖ (2^32) ✖ 20 / (10^9)
我们取cnt寄存器的高8位作为rom的地址,通过对地址的不断读取即可以实现dds功能

仿真

仿真代码如下

`timescale	1ns/1ps
module	dds_v3_tb;
	reg			clk;
	reg			rst_n;
	wire	[7:0]	wave;
	wire	[7:0]	wave1;
	
	defparam	dds_v3_inst1.dds_ctrl_inst.FREQ=123456;
	defparam	dds_v3_inst2.dds_ctrl_inst.FREQ=654321;
	
	
	
	dds_v3 dds_v3_inst1(
		.clk(clk),
		.rst_n(rst_n),
		.wave(wave)
);
	dds_v3 dds_v3_inst2(
		.clk(clk),
		.rst_n(rst_n),
		.wave(wave1)
);
	initial	clk=1'b0;
	always	#10 	clk=~clk;
	initial		begin
		rst_n=1'b0;
		#200;
		@(posedge clk)
		#2;
		rst_n=1'b1;
		
		repeat (20) begin
			while	(wave != 255)
				@(posedge clk);
			while	(wave != 0)
				@(posedge clk);
		end
		#2000;
		$stop;
	end
endmodule

仿真结果

在这里插入图片描述

原创文章 2 获赞 1 访问量 68

猜你喜欢

转载自blog.csdn.net/gouyepeng/article/details/106167358