基於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

仿真結果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章