大家好,欢迎来到IT知识分享网。
目的:设计一个DDS,可以输出两个波形,输出的波形的周期可以修改,相位可以修改,种类也可以修改
输入:clk,reset,一个控制T的按键,一个控制相位的按键,一个控制波形种类的按键。
思路:双通道——需要两个DDS。
波形种类可控——每个DDS需要四个ROM分别存放正弦波,三角波,锯齿波,方波。
频率可控——一个频率控制按钮,按一下切换一次频率,可供选择的频率是固定的,用计数器来设计。
相位可控——一个相位控制按钮,按一下切换一次相位,可供选择的相位是固定的,用计数器来设计。
有按钮——引入按键消抖模块,提高准确性。
可控——计数器+查找表 可以实现简单切换。(其他,如矩阵键盘等,后续)
建模:
细节:输出波形的周期与频率控制的关系
ROM存储一个波形,而相位累加器的内存存储一个波形的离散点。一般来说相位累加器内存大于ROM。而取点间隔就是频率控制字。
比如ROM是十位【9:0】,而相位累加器是【15:0】,那么取点时相位累加器应该取高10位来ROM中取幅度,即【15:6】,这样子输出的波形的周期会随着频率控制字(即取点步长)的大小而改变。如果频率比较小(如2),那么取ROM中一个点要停留很多个系统时钟周期,且ROM中每个点都会被取到,输出的波形周期就长,如果频率比较大(如128),那么取ROM中一个点只停留一个系统时钟周期,且会跳过ROM中的某些点,输出的波形周期就短。
验证结果:
第一行:按键控制频率
第二行:按键控制波形
代码:
module DDS_advanced( clk, reset, f_change_A, f_change_B, p_change_A, p_change_B, wave_change_A, wave_change_B, dout_A, dout_B ); input clk ; input reset ; input f_change_A ; input f_change_B ; input p_change_A ; input p_change_B ; input wave_change_A ; input wave_change_B ; output wire[9:0]dout_A ; output wire[9:0]dout_B ; reg [1:0]f_cnt_A ;//设置A通道的频率选择按钮的消抖,计数
wire tx_fA ; wire f_change_A_sign ; buttopn_debounde #( .delay(1000) ) buttopn_debounde_fA (//消抖,取释放符号为+1信号
.clk(clk), .tx(f_change_A), .reset(reset), .bd_tx(tx_fA), .release_sign(f_change_A_sign) ); always@(posedge clk or negedge reset)//计数
if (!reset) f_cnt_A <= 2'd0 ;
else if(f_change_A_sign) f_cnt_A <= f_cnt_A + 1'd1 ;
else f_cnt_A <= f_cnt_A ; reg [1:0]p_cnt_A ;//设置A通道的相位选择按钮的消抖,计数
wire tx_pA ; wire p_change_A_sign ; buttopn_debounde #( .delay(1000) ) buttopn_debounde_pA (//消抖,取释放符号为+1信号
.clk(clk), .tx(p_change_A), .reset(reset), .bd_tx(tx_pA), .release_sign(p_change_A_sign) ); always@(posedge clk or negedge reset)//计数
if (!reset) p_cnt_A <= 2'd0 ;
else if(p_change_A_sign) p_cnt_A <= p_cnt_A + 1'd1 ;
else p_cnt_A <= p_cnt_A ; reg [1:0]wave_change_cnt_A ;//设置A通道的波形选择按钮的消抖,计数
wire tx_wavea ; wire wave_change_A_debounde_sign ; buttopn_debounde #( .delay(1000) ) buttopn_debounde_waveA (//消抖,取释放符号为+1信号
.clk(clk), .tx(wave_change_A), .reset(reset), .bd_tx(tx_wavea), .release_sign(wave_change_A_debounde_sign) ); always@(posedge clk or negedge reset)//计数
if (!reset) wave_change_cnt_A <= 2'd0 ;
else if(wave_change_A_debounde_sign) wave_change_cnt_A <= wave_change_cnt_A + 1'd1 ;
else wave_change_cnt_A <= wave_change_cnt_A ; reg [1:0]f_cnt_B ;//设置B通道的频率选择按钮的消抖,计数
wire tx_fB ; wire f_change_B_sign ; buttopn_debounde #( .delay(1000) ) buttopn_debounde_fB (//消抖,取释放符号为+1信号
.clk(clk), .tx(f_change_B), .reset(reset), .bd_tx(tx_fB), .release_sign(f_change_B_sign) ); always@(posedge clk or negedge reset)//计数
if (!reset) f_cnt_B <= 2'd0 ;
else if(f_change_B_sign) f_cnt_B <= f_cnt_B + 1'd1 ;
else f_cnt_B <= f_cnt_B ; reg [1:0]p_cnt_B ;//设置B通道的相位选择按钮的消抖,计数
wire tx_pB ; wire p_change_B_sign ; buttopn_debounde #( .delay(1000) ) buttopn_debounde_pB (//消抖,取释放符号为+1信号
.clk(clk), .tx(p_change_B), .reset(reset), .bd_tx(tx_pB), .release_sign(p_change_B_sign) ); always@(posedge clk or negedge reset)//计数
if (!reset) p_cnt_B <= 2'd0 ;
else if(p_change_B_sign) p_cnt_B <= p_cnt_B + 1'd1 ;
else p_cnt_B <= p_cnt_B ; reg [1:0]wave_change_cnt_B ;//设置B通道的波形选择按钮的消抖,计数
wire tx_waveb ; wire wave_change_B_debounde_sign ; buttopn_debounde #( .delay(1000) ) buttopn_debounde_waveB (//消抖,取释放符号为+1信号
.clk(clk), .tx(wave_change_B), .reset(reset), .bd_tx(tx_waveb), .release_sign(wave_change_B_debounde_sign) ); always@(posedge clk or negedge reset)//计数
if (!reset) wave_change_cnt_B <= 2'd0 ;
else if(wave_change_B_debounde_sign) wave_change_cnt_B <= wave_change_cnt_B + 1'd1 ;
else wave_change_cnt_B <= wave_change_cnt_B ; DDS_Module channel_A(//A通道连线
.clk(clk) , .reset(reset) , .f_ctrl(f_cnt_A) , .p_ctrl(p_cnt_A) , .wave_ctrl(wave_change_cnt_A) , .dout(dout_A) ); DDS_Module channel_B(//B通道连线
.clk(clk) , .reset(reset) , .f_ctrl(f_cnt_B) , .p_ctrl(p_cnt_B) , .wave_ctrl(wave_change_cnt_B) , .dout(dout_B) ); endmodule
module DDS_Module( clk , reset , f_ctrl , p_ctrl , wave_ctrl , dout ); input clk ; input reset ; input [1:0]wave_ctrl ; input [1:0]f_ctrl ;//(频率选择按钮)
input [1:0]p_ctrl ; output reg [9:0]dout ; reg [4:0]frequen; always@(*) case(f_ctrl) 0:frequen = 5'd2 ;//输出周期:(65536/2 )* 20ns = 655360ns
1:frequen = 5'd4 ;//输出周期:(2^16/4 )* 20ns = 327680ns
2:frequen = 5'd8 ;//输出周期:(2^16/8 )* 20ns = 163840ns
3:frequen = 5'd16 ;//输出周期:(2^16/4 )* 20ns = 81920ns
endcase
//频率控制字寄存器(频率)(大于1的时候,后面相位累加器输出到实时相位时要砍掉它的位宽)
reg [4:0]f_regist ;//(取值限制为2的倍数)
always @ (posedge clk) f_regist <= frequen ; //相位累加器 (f * t)
reg [15:0]p_add ; always@(posedge clk or negedge reset ) if(!reset ) p_add <= 0 ; else p_add <= p_add + f_regist ; reg [9:0]phase_cv; always@(*) case(p_ctrl) 0:phase_cv = 10'd128 ;//45°
1:phase_cv = 10'd256 ;//90°
2:phase_cv = 10'd512 ;//135°
3:phase_cv = 10'd640 ;//180°
endcase
//相位控制字寄存器(初始相位)(相位偏移量)
reg [9:0]p_regist ; always @ (posedge clk) p_regist <= phase_cv ; //实时相位
reg [9:0]p_now ; always@(posedge clk or negedge reset ) if(!reset ) p_now <= 0 ; else p_now <= p_add[15:6] + p_regist ; //取相位累加器的前10位
wire [9:0]wave_sin ; wire [9:0]wave_square ; wire [9:0]wave_triangular; wire [9:0]wave_sawtooth; always@(*)//波形选择
case(wave_ctrl) 0: dout = wave_sin ; 1: dout = wave_triangular ; 2: dout = wave_square ; 3: dout = wave_sawtooth ; endcase rom_sin rom_sin(//正弦波
.clka(clk), .addra(p_now), .douta(wave_sin) ); rom_triangular rom_triangular(//三角波
.clka(clk), .addra(p_now), .douta(wave_triangular) ); rom_square rom_square(//方波
.clka(clk), .addra(p_now), .douta(wave_square) ); rom_sawtooth rom_sawtooth(//锯齿波
.clka(clk), .addra(p_now), .douta(wave_sawtooth) ); endmodule
module buttopn_debounde( clk, tx, reset, bd_tx, release_sign ); input tx ; input clk ; input reset ; output reg bd_tx ; output reg release_sign ;//按下释放信号
reg [1:0]edge_detect_regist; always@(posedge clk or negedge reset)//输入信号的移位寄存器
begin
if (!reset) edge_detect_regist <= 2'd0 ;
else
begin edge_detect_regist[0] <= tx ; edge_detect_regist[1] <= edge_detect_regist[0] ; //等效于 edge_detect_regist <={ edge_detect_regist[0] , tx }
end
end
wire neg_edge , pos_edge ; assign neg_edge = ( edge_detect_regist == 2'b10 ) ? 1 : 0 ;//下降沿
assign pos_edge = ( edge_detect_regist == 2'b01 ) ? 1 : 0 ;//上升沿
parameter delay = 20000000 / 20 ;//抖动20ms
reg [3:0]state ; reg [19:0]counter1 ; always@(posedge clk or negedge reset) begin
if (!reset) state <= 4'd0 ;//空闲态
else if ( ( neg_edge ) && ( state == 4'd0 ) )
state <= 4'd1 ;//按下消抖态
else if ( ( state == 4'd1 ) && (( delay - 1) > counter1 ) && ( pos_edge ) )
state <= 4'd0 ;//空闲态
else if ( ( state == 4'd1 ) && (( delay - 1) <= counter1 ) )
state <= 4'd2 ;//按下态
else if ( ( pos_edge ) && ( state == 4'd2 ) )
state <= 4'd3 ;//释放消抖态
else if ( ( state == 4'd3 ) && (( delay - 1) > counter1 ) && ( neg_edge ) )
state <= 4'd2 ;//按下态
else if ( ( state == 4'd3 ) && (( delay - 1) <= counter1 ) )
state <= 4'd0 ;//空闲态
end
always@(posedge clk or negedge reset) begin
if (!reset) counter1 <= 5'd0 ;
else if ( ( neg_edge ) || ( pos_edge ) ) counter1 <= 5'd0 ;
else if ( ( state == 4'd1 ) && (! neg_edge ) && (! pos_edge ) )
counter1 <= counter1 + 1'd1 ;
else if ( ( state == 4'd3 ) && (! neg_edge ) && (! pos_edge ) )
counter1 <= counter1 + 1'd1 ;
end
always@(posedge clk or negedge reset) begin
if (!reset) bd_tx <= 1'd1 ;//空闲态
else
case(state) 0:bd_tx <= 1'd1 ;
1:bd_tx <= 1'd1 ;
2:bd_tx <= 1'd0 ;
3:bd_tx <= 1'd0 ;
endcase
end
reg pre_sign ; always@(posedge clk or negedge reset) begin
if (!reset) pre_sign <= 1'd1 ;//空闲态
else if( ( state == 4'd1 ) && (( delay - 1) <= counter1 ) )
pre_sign <= 1'd0 ;
else if ( state == 4'd2 )
pre_sign <= 1'd1 ;
end
always@(posedge clk or negedge reset) begin
if (!reset) release_sign <= 1'd0 ;//空闲态
else if( ( state == 4'd3 ) && (( delay - 1) <= counter1 ) )
release_sign <= 1'd1 ;
else if ( state == 4'd0 )
release_sign <= 1'd0 ;
end
endmodule
`timescale 1ns / 1ps module DDS_advanced_tb( ); reg clk ; reg reset ; reg f_change_A ; reg f_change_B ; reg p_change_A ; reg p_change_B ; reg wave_change_A ; reg wave_change_B ; wire [9:0]dout_A ; wire [9:0]dout_B ; DDS_advanced DDS_advanced_sim( clk, reset, f_change_A, f_change_B, p_change_A, p_change_B, wave_change_A, wave_change_B, dout_A, dout_B ); initial clk = 1 ; always #10 clk = ! clk ; initial
begin reset = 0 ; f_change_A = 1 ; f_change_B = 1 ; p_change_A = 1 ; p_change_B = 1 ; wave_change_A = 1 ; wave_change_B = 1 ; #201 ; reset = 1 ; #90000 ; wave_change_A = 0 ; #910000 ; wave_change_A = 1 ; f_change_B = 0 ; #910000 ; f_change_B = 1 ; wave_change_A = 0 ; #910000 ; wave_change_A = 1 ; f_change_B = 0 ; #910000 ; f_change_B = 1 ; wave_change_A = 0 ; #910000 ; f_change_B = 0 ; wave_change_A = 1 ; #910000 ; f_change_B = 1 ; wave_change_A = 0 ; #910000 ; f_change_B = 0 ; wave_change_A = 1 ; #910000 ; f_change_B = 1 ; #910000 ;//验证波形和频率控制
reset = 0 ;//验证相位控制
#201 ; reset = 1 ; p_change_B = 0 ; f_change_A = 0 ; f_change_B = 0 ; #200 f_change_A = 1 ; f_change_B = 1 ; #910000 ; p_change_B = 1 ; #910000 ; p_change_B = 0 ; #910000 ; p_change_B = 1 ; #910000 ; p_change_B = 0 ; #910000 ; p_change_B = 1 ; #910000 ; p_change_B = 0 ; #910000 ; p_change_B = 1 ; #910000 ; $stop; end
endmodule
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32695.html