dds信号发生器(基于Verilog的信号发生器DDS的设计)

dds信号发生器
1、前言采用 Verilog 设计了一个简单的信号发生器,可输出正弦波、方波、三角波、锯齿波这 4 种频率、相位和幅值可调的波形。
2、具体功能
module dds(

input wire clk,
input wire rst_n,
input wire [19:0] freq,
input wire [1:0] wave_sel,
input wire [1:0] amp_adj,
output wire [9:0] wave_adj

);

wire [31:0] step_val;
wire [9:0] addr;
wire [7:0] q;

freq_ctrl_v2 freq_ctrl_inst(

.clk (clk),
.rst_n (rst_n),
.wave_sel(wave_sel),
.freq (freq),
.step_val(step_val)

);

phase_adder phase_adder_inst(

.clk (clk),
.rst_n (rst_n),
.wave_sel(wave_sel),
.step_val(step_val),
.addr (addr)

);

rom_ip rom_ip_inst (
.address ( addr ),
.clock ( clk ),
.q ( q )
);

amp_adj amp_adj_inst(

.clk (clk),
.rst_n (rst_n),
.wave (q),
.amp_factor(amp_adj),
.wave_adj(wave_adj)

);

endmodule在设计的模块中,包含以下功能:
(1)通过 freq 信号输入需要的频率的值;
(2)通过 wave_sel 信号选择所需的波形;
(3)通过 amp_adj 信号选择波形放大的倍数。
在该设计中,包含 3 个模块:
频率控制器,根据输入的频率值输出步进值 step_val 。
相位累加器,根据步进值 step_val 控制对应地址的变化。
 波形放大器,对 rom 输出的数据进行放大。
3、设计实现
1、由于正弦波无法直接通过 FPGA 直接产生,因此在 FPGA 中例化一个位宽为 10bit、深度为 1024 的 rom ip核,采用 matlab 产生一个由 256 个采样点构成的正弦波形、一个由 256 个采样点构成的方波波形、一个由 256 个采样点构成的三角波波形、一个由 256 个采样点构成的锯齿波的数据点作为该 rom 的初始化文件。FPGA只需要从 ROM 中读取相应地址中的数据即可输出对应波形。
2、在产生正弦波的过程中,FPGA 读取 ROM 地址中的数据速率决定了正弦波的周期,例如,当 FPGA 的主时钟为 50MHz,在每个时钟上升沿读取完地址 0~255 这 256 个地址的数据后输出一个完整的正弦波,即经过了一个正弦波周期,此时波形周期为 20ns x 256  = 5120ns。如果每 2 个上升沿读取的地址才加 1, 则周期为 40ns x 256 = 10240ns 。如果每个上升沿读取的地址加 2, 则周期为 40ns x128= 2560ns 。因此通过这种改变方法可以改变输出波形的周期。
但是,此时只能输出某些频率的波形,因此在这里使用了 32 位的计数器cnt[31:0],把高 8 位给 addr[7:0],这样一来,如果 cnt 在上升沿加 1 ,需要 2^32 个时钟周期才能产生一个周期的正弦波,此时频率为 50MHz /(2^32),约为 0.01164Hz,即可以产生的正弦波最小频率为 0.01164Hz,通过增大 cnt 在每隔上升沿加的值 step_val 即可改变频率。
3、amp_adj[1:0] 信号可改变波形,将其赋给 addr[9:8],即可改变 rom 的基地址,通过这种方式改变波形。
4、amp_adj[1:0] 信号对波形进行放大,只要将得到的波形信号与该信号加 1 的值相乘即可。
4、具体源码

module freq_ctrl(

input wire clk,
input wire rst_n,
input wire [1:0] wave_sel,
input wire [19:0] freq,
output reg [31:0] step_val

);

always @(posedge clk or negedge rst_n)
if(!rst_n) begin
step_val <= 0;
end
else begin
step_val <= 86 * freq;
end

endmodule
module phase_adder(

input wire clk,
input wire rst_n,
input wire [1:0] wave_sel,
input wire [31:0] step_val,
output reg [9:0] addr

);

reg [31:0] cnt;
reg [31:0] reg_step;

always @(posedge clk or negedge rst_n)
if(!rst_n) cnt <= 32’d0;
else cnt <= cnt + reg_step;

always @(posedge clk or negedge rst_n)
if(!rst_n) begin
addr <= 0;
reg_step <= 0;
end
else begin
addr <= {wave_sel, cnt[31:24]};
reg_step <= step_val;
end

endmodule
module amp_adj(

input wire clk,
input wire rst_n,
input wire [7:0] wave,
input wire [1:0] amp_factor,
output reg [9:0] wave_adj

);

always @(posedge clk or negedge rst_n)
if(!rst_n)
wave_adj <= 10’d0;
else
wave_adj <= wave * (amp_factor + 1’b1);

endmodule

dds信号发生器相关文章

版权声明

为您推荐