1、NCO原理
在通过相位累加产生地址信息时,通常需要输出当前时刻的相位值所对应的正弦值,即以参考频率源对相位进行等可控间隔采样。
根据Nyquist准则,允许输出的最高频率为
2、任意三角波
(1)首先在matlab生成存入ROM的NCO码表(.coe)文件,有固定格式
n = 0:4095; %相位累加器位数N为12
costable = cos(2*pi/4096*n);
costable = round(costable*64); %量化
fid = fopen('costable.coe','wt');
fprintf(fid,'memory_initialization_radix = 10;\nmemory_initialization_vector = ');
for i = 1 : 4096
fprintf(fid,'\n');
fprintf(fid,'%4d,',costable(i));
end
(2)将.coe文件导入Vivado ROM中,Vivado中需要写两个模块相位累加器和调用IP核输出波形
相位累加器代码如下:
`timescale 1ns / 1ps
module PhaseAdder(
input sysclk,
input rstn,
input [31:0] carr_freq, //频率控制字,相位累加步长
input en,
output [11:0] phase
);
reg [31:0] phase_reg;
always@(posedge sysclk or negedge rstn)
begin
if(!rstn)
phase_reg <= 32'd0;
else
begin
if(en)
phase_reg <= phase_reg + carr_freq; //溢出循环
end
end
assign phase = phase_reg[31:20];
endmodule
这里需要注意,根据波形生成公式越大,频率精度越高,本应需要深度和生成点数相同的ROM。但是可以通过截位运算用4096深度的ROM来装码表,计算频率控制字还是要通过
来计算,截位产生的误差为
例化ROM核后输出波形代码如下:
module cos_gen(
input sysclk,
input rstn,
input en,
input [31:0] cos_freq,
output signed [7:0] cos_wave,
);
wire [11:0] phase;
PhaseAdder u_PhaseAdder
(
.sysclk (sysclk),
.rstn (rstn),
.cos_freq (cos_freq),
.en (en),
.phase (phase)
);
NCO_COS u_NCO_COS
(
.a (phase),
.spo (cos_wave)
);
endmodule
3、任意方波(时钟信号)
方波信号产生相较于三角波而言比较简单,可以省略生成码表的步骤(因为只有01),可以只通过Verilog代码产生。
`timescale 1ns / 1ps
module ClkGen_unit(
input clk_96m,
input rst_n,
input en,
input [31:0] code_nco_word,
output [7:0] code_clk_reg,
);
reg [31:0] code_nco;
reg code_nco_h32;
reg [7:0] code_clk_reg_c;
always @(posedge clk_96m)
begin
if (rst_n==0) begin
code_nco <= 0;
end else begin
if (en==1) begin
code_nco<=code_nco+code_nco_word;
end else begin
code_nco<=0;
end
end
end
always @(posedge clk_96m)
begin
if (rst_n==0) begin
code_nco_h32 <= 0;
end else begin
code_nco_h32<=code_nco[31];
end
end
always @(posedge clk_96m)
begin
if (rst_n==0) begin
code_clk_reg_c <= 0;
end else begin
code_clk_reg_c[0]<=(~code_nco[31]) & code_nco_h32; //方波整形,改变占空比
code_clk_reg_c[7:1]<=code_clk_reg_c[6:0]; //产生多级延迟方波信号,方便自行选择
end
end
assign code_clk_reg=code_clk_reg_c;
endmodule
本代码增加了两个比较巧妙的步骤:
(1)对方波进行整形,改变其占空比;
(2)产生多级延迟方波信号,方便自行选择。