1、端口变量声明
module DDS(
input wire clk,
input wire rst_n,
input wire key_f,
input wire key_s,
input wire key_p,
output wire [16:0] wave_data
);
parameter SINE = 4'b0001;
parameter FANGBO = 4'b0010;
parameter SANJIAO = 4'b0100;
parameter JUCHI = 4'b1000;
reg [15:0] AM_ctrl='d400; //控制幅度的参数
reg [31:0] phase_ctrl=429496729/500000;//控制频率的步进
reg [31:0] phase_data; //用于控制当前波形频率,受到按键key_f控制
reg [6:0] M ; //用于控制占空比,受到按键key_p控制
reg [3:0] state; //四个状态切换,受按键key_s控制
reg [31:0] phase_data_1;
reg key_f_n;
reg key_s_n;
reg key_p_n;
reg [31:0] cnt;
reg [31:0] cnt_1;
reg phase_valid =1;
reg [15:0] sine_buchang='d32766;
reg [15:0] fangbo_data; //方波信号
wire signed [15:0] sine_data_signed;
wire [15:0] sine_data; //正弦波
wire [15:0] sanjiao_data; //三角波
wire [15:0] juchi_data; //锯齿波
wire data_valid;
wire s_axis_divisor_tvalid= 'd1;
wire s_axis_dividend_tvalid= 'd1;
wire m_axis_dout_tvalid;
wire [63:0] zhankong_ctrl;
wire [31:0] zhankong=42949673;
wire [63:0] zhangkong_ctrl_n;
wire [32:0] fuzhi;
wire [16:0] fuzhi_data=AM_ctrl+16'd1;
2、打拍操作,用于识别按键按下状态
always @(posedge clk ) begin
key_f_n<=key_f;
end
always @(posedge clk ) begin
key_s_n<=key_s;
end
always @(posedge clk ) begin
key_p_n<=key_p;
end
3、按键按下,频率增加一个phase_ctrl
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
phase_data <= phase_ctrl;
end
else if (key_f=='d1 && key_f_n=='d0) begin
phase_data <= phase_data+ phase_ctrl;
end
else begin
phase_data <=phase_data;
end
end
4、根据当前phase_data生成指定频率的锯齿波和三角波
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
phase_data_1 <=0;
end
else begin
phase_data_1 <=phase_data_1+phase_data;
end
end
assign sanjiao_data = phase_data_1[31]? (~phase_data_1[30:15]): phase_data_1[30:15]; //三角波
assign juchi_data = phase_data_1[31:15]; //锯齿波
5、生成正弦波
dds_compiler_0 your_instance_name (
.aclk(clk),
.aclken(rst_n),
.s_axis_phase_tvalid(phase_valid),
.s_axis_phase_tdata(phase_data),
.m_axis_data_tvalid(data_valid),
.m_axis_data_tdata(sine_data_signed)
);
assign sine_data = sine_data_signed+sine_buchang; //ip核产生的是有符号数,根据题目要求幅度范围,加一个补偿变成无符号数
6、生成占空比可调的方波
div_gen_0 div ( //除法是为了计算2的32次方除以100然后除以当前phase_data
.aclk(clk), //计算一下当前频率下,占空比百分之一需要经过几个clk
.s_axis_divisor_tvalid(s_axis_divisor_tvalid),
.s_axis_divisor_tdata(phase_data),
.s_axis_dividend_tvalid(s_axis_dividend_tvalid),
.s_axis_dividend_tdata(zhankong), //2的32次方除以100
.m_axis_dout_tvalid(m_axis_dout_tvalid),
.m_axis_dout_tdata(zhankong_ctrl)
);
always @(posedge clk or negedge rst_n) begin //M=1 就是占空比为百分之一
if (!rst_n) begin
M <= 1;
end
else if (key_p=='d1 && key_p_n=='d0) begin
M<= M+1;
end
else begin
M <= M;
end
end
assign zhangkong_ctrl_n = zhankong_ctrl[63:32] *M;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt<='d0;
cnt_1<='d0;
fangbo_data<=16'd0;
end
else if (cnt_1==zhankong_ctrl[63:32] *100 || (key_f=='d1 && key_f_n=='d0) )begin
cnt_1<='d0;
cnt<='d0;
fangbo_data<=16'd0;
end
else if (cnt==zhangkong_ctrl_n-1) begin
cnt<=cnt;
cnt_1<=cnt_1+1;
fangbo_data<=16'd0;
end
else begin
cnt<=cnt+1;
cnt_1<=cnt_1+1;
fangbo_data<=16'd65535;
end
end
7、选择波形
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state<= SINE;
end
else case (state)
SINE:
if (key_s=='d1 && key_s_n=='d0) begin
state <= FANGBO;
end
else begin
state <=SINE;
end
FANGBO:
if (key_s=='d1 && key_s_n=='d0) begin
state <=SANJIAO;
end
else begin
state <=FANGBO;
end
SANJIAO:
if (key_s=='d1 && key_s_n=='d0) begin
state <=JUCHI;
end
else begin
state <=SANJIAO;
end
JUCHI:
if (key_s=='d1 && key_s_n=='d0) begin
state <=SINE;
end
else begin
state <=JUCHI;
end
default:
state <=SINE;
endcase
end
reg [15:0] data_temp;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_temp <= 'd0;
end
else if (state == SINE) begin
data_temp<=sine_data;
end
else if (state == FANGBO) begin
data_temp<=fangbo_data;
end
else if (state == JUCHI) begin
data_temp<=juchi_data;
end
else if (state == SANJIAO) begin
data_temp<=sanjiao_data;
end
else begin
data_temp <=sine_data;
end
end
8、幅度控制
mult_gen_0 chengfa (
.CLK(clk), // input wire CLK
.A(data_temp), // input wire [15 : 0] A
.B(fuzhi_data), // input wire [16 : 0] B
.P(fuzhi) // output wire [32 : 0] P
);
9、输出最终波形
assign wave_data =fuzhi[32:16];
endmodule
10、仿真结果图
本代码可作参考,里面用到了几个ip核,工程文件可以关注后私信。