本文承接以上博主的博客且增添了相位可调节,双通道输出和多种合成波输出的功能,同时通过ILA仿真验证其功能。基于FPGA的DDS在Vivado中仿真以及在ZYNQ7020上板的实现(2)_vivado dds可以在板子里使用嘛_静心.舍得.放下的博客-CSDN博客ILA硬件仿真内容:(详细过程可参考bilibili博主:小梅哥爱漂流 的 Vivado在线调试工具ILA使用教程)
1)点击IP Catalog
2)搜索框内输入ILA,双击如下图所示
3)如图按照如下配置所需
4)跳出如下界面,点击Generate
5)在Sources出现该文件
6)在IP Sources里选择,双击ila_0.veo,打开文件
7)复制此段程序到DDS.v的文件里
8)在DDS中根据需求,例化ILA程序
9)点击Run Synthesis
10)点击Run Implementation
11)运行成功后,点击Genrate Bistream
12)静静等待,点击Auto Connect
13)连接硬件,连接成功后出现
14)点击Program device
15)即可出现波形
相位可调节实现
1)新建文件key_debounce.v文件(按键消抖)
//按键消抖模块
module key_debounce(
input sys_clk ,
input sys_rst_n ,
input key , //外部输入的按键值
output reg key_value , //消抖后的按键值
output reg key_flag //消抖后的按键值的效标志
);
//reg define
reg [19:0] cnt ;
reg key_reg ;
//按键值消抖
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n) begin
cnt <= 20'd0;
key_reg <= 1'b1;
end
else begin
key_reg <= key; //将按键值延迟一拍
if(key_reg != key) begin //如果当前按键值和前一拍的按键值不一样,即按键被按下或松开
cnt <= 20'd100_0000; //则将计数器置为20'd100_0000,
//即延时100_0000 * 20ns(1s/50MHz) = 20ms
end
else begin //如果当前按键值和前一个按键值一样,即按键没有发生变化
if(cnt > 20'd0) //则计数器递减到0
cnt <= cnt - 1'b1;
else
cnt <= 20'd0;
end
end
end
//将消抖后的最终的按键值送出去
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n) begin
key_value <= 1'b1;
key_flag <= 1'b0;
end
//在计数器递减到1时送出按键值
else if(cnt == 20'd1) begin
key_value <= key;
key_flag <= 1'b1;
end
else begin
key_value <= key_value;
key_flag <= 1'b0;
end
end
endmodule
2)新建文件key_control.v文件 (按键控制)
//按键控制模块
module key_control(
input sys_clk , //接时钟
input sys_rst_n, //接复位
input key, //接你的key
output reg led, //可以接一个led来显示你的按键是否成功按下
output reg [1:0] counter //counter 四个状态 接到你自己写的counter就行 四种不同的相位
);
wire key_value ; //key的value信号 可以忽略不管
wire key_flag ; //key的flag信号 可以忽略不管
key_debounce u_key_debounce(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key (key),
.key_value (key_value),
.key_flag (key_flag)
);
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n) //sys_rst_n 按下,复位
begin
led <= 1'b0;
counter<= 2'b00;
end
else begin
if (key_flag && (key_value == 1'b0)) begin
if(counter == 2'b11) begin //counter 四个状态 00 01 10 11
led <= ~led;
counter<= 2'b00;
end
else begin
led <= ~led;
counter <= counter + 1 ;
end
end
end
end
endmodule
3)将DDS.V设置成顶层文件,右击DDS.v
双通道设置和合成波:下面给出DDS文件总代码
module DDS(
input clk,
input key,
input rst_n,
input [1:0] Mode_Sel,
input [1:0] fword_sel,
output DA_clk,
output DB_clk,
output led,
output reg [11:0] Data,
output reg [11:0] Data1
);
reg [31:0] r_fword;
reg [11:0] r_pword;
reg [31:0] cnt;
wire[11:0] rom_addr;
wire[11:0] rom_addr1;
wire[11:0] rom_addr2;
wire[11:0] rom_addr3;
wire[11:0] rom_addr4;
wire [1:0] counter;
key_control key_control(
.sys_clk(clk),
.sys_rst_n(rst_n),
.key(key),
.led(led),
.counter(counter)
) ;
/* reg[1:0] counter=2'b00;
always@(posedge clk or negedge rst_n)begin
if(rst_n)begin
counter<=2'b00;
end else begin
if(counter==3)begin
counter<=0;
end else begin
counter<=counter+1;
end
end
end
ila_0 ila_0 (
.clk(clk), // input wire clk
.probe0(Data_sin[11:4]), // input wire [7:0] probe0
.probe1(Data_square[11:4]), // input wire [7:0] probe1
.probe2(Data_triangular[11:4]), // input wire [7:0] probe2
.probe3(Data_sawtooth_wave[11:4]) // input wire [7:0] probe3
);
*/
always@(*)
begin
if(counter==0) begin
r_pword <= 0;
end
else if(counter==1) begin
r_pword <= 512;
end
else if(counter==2) begin
r_pword <= 1024;
end
else if(counter==3) begin
r_pword <= 2048;
end
end
always@(posedge clk or negedge rst_n)
if(rst_n)
cnt <= 32'd0;
else
cnt <= cnt +r_fword;
assign rom_addr = cnt[31:20] + r_pword;
assign rom_addr1 = cnt[31:20] + r_pword;
assign rom_addr2 = cnt[31:20] + r_pword;
assign rom_addr3 = cnt[31:20] + r_pword;
assign rom_addr4 = cnt[31:20] + r_pword;
assign DA_clk=clk;
assign DB_clk=clk;
//例化不同的波形IP核
wire [11:0]Data_sin,Data_sin1,Data_square,Data_triangular,Data_sawtooth_wave;
sine_wave sine_DDS(
.clka(clk), // input wire clka
.addra(rom_addr), // input wire [11 : 0] addra
.douta(Data_sin) // output wire [11 : 0] douta
);//正弦
triangular_wave triangular_DDS(
.clka(clk), // input wire clka
.addra(rom_addr1), // input wire [11 : 0] addra
.douta(Data_triangular) // output wire [11 : 0] douta
);//三角
square_wave square_DDS(
.clka(clk), // input wire clka
.addra(rom_addr2), // input wire [11 : 0] addra
.douta(Data_square) // output wire [11 : 0] douta
);//方波
sawtooth_wave sawtooth_wave_DDS(
.clka(clk), // input wire clka
.addra(rom_addr3), // input wire [11 : 0] addra
.douta(Data_sawtooth_wave) // output wire [11 : 0] douta
);//锯齿
sine1_DDS sine_DDS1(
.clka(clk), // input wire clka
.addra(rom_addr4), // input wire [11 : 0] addra
.douta(Data_sin1) // output wire [11 : 0] douta
);//幅度改变的正弦
//矩阵混合模块
wire signed [11:0] a11, a12, a21, a22;
assign a11 = 12'h300;
assign a12 = 12'h600;
assign a21 = 12'h400;
assign a22 = 12'h800;
reg signed [23:0] a11s1;
reg signed [23:0] a12s2;
reg signed [23:0] a21s1;
reg signed [23:0] a22s2;
always @(posedge clk or negedge rst_n)begin
if(rst_n)begin
a11s1 <= 'b0;
a12s2 <= 'b0;
a21s1 <= 'b0;
a22s2 <= 'b0;
end
else begin//混合矩阵混合
a11s1 <= a11 * Data_sin;
a12s2 <= a12 * Data_square;
a21s1 <= a21 * Data_sin;
a22s2 <= a22 * Data_triangular;
end
end
reg signed [11:0] wave1;
reg signed [11:0] wave2;
always@(posedge clk or negedge rst_n)begin
if(rst_n)begin
wave1 <= 'b0;
wave2 <= 'b0;
end
else begin
wave1 <= (a11s1 >>> 12) + (a12s2 >>> 12);
wave2 <= (a21s1 >>> 12) + (a22s2 >>> 12);
end
end
//矩阵混合模块
wire signed [11:0] b11, b12, b21, b22;
assign b11 = 12'h300;
assign b12 = 12'h600;
assign b21 = 12'h100;
assign b22 = 12'h800;
reg signed [23:0] b11s1;
reg signed [23:0] b12s2;
reg signed [23:0] b21s1;
reg signed [23:0] b22s2;
always @(posedge clk or negedge rst_n)begin
if(rst_n)begin
b11s1 <= 'b0;
b12s2 <= 'b0;
b21s1 <= 'b0;
b22s2 <= 'b0;
end
else begin//混合矩阵混合
b11s1 <= b11 * Data_triangular;
b12s2 <= b12 * Data_sawtooth_wave;
b21s1 <= b21 * Data_triangular;
b22s2 <= b22 * Data_sawtooth_wave;
end
end
reg signed [11:0] wave3;
reg signed [11:0] wave4;
always@(posedge clk or negedge rst_n)begin
if(rst_n)begin
wave3 <= 'b0;
wave4 <= 'b0;
end
else begin
wave3 <= (b11s1 >>> 12) + (b12s2 >>> 12);
wave4 <= (b21s1 >>> 12) - (b22s2 >>> 12);
end
end
//频率的切换
always@(*)
case(fword_sel)
0:r_fword=8590;//250HZ
1:r_fword=85899;//2500HZ
2:r_fword=858993;//25KHZ
3:r_fword=8589935;//250KHZ
endcase
//波形的切换
always@(*)
case(Mode_Sel)
0:begin
Data=Data_sin;
Data1=Data_square;
end//正弦波和方波
1:begin
Data=Data_triangular;
Data1=Data_sawtooth_wave;
end//三角波和锯齿波
2:begin
Data=wave1;
Data1=wave2;
end//wave1:正弦波和方波的混合;wave2:正弦和三角波的混合
3:begin
Data=wave3;
Data1=wave4;
end//三角波和锯齿的混合
endcase
endmodule
管脚约束文件XDC改为以下内容
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property PACKAGE_PIN K17 [get_ports clk]
set_property PACKAGE_PIN Y16 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports DA_clk]
set_property PACKAGE_PIN V8 [get_ports DA_clk]
set_property IOSTANDARD LVCMOS33 [get_ports {Mode_Sel[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Mode_Sel[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data[11]}]
set_property PACKAGE_PIN V15 [get_ports {Data[11]}]
set_property PACKAGE_PIN W15 [get_ports {Data[10]}]
set_property PACKAGE_PIN T11 [get_ports {Data[9]}]
set_property PACKAGE_PIN T10 [get_ports {Data[8]}]
set_property PACKAGE_PIN W14 [get_ports {Data[7]}]
set_property PACKAGE_PIN Y14 [get_ports {Data[6]}]
set_property PACKAGE_PIN T12 [get_ports {Data[5]}]
set_property PACKAGE_PIN U12 [get_ports {Data[4]}]
set_property PACKAGE_PIN G15 [get_ports {Mode_Sel[1]}]
set_property PACKAGE_PIN P15 [get_ports {Mode_Sel[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {fword_sel[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {fword_sel[0]}]
set_property PACKAGE_PIN W13 [get_ports {fword_sel[1]}]
set_property PACKAGE_PIN T16 [get_ports {fword_sel[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Data1[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports DB_clk]
set_property PACKAGE_PIN W8 [get_ports DB_clk]
set_property PACKAGE_PIN T14 [get_ports {Data1[11]}]
set_property PACKAGE_PIN T15 [get_ports {Data1[10]}]
set_property PACKAGE_PIN P14 [get_ports {Data1[9]}]
set_property PACKAGE_PIN R14 [get_ports {Data1[8]}]
set_property PACKAGE_PIN U14 [get_ports {Data1[7]}]
set_property PACKAGE_PIN U15 [get_ports {Data1[6]}]
set_property PACKAGE_PIN V17 [get_ports {Data1[5]}]
set_property PACKAGE_PIN V18 [get_ports {Data1[4]}]
#set_property PACKAGE_PIN K19 [get_ports rword1]
#set_property PACKAGE_PIN P16 [get_ports rword2]
#set_property PACKAGE_PIN K18 [get_ports rword3]
#set_property IOSTANDARD LVCMOS33 [get_ports rword1]
#set_property IOSTANDARD LVCMOS33 [get_ports rword2]
#set_property IOSTANDARD LVCMOS33 [get_ports rword3]
set_property IOSTANDARD LVCMOS33 [get_ports key]
set_property IOSTANDARD LVCMOS33 [get_ports led]
set_property PACKAGE_PIN K19 [get_ports key]
set_property PACKAGE_PIN M14 [get_ports led]
运行结果展示
250HZ频率展示:
2.5KHZ频率展示:
硬件展示