赞
踩
基于FPGA的任意波形DDS发生器
说明:
1.采用XINLNUX平台,使用rom加载coe文件,产生波形,
2.频率调节使用的是加载读取ROM速度的不同产生频率变换。
3.对于调节频率的加减,写入按键值进去控制读取ROM地址加载的速度就可以。或者改变输入的全局时钟的频率,对应的输出频率也会改变的。
4.对于输出的8为数据。后面加上DAC就可以下载程序上板子测试啦。
频率计算:一个周期:5470ns-4730ns=740ns=1.351Mhz(这个是最低的)
后面的第三个频率可以达到5.5MHZ
同样的也可以先把全局时钟倍频到100MHZ,200hz,或者跟高的频率,那么输出的dds的频率将会更高。
1.生成COE文件:用于配置dds,保存到工程下,待会要用
打开vivado,IP核里面找到
选择位宽为8位,深度256,也可以选择其他的,需要和你的COE文件格式匹配就行。
这里找到第一步生成的文件加载进去。
然后撸代码:(加的有按键消抖的程序,仿真但是没有用到)
module top_dds #( parameter INPUT_WIDTH = 3, parameter OUTPUT_WIDTH = 8 )( input wire sys_clk, input sys_rst_n, input [INPUT_WIDTH - 1 : 0] key, output [OUTPUT_WIDTH - 1 : 0] dds_sin, output [15: 0] dds_sin2 , output [OUTPUT_WIDTH - 1 : 0] fangbo, output [OUTPUT_WIDTH - 1 : 0] sanjiao, output [OUTPUT_WIDTH - 1 : 0] juci ); wire [2:0] key_value; wire ena; reg [7:0]cnt; reg [15:0]cnt2; assign ena = 1; key_debounce u_key_debounce1( .sys_clk (sys_clk ), //外部50M时钟 .sys_rst_n (sys_rst_n ), //外部复位信号,低有效 .key (key[0] ), //外部按键输入 .key_flag ( ), //按键数据有效信号 .key_value (key_value[0]) //按键消抖后的数据 ); key_debounce u_key_debounce2( .sys_clk (sys_clk ), //外部50M时钟 .sys_rst_n (sys_rst_n ), //外部复位信号,低有效 .key (key[1] ), //外部按键输入 .key_flag ( ), //按键数据有效信号 .key_value (key_value[1]) //按键消抖后的数据 ); key_debounce u_key_debounce3( .sys_clk (sys_clk ), //外部50M时钟 .sys_rst_n (sys_rst_n ), //外部复位信号,低有效 .key (key[2] ), //外部按键输入 .key_flag ( ), //按键数据有效信号 .key_value (key_value[2] ) //按键消抖后的数据 ); //dds IP 核:rom //正弦波COE文件位宽8,深度256 sin u_sin ( .clka(sys_clk), // input wire clka .ena(ena), // input wire ena .addra(cnt), // input wire [7 : 0] addra .douta(dds_sin) // output wire [7 : 0] douta ); //正弦波这个采用的COE文件不一样,位宽16,深度256 sin2 u_sin2 ( .clka(sys_clk), // input wire clka .ena(ena), // input wire ena .addra(cnt2), // input wire [7 : 0] addra .douta(dds_sin2) // output wire [7 : 0] douta ); //方波COE文件位宽8,深度256 dds_fangbo u_dds_fangbo ( .clka(sys_clk), // input wire clka .ena(ena), // input wire ena .addra(cnt), // input wire [7 : 0] addra .douta(fangbo) // output wire [7 : 0] douta ); //三角波COE文件位宽8,深度256 dds_sanjiao u_dds_sanjiao ( .clka(sys_clk), // input wire clka .ena(ena), // input wire ena .addra(cnt), // input wire [7 : 0] addra .douta(sanjiao) // output wire [7 : 0] douta ); //锯齿波COE文件位宽8,深度256 dds_juci u_dds_juci ( .clka(sys_clk), // input wire clka .ena(ena), // input wire ena .addra(cnt), // input wire [7 : 0] addra .douta(juci) // output wire [7 : 0] douta ); /*按键值寄存*/ /*reg [2:0]key_integer; always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) key_integer <= 0; else if(key_value[0] == 0) key_integer <= key_integer+ 1'b1; else key_integer <= key_integer; end reg [2:0]key_integer1; always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) key_integer1 <= 0; else if(key_value[1] == 0) key_integer1 <= key_integer1+ 1'b1; else key_integer1 <= key_integer1; end reg [2:0]key_integer2; always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) key_integer2 <= 0; else if(key_value[2] == 0) key_integer2 <= key_integer2+ 1'b1; else key_integer2 <= key_integer2; end always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) cnt <= 8'd0; else if(key_integer == 1'b1 &&(cnt <=100 )) cnt <= cnt+1'b1; else cnt <= 0; end always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) cnt <= 8'd0; else if(key_integer1 == 0 &&(cnt <=250 )) cnt <= cnt+1'b1; else cnt <= 0; end */ always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) cnt <= 8'd0; else if(key[0] == 0 &&(cnt <250 )) cnt <= cnt+3'd7; else if(key[1] == 0 &&(cnt <250 )) cnt <= cnt+4'd15; else if(key[2] == 0 &&(cnt <250 )) cnt <= cnt+5'd31; else cnt <= 0; end //步进不一样 always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) cnt2 <= 16'd0; else if(key[0] == 0 &&(cnt2 <65536 )) cnt2 <= cnt2+'d4;//这个已经达到1G了。后口的更大 else if(key[1] == 0 &&(cnt2 <65536 )) cnt2 <= cnt2+'d15; else if(key[2] == 0 &&(cnt2 <65536 )) cnt2 <= cnt2+'d25; else cnt2 <= 0; end endmodule
加的原子哥的按键消抖,仿真没有用到
//---------------------------------------------------------------------------------------- // File name: key_debounce module key_debounce( input sys_clk, //外部50M时钟 input sys_rst_n, //外部复位信号,低有效 input key, //外部按键输入 output reg key_flag, //按键数据有效信号 output reg key_value //按键消抖后的数据 ); //reg define reg [31:0] delay_cnt; reg key_reg; //***************************************************** //** main code //***************************************************** always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin key_reg <= 1'b1; delay_cnt <= 32'd0; end else begin key_reg <= key; if(key_reg != key) //一旦检测到按键状态发生变化(有按键被按下或释放) delay_cnt <= 32'd1000000; //给延时计数器重新装载初始值(计数时间为20ms) else if(key_reg == key) begin //在按键状态稳定时,计数器递减,开始20ms倒计时 if(delay_cnt > 32'd0) delay_cnt <= delay_cnt - 1'b1; else delay_cnt <= delay_cnt; end end end always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin key_flag <= 1'b0; key_value <= 1'b1; end else begin if(delay_cnt == 32'd1) begin //当计数器递减到1时,说明按键稳定状态维持了20ms key_flag <= 1'b1; //此时消抖过程结束,给出一个时钟周期的标志信号 key_value <= key; //并寄存此时按键的值 end else begin key_flag <= 1'b0; key_value <= key_value; end end end endmodule
仿真激励文件:
module top_dds_tb(); reg sys_clk; reg sys_rst_n; reg [2:0] key; wire [7:0] dds_sin; wire [15:0] dds_sin2; wire [7:0] fangbo ; wire [7:0] sanjiao; wire [7:0] juci; reg [3:0]cnt_key; top_dds u_top_dds( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .key (key), .dds_sin (dds_sin), .dds_sin2 (dds_sin2), .fangbo (fangbo), .sanjiao (sanjiao), .juci (juci) ); initial begin #5 sys_clk=0; sys_rst_n=0; #10 sys_rst_n = 1; key <= 3'b111; #200 key <= 3'b110; #10000 key <= 3'b101; #10000 key <= 3'b011; end always #10 sys_clk =~sys_clk; /*always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin key <= 3'b111; cnt_key <=0; end else if(cnt_key == 4'd10000) key <= 3'b010; else if (cnt_key == 4'd20000) begin key <= 3'b001; end else if(cnt_key == ) else cnt_key <= cnt_key + 1'b1; end*/ endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。