基于FPGA的DDS信号发生器

之前的博客讲到了DDS的基本原理,现在用Verilog代码实现DDS,能够产生四种波形,方波,三角波,正弦波,锯齿波,用按键来控制频率和选择波形。其中按键消抖模块来自小梅哥的FPGA自学笔记设计与验证这本书,产生波形的数据可以借助matlab或者mif小精灵这个软件来生成,将产生的数据存储到ROM中,按照一定的地址读出ROM中的数据,将读出的数据按照一定的时序送给DAC,不同的DAC时序不一样,可参照相关的数据手册。

module DDS_Module(
	Clk,
	Rst_n,
	EN,
	Fword,
	Key1,
	Pword,
	DA_Clk,
	DA_Data
);
  
	input Clk;/*系统时钟*/
	input Rst_n;/*系统复位*/
	input EN;/*DDS模块使能*/
	input Key1;
	input [31:0]Fword;/*频率控制字*/
	input [11:0]Pword;/*相位控制字*/
	
	output DA_Clk;/*DA数据输出时钟*/
	output reg [13:0]DA_Data;/*D输出输出A*/
	
	reg [31:0]Fre_acc;	
	reg [13:0]Rom_Addr;
   reg [1:0] wave_sel;
   wire [13:0]DA_Data1;
	wire [13:0]DA_Data2;
	wire [13:0]DA_Data3;
	wire [13:0]DA_Data4;
   wire  key_flag,key_state;
	
	
	key_filter key_filter1(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.key_in(Key1),
		.key_flag(key_flag),
		.key_state(key_state)
	);
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		wave_sel <= 2'b0;
	else if(key_flag && (!key_state))
		wave_sel <= wave_sel + 1'b1;
	else
		wave_sel <= wave_sel;
		
	always@(*)begin
		case(wave_sel)
			0:  DA_Data <= DA_Data1;  //选择正弦波	
            1:  DA_Data <= DA_Data2;  //选择方波
			2:  DA_Data <= DA_Data3;  //选择三角波
			3:  DA_Data <= DA_Data4;  //选择锯齿波
			default: DA_Data <= DA_Data1;
		endcase
	end
	

/*---------------相位累加器------------------*/	
	always @(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Fre_acc <= 32'd0;
	else if(!EN)
		Fre_acc <= 32'd0;	
	else 
		Fre_acc <= Fre_acc + Fword;

/*----------生成查找表地址---------------------*/		
	always @(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Rom_Addr <= 14'd0;
	else if(!EN)
		Rom_Addr <= 14'd0;
	else
		Rom_Addr <= Fre_acc[31:18] + Pword;	

/*----------例化查找表ROM-------*/
   	
 	ddsrom ddsrom(
		.address(Rom_Addr),
		.clock(Clk),
		.q(DA_Data1)
	);
	
   fangbo fangbo(
		.address(Rom_Addr),
		.clock(Clk),
		.q(DA_Data2)
	);
	 /*
	  sanjian sanjiao(
		.address(Rom_Addr),
		.clock(Clk),
		.q(DA_Data3)
	);
	*/
	/*
	  juchi juchi(
		.address(Rom_Addr),
		.clock(Clk),
		.q(DA_Data4)
	);
   */
/*----------输出DA时钟----------*/
	assign DA_Clk = (EN)?Clk:1'b1;
endmodule
//按键消抖模块
module key_filter(
			Clk,      //50M时钟输入
			Rst_n,    //模块复位
			key_in,   //按键输入
			key_flag, //按键标志信号
			key_state //按键状态信号
		);
   
	input Clk;
	input Rst_n;
	input key_in;
	
	output reg key_flag;
	output reg key_state;
	
	localparam
		IDEL		= 4'b0001,
		FILTER0	= 4'b0010,
		DOWN		= 4'b0100,
		FILTER1 	= 4'b1000;
		
	reg [3:0]state;
	reg [19:0]cnt;
	reg en_cnt;	//使能计数寄存器
	
//对外部输入的异步信号进行同步处理
	reg key_in_sa,key_in_sb;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		key_in_sa <= 1'b0;
		key_in_sb <= 1'b0;
	end
	else begin
		key_in_sa <= key_in;
		key_in_sb <= key_in_sa;	
	end
	
	reg key_tmpa,key_tmpb;
	wire pedge,nedge;
	reg cnt_full;//计数满标志信号
	
//使用D触发器存储两个相邻时钟上升沿时外部输入信号(已经同步到系统时钟域中)的电平状态
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		key_tmpa <= 1'b0;
		key_tmpb <= 1'b0;
	end
	else begin
		key_tmpa <= key_in_sb;
		key_tmpb <= key_tmpa;	
	end

//产生跳变沿信号	
	assign nedge = !key_tmpa & key_tmpb;
	assign pedge = key_tmpa & (!key_tmpb);
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		en_cnt <= 1'b0;
		state <= IDEL;
		key_flag <= 1'b0;
		key_state <= 1'b1;
	end
	else begin
		case(state)
			IDEL :
				begin
					key_flag <= 1'b0;
					if(nedge)begin
						state <= FILTER0;
						en_cnt <= 1'b1;
					end
					else
						state <= IDEL;
				end
					
			FILTER0:
				if(cnt_full)begin
					key_flag <= 1'b1;
					key_state <= 1'b0;
					en_cnt <= 1'b0;
					state <= DOWN;
				end
				else if(pedge)begin
					state <= IDEL;
					en_cnt <= 1'b0;
				end
				else
					state <= FILTER0;
					
			DOWN:
				begin
					key_flag <= 1'b0;
					if(pedge)begin
						state <= FILTER1;
						en_cnt <= 1'b1;
					end
					else
						state <= DOWN;
				end
			
			FILTER1:
				if(cnt_full)begin
					key_flag <= 1'b1;
					key_state <= 1'b1;
					state <= IDEL;
					en_cnt <= 1'b0;
				end
				else if(nedge)begin
					en_cnt <= 1'b0;
					state <= DOWN;
				end
				else
					state <= FILTER1;
			
			default:
				begin 
					state <= IDEL; 
					en_cnt <= 1'b0;		
					key_flag <= 1'b0;
					key_state <= 1'b1;
				end
				
		endcase	
	end
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		cnt <= 20'd0;
	else if(en_cnt)
		cnt <= cnt + 1'b1;
	else
		cnt <= 20'd0;
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		cnt_full <= 1'b0;
	else if(cnt == 20'd999_999)
		cnt_full <= 1'b1;
	else
		cnt_full <= 1'b0;	

endmodule

//DDS顶层模块
module DDS_top(
	input CLK50M, 
	input Rst_n,
	input Key,
	input Key1,
	output [3:0]led,
	
	output DACA_CLK,
	output DACB_CLK,
	output DACA_WRT,
	output DACB_WRT,
	output [13:0]DAC_DATA1,
	output [13:0]DAC_DATA2
);

	wire D_CLK;
	
	assign DACA_CLK = D_CLK;
	assign DACB_CLK = D_CLK;
	
	assign DACA_WRT = D_CLK;
	assign DACB_WRT = D_CLK;
	assign DAC_DATA2 = DAC_DATA1;

	pll pll(
		.inclk0(CLK50M),
		.c0(D_CLK)
	);

	wire [31:0]Fword;
	wire [3:0]Fword_sel;

	DDS_Module DDS_Module0(
		.Clk(D_CLK),
		.Rst_n(Rst_n),
		.Key1(Key1),
		.EN(1),
		.Fword(Fword),
		.Pword(0),
		.DA_Clk(),
		.DA_Data(DAC_DATA1)
	);
	
	Fword_Set Fword_Set(
		.Clk(CLK50M),
		.Rst_n(Rst_n),
		.Key(Key),
		.Fword(Fword),
		.Fword_sel(Fword_sel)
	);
	
	assign led = ~Fword_sel;
	
endmodule

//频率设置模块
module Fword_Set(
	Clk,
	Rst_n,
	Key,
	Fword,
	Fword_sel
);
	input Clk;
	input Rst_n;
	input Key;
	output reg[31:0]Fword;
	output reg[3:0]Fword_sel;
	
	wire key_flag, key_state;
	
	key_filter key_filter0(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.key_in(Key),
		.key_flag(key_flag),
		.key_state(key_state)
	);
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Fword_sel <= 4'd0;
	else if(key_flag && (!key_state))
		Fword_sel <= Fword_sel + 1'b1;
	else
		Fword_sel <= Fword_sel;
		
	always@(*)begin
		case(Fword_sel)
			0:  Fword <= 344;	//10Hz
			1:  Fword <= 1718;	//50Hz
			2:  Fword <= 3436;	//100Hz
			3:  Fword <= 17180;	//500Hz
			4:  Fword <= 34360;	//1KHz
			5:  Fword <= 171799;	//5KHz
			6:  Fword <= 343597;	//10KHz
			7:  Fword <= 1717987;	//50KHz
			8:  Fword <= 3435974;	//100KHz
			9:  Fword <= 17179869;	//500KHz
			10: Fword <= 34359738;	//1MHz
			11: Fword <= 68719477;	//2MHz
			12: Fword <= 103079215;	//3MHz
			13: Fword <= 137438953;	//4MHz
			14: Fword <= 171798692;	//5MHz
			15: Fword <= 343597384;	//10MHz
		endcase
	end
endmodule        

  • 21
    点赞
  • 236
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值