fpga模块(3)verilog实现14位dds信号发生器+DAC模块波形输出
·
目录
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正弦波

更多推荐



所有评论(0)