本文主要是介绍FPGA中Verilog HDL/VHDL实现NCO(数字控制振荡器),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
数控振荡器(NCO,numerically controlled oscillator)软件无线接收机,直接频率合成器(DDS),快速傅里叶变换(FFT)的重要组成部分,NCO采用全数字技术实现,具有分辨率高,频率切换快,相位噪声低等优点。
一般实现NCO的方法是查表法,即实现计算好各个相位的正余弦值存储在查找表中,然后通过寻址输出相应的正余弦值。
下面利用查表法分两步实现一个基于FPGA以及VerilogHDL语言的NCO。
1.利用matlab软件将所需要的相位的正余弦值计算好待用
其中利用matlab产生正余弦值的程序如下:
clear,clc,close all
%%设置参数
sam_clk=20; %%采样频率
out_freq=1;%%输出频率
data_width=18;%%数据位宽, 量化位数
N=20;
%%计算正弦值
sin_1=-sin(([0:N])*2*pi*out_freq/sam_clk);
sin_1_out=round(sin_1*2^(data_width-1));%%计算余弦值
cos_1=cos(([0:N])*2*pi*out_freq/sam_clk);
cos_1_out=round(cos_1*2^(data_width-1));
%%调整输出格式
sin=[sin_1_out];
cos=[cos_1_out];sin_bin=zeros(1,2001);
cos_bin=zeros(1,2001);
sin_bin=[];
cos_bin=[];
for cnt=1:20
sin_bin=[sin_bin ; dec2binPN(sin(cnt),18)];
end
for cnt=1:20
cos_bin=[cos_bin ; dec2binPN(cos(cnt),18)];
end
将得到的值plot得正余弦波形如下:
2.FPGA中实现nco
首先将上一步matlab中生成的数据导出,存入mif表中,然后在quartus中调用两个rom并用mif分别进行初始化,然后通过程序调用这两个rom,分别根据地址输出对应的值,编写的verilog HDL程序如下:
module nco(input clk,input nco_en,input rst,output [17:0]nco_I,output [17:0]nco_Q
);reg [4:0]addr;always@(posedge clk or negedge rst)if(rst==1'b0)begin addr<=5'd0; end else begin if(nco_en==1'b0) addr<=5'd0;else begin if(addr==5'd19) addr<=5'd0;else addr<=addr+1'd1;end end wire [17:0] nco_I_temp;wire [17:0] nco_Q_temp;rom_I my_rom_I(.address(addr),.clock(clk),.q(nco_I_temp));rom_Q my_rom_Q(.address(addr),.clock(clk),.q(nco_Q_temp));assign nco_I=nco_I_temp;assign nco_Q=nco_Q_temp;endmodule
编写测试代码如下:
`timescale 1ps/1ps
`define clock_period 20 module nco_tb;reg rst;reg clk;reg nco_en;wire [17:0]nco_I;wire [17:0]nco_Q;nco my_nco(.clk(clk),.nco_en(nco_en),.rst(rst),.nco_I(nco_I),.nco_Q(nco_Q));initial begin clk=1'b1;end always #(`clock_period/2) clk=~clk; initial begin rst=1'b0;#(`clock_period*10)rst=1'b1;nco_en=1'b1;#(`clock_period*200)$stop;end
endmodule
经过quartus ii 软件调用modelsim仿真软件验证所编写nco程序,得到结果如下:
以上就基于查表法实现了数控振荡器nco
这篇关于FPGA中Verilog HDL/VHDL实现NCO(数字控制振荡器)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!