DDS的verilog实现(波形切换、幅度控制、相位控制、频率控制)

本文档展示了一个使用Verilog编写的直接数字频率合成(DDS)模块,该模块能够根据输入的控制参数产生四种不同类型的波形:正弦波、方波、三角波和锯齿波。通过按键控制,可以调整波形的频率、幅度和占空比,同时支持四种波形之间的切换。DDS模块内部包含了IP核用于生成正弦波,以及除法器和乘法器来实现占空比调整和幅度控制。仿真实验结果显示了模块的正确工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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核,工程文件可以关注后私信。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值