目录

dds信号发生

 wave_set(波形选择)

 key_filter(按键消抖)

amplitude_set(幅值控制) 

f_word_set(频率设置)

 dds_top(顶层文件)

引脚配置xdc 

ILA逻辑分析仪

上板验证


DDS即直接数字频率合成(Direct Digital Synthesis)以下是dds实现的基本原理

 

dds信号发生

(coe文件由matlab或软件生成,此处波形数据为14bit,深度为4096)

 
// 14位dds信号发生器 
 
module dds(
	input				clk			,
	input				rst_n		,
	input		[31:0]	f_word		,    //频率设置
	input		[1:0]	wave_c		,    //波形选择
	input		[13:0]	p_word		,     //相位偏移量--------------->控制相位---------pi/2对应1024
	input		[4:0]	amplitude	,    //幅值控制
	output	reg	[13:0]	dac_data	
);
 
localparam	DATA_WIDTH = 4'd14;   //DAC数据位宽
localparam	ADDR_WIDTH = 4'd12;   //ROM地址位宽
 
reg		[ADDR_WIDTH - 1 :0]	addr	 ;
 
wire	[DATA_WIDTH - 1 :0]	dac_data0;
wire	[DATA_WIDTH - 1 :0]	dac_data1;
wire	[DATA_WIDTH - 1 :0]	dac_data2;
wire	[DATA_WIDTH - 1 :0]	dac_data3;
//波形选择
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dac_data <= 14'd0;
	end
	else begin
		case(wave_c)
			2'b00:dac_data <= (dac_data0>14'd8192)?14'd8192+(dac_data0-14'd8192)/amplitude:14'd8192-(14'd8192-dac_data0)/amplitude;	//正弦波
			2'b01:dac_data <= (dac_data1>14'd8192)?14'd8192+(dac_data1-14'd8192)/amplitude:14'd8192-(14'd8192-dac_data1)/amplitude;	//三角波
			2'b10:dac_data <= (dac_data2>14'd8192)?14'd8192+(dac_data2-14'd8192)/amplitude:14'd8192-(14'd8192-dac_data2)/amplitude;	//锯齿波
			2'b11:dac_data <= (dac_data3>14'd8192)?14'd8192+(dac_data3-14'd8192)/amplitude:14'd8192-(14'd8192-dac_data3)/amplitude;	//方波
			default:;
		endcase
	end
end
//相位累加器
reg	[31:0]	fre_acc;
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		fre_acc <= 0;
	end
	else begin
		fre_acc <= fre_acc + f_word;
	end
end
//生成查找表地址
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		addr <= 0;
	end
	else begin
			addr <= fre_acc[31:20] + p_word;
 
	end
end
 
//正弦波
sine_wave_rom sine_wave_rom_inst 
(
    .clka(clk),
	.addra(addr),
	.douta(dac_data0)
);
 
//三角波
triangular_wave_rom triangular_wave_rom_inst
(
    .clka(clk),
	.addra(addr),
	.douta(dac_data1)
);
 
//锯齿波
sawtooth_wave_rom sawtooth_wave_rom_inst
(
    .clka(clk),
	.addra(addr),
	.douta(dac_data2)
);
 
//方波
square_wave_rom square_wave_rom_inst
(
    .clka(clk),
	.addra(addr),
	.douta(dac_data3)
);
 
// ----------50Mhz时的频率字对应频率----------- 
// 			4'd0:f_word = 32'd86;		//1Hz
// 			4'd1:f_word = 32'd859;		//10Hz
// 			4'd2:f_word = 32'd8590;		//100Hz
// 			4'd3:f_word = 32'd42950;	//500Hz
// 			4'd4:f_word = 32'd85899;	//1kHz
// 			4'd5:f_word = 32'd429497;	//5kHz
// 			4'd6:f_word = 32'd858993;	//10kHz
// 			4'd7:f_word = 32'd4294967;	//50kHz
// 			4'd8:f_word = 32'd8589935;	//100kHz
// 			4'd9:f_word = 32'd17179869;	//200kHz
// 			4'd10:f_word = 32'd42949673;//500kHz
// 			4'd11:f_word = 32'd85899345;//1MHz
// 			4'd12:f_word = 32'd171798691;//2MHz
// 			4'd13:f_word = 32'd429496729;//5MHz
// 			4'd14:f_word = 32'd858993459;//10MHz
 
endmodule
 wave_set(波形选择)
`timescale 1ns / 1ps

 
module wave_set(
	input				clk		,
	input				rst_n	,
	input				key0_in	,
	output	reg	[1:0]	wave_c		//wave_c 00~正弦波  01~三角波  10~锯齿波  11~方波
);
 
wire key_flag;


//按键步进,控制波形
always @(posedge clk or negedge rst_n) begin
	if (~rst_n)
		wave_c <= 0; //默认正弦波
	else if (key_flag)
		wave_c <= wave_c + 1'b1;
end

//按键消抖模块例化
key_filter #(
    .CNT_MAX(20'd24)
)
key_filter_inst_0
(
    .clk(clk),
    .rst_n(rst_n),
    .key_in(key0_in),
    .key_flag(key_flag)
);
endmodule
 key_filter(按键消抖)
`timescale 1ns / 1ps



module key_filter
#(
parameter CNT_MAX = 20'd999_999   //计数器的最大值
)
(
	input wire clk,         //系统时钟50Mhz
	input wire rst_n,       //全局复位按键
	input wire key_in,          //按键输入信号
		
	output reg key_flag         //key_flag=1时表示消抖后检测到按键按下   =0表示没有检测到案件爱你按下
);
		


reg [19:0] cnt_20ms;            //计数器



//时钟的上升沿如果检测到外部按键输入值为高电平,就开始计数
always@(posedge clk or negedge rst_n) begin
	if(rst_n == 1'b0) //复位按键按下
	    cnt_20ms <=20'b0;
	else if(key_in == 1'b1) //如果检测到高电平
	    cnt_20ms <=20'b0;
	else if(cnt_20ms ==CNT_MAX && key_in == 1'b0)
	    cnt_20ms <= cnt_20ms;
	else 
	    cnt_20ms <=cnt_20ms + 1'b1;
end	
	
		
//key_flag:计数满20ms后产生按键有效标志位
always@(posedge clk or negedge rst_n) begin
	if(rst_n == 1'b0)
	    key_flag <=1'b0;
	else if(cnt_20ms == CNT_MAX -1'b1)
	    key_flag <= 1'b1;
	else 
	    key_flag <= 1'b0;
end

endmodule
amplitude_set(幅值控制) 

1/2、1/4/、1/8、1/16

`timescale 1ns / 1ps
 
//信号电压幅度设置 1/2/4/8/16分之一
module amplitude_set(
	input				clk		,
	input				rst_n	,
	input				key2_in	,
	output	reg	[4:0]	amplitude	
);

reg	[2:0]	cnt;
wire key_flag;

always @(posedge clk or negedge rst_n) begin
	if (~rst_n)
		cnt <= 3'd0;
	else if (key_flag) begin
		if (cnt == 3'd4) 
			cnt <= 3'd0;
		else 
			cnt <= cnt + 1'b1;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) 
		amplitude <= 0;			
	else begin
		case(cnt)
			3'd0: amplitude <= 5'd1;
			3'd1: amplitude <= 5'd2;
			3'd2: amplitude <= 5'd4;
			3'd3: amplitude <= 5'd8;
			3'd4: amplitude <= 5'd16;
			default:amplitude <= 5'd1;
		endcase
	end
end



//按键消抖模块例化
key_filter #(
    .CNT_MAX(20'd24)
)
key_filter_inst_2
(
    .clk(clk),
    .rst_n(rst_n),
    .key_in(key2_in),
    .key_flag(key_flag)
);
endmodule
f_word_set(频率设置)
`timescale 1ns / 1ps
 
module f_word_set(
	input				clk		,
	input				rst_n	,
	input				key1_in	,
	output	reg	[31:0]	f_word	
);
	
wire		key_flag	;
reg	[3:0]	cnt			;


key_filter #(
    .CNT_MAX(20'd24)
)
key_filter_inst_1
(
    .clk(clk),
    .rst_n(rst_n),
    .key_in(key1_in),
    .key_flag(key_flag)
);

always @(posedge clk or negedge rst_n) begin
	if (~rst_n)
		cnt <= 4'd0;
	else if (key_flag) begin
		if(cnt==4'd15) 
			cnt <= 4'd0;
		else
			cnt <= cnt + 1'b1;
	end
end

//	200Mhz时钟下的频率设置
always @(posedge clk or negedge rst_n) begin
	if (!rst_n) begin
		f_word <= 0;
	end
	else begin
		case(cnt)
			4'd0: f_word = 32'd21;		//1Hz
			4'd1: f_word = 32'd215;		//10Hz
			4'd2: f_word = 32'd2147;		//100Hz
			4'd3: f_word = 32'd10737;	//500Hz
			4'd4: f_word = 32'd21475;	//1kHz
			4'd5: f_word = 32'd107374;	//5kHz
			4'd6: f_word = 32'd214748;	//10kHz
			4'd7: f_word = 32'd1073742;	//50kHz
			4'd8: f_word = 32'd2147484;	//100kHz
			4'd9: f_word = 32'd4294967;	//200kHz
			4'd10:f_word = 32'd10737418;//500kHz
			4'd11:f_word = 32'd21474836;//1MHz
			4'd12:f_word = 32'd42949673;//2MHz
			4'd13:f_word = 32'd107374182;//5MHz
		    // 在200M下,失真比较大
			4'd14:f_word = 32'd214748365;//10MHz  
			4'd15:f_word = 32'd429496730;//20MHz
			default:;
		endcase
	end
end

// //	500Mhz时钟下的频率设置((时钟频率太高了,感觉不稳定)
// always @(posedge clk or negedge rst_n) begin
// 	if (!rst_n) begin
// 		f_word <= 0;
// 	end
// 	else begin
// 		case(cnt)
// 			4'd0:f_word = 32'd9;		//1Hz
// 			4'd1:f_word = 32'd86;		//10Hz
// 			4'd2:f_word = 32'd859;		//100Hz
// 			4'd3:f_word = 32'd4295;	//500Hz
// 			4'd4:f_word = 32'd8590;	//1kHz
// 			4'd5:f_word = 32'd42950;	//5kHz
// 			4'd6:f_word = 32'd85899;	//10kHz
// 			4'd7:f_word = 32'd429497;	//50kHz
// 			4'd8:f_word = 32'd858994;	//100kHz
// 			4'd9:f_word = 32'd1717987;	//200kHz
// 			4'd10:f_word = 32'd4294967;//500kHz
// 			4'd11:f_word = 32'd8589935;//1MHz
// 			4'd12:f_word = 32'd17179869;//2MHz
// 			4'd13:f_word = 32'd42949673;//5MHz
// 			4'd14:f_word = 32'd85899346;//10MHz
// 			4'd15:f_word = 32'd171798692;//20MHz
// 			default:;
// 		endcase
// 	end
// end

//    50Mhz时钟下的频率设置

// always @(posedge clk or negedge rst_n) begin
// 	if (!rst_n) begin
// 		f_word <= 0;
// 	end
// 	else begin
// 		case(cnt)
// 			4'd0:f_word = 32'd86;		//1Hz
// 			4'd1:f_word = 32'd859/;		//10Hz
// 			4'd2:f_word = 32'd8590;		//100Hz
// 			4'd3:f_word = 32'd42950;	//500Hz
// 			4'd4:f_word = 32'd85899;	//1kHz
// 			4'd5:f_word = 32'd429497;	//5kHz
// 			4'd6:f_word = 32'd858993;	//10kHz
// 			4'd7:f_word = 32'd4294967;	//50kHz
// 			4'd8:f_word = 32'd8589935;	//100kHz
// 			4'd9:f_word = 32'd17179869;	//200kHz
// 			4'd10:f_word = 32'd42949673;//500kHz
// 			4'd11:f_word = 32'd85899345;//1MHz
// 			4'd12:f_word = 32'd171798691;//2MHz
// 			4'd13:f_word = 32'd429496729;//5MHz
// 			4'd14:f_word = 32'd858993459;//10MHz
// 			4'd15:f_word = 32'd1717986918;//20MHz
// 			default:;
// 		endcase
// 	end
// end




endmodule
 dds_top(顶层文件)
`timescale 1ns / 1ps
 
 
module dds_top(
	input					clk			,
	input					rst_n		,
	input					key0_in		,   //波形选择
	input					key1_in		,   //频率控制
	//input					key2_in		,   //幅值控制
	output                  dac_clk     ,   //DAC时钟
	output	wire	[13:0]	dac_data	                 // 14位DAC输出
);
 
wire	[1:0]	wave_c		;   //波形选择
wire	[31:0]	f_word		;   //频率字
wire	[4:0]	amplitude	;   //幅值控制

wire locked;
wire clk_500m;
wire clk_200m;



dds dds_inst
(
	.clk      (clk_200m),
	.rst_n    (rst_n),
	.f_word   (f_word),
	.wave_c   (wave_c),
	.p_word   (14'd0),
	.amplitude(1'b1),
	.dac_data (dac_data)
);
 
assign dac_clk = clk;

f_word_set f_word_set_inst 
(
	.clk(clk_200m), 
	.rst_n(rst_n), 
	.key1_in(key1_in), 
	.f_word(f_word)
);

wave_set wave_set_inst
(
	.clk(clk), 
	.rst_n(rst_n), 
	.key0_in(key0_in), 
	.wave_c(wave_c)
);
 
// amplitude_set amplitude_set_inst(
// 	.clk	(clk)		,
// 	.rst_n	(rst_n)		,
// 	.key2_in(key2_in)	,
 
// 	.amplitude(amplitude)	
// );

ila_0 ila_0_inst(
	.clk(clk),
	.probe0(f_word),
	.probe1(wave_c),
	.probe2(dac_data)
);


clock_0 clock_0_inst(
	//.clk_20m(dac_clk),
	//.clk_500m(clk_500m),
	.clk_200m(clk_200m),
	.resetn(rst_n),
	.locked(locked),

	.clk_in1(clk)
);


 
endmodule
引脚配置xdc 
set_property PACKAGE_PIN J19 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports key0_in]
set_property IOSTANDARD LVCMOS33 [get_ports key1_in]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[11]}]
set_property PACKAGE_PIN AA1 [get_ports key0_in]
set_property PACKAGE_PIN W1 [get_ports key1_in]
set_property PACKAGE_PIN L18 [get_ports rst_n]
set_property PACKAGE_PIN N17 [get_ports {dac_data[13]}]
set_property PACKAGE_PIN P17 [get_ports {dac_data[12]}]
set_property PACKAGE_PIN P19 [get_ports {dac_data[11]}]
set_property PACKAGE_PIN R19 [get_ports {dac_data[10]}]
set_property PACKAGE_PIN R18 [get_ports {dac_data[9]}]
set_property PACKAGE_PIN T18 [get_ports {dac_data[8]}]
set_property PACKAGE_PIN T21 [get_ports {dac_data[7]}]
set_property PACKAGE_PIN U21 [get_ports {dac_data[6]}]
set_property PACKAGE_PIN U22 [get_ports {dac_data[5]}]
set_property PACKAGE_PIN V22 [get_ports {dac_data[4]}]
set_property PACKAGE_PIN Y21 [get_ports {dac_data[3]}]
set_property PACKAGE_PIN Y22 [get_ports {dac_data[2]}]
set_property PACKAGE_PIN AA20 [get_ports {dac_data[1]}]
set_property PACKAGE_PIN AA21 [get_ports {dac_data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[0]}]

set_property IOSTANDARD LVCMOS33 [get_ports {dac_clk}]
set_property PACKAGE_PIN W22 [get_ports {dac_clk}]
ILA逻辑分析仪

 

上板验证

通过按键控制波形

输出10Mhz正弦波

参考资料:基于FPGA的DDS信号发生器设计(频率、幅度、波形可调)

更多推荐