0
点赞
收藏
分享

微信扫一扫

FPGA学习(1)NCO产生任意三角波、方波

凶猛的小白兔 2022-01-09 阅读 160

1、NCO原理

在通过相位累加产生地址信息时,通常需要输出当前时刻的相位值所对应的正弦值,即以参考频率源对相位进行等可控间隔采样。

f_{out}=\frac{f_{sys}}{2^{N}}\times Freq

根据Nyquist准则,允许输出的最高频率为\frac{f_{clk}}{2}

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

这里需要注意,根据波形生成公式2^{N}越大,频率精度越高,本应需要深度和生成点数相同的ROM。但是可以通过截位运算用4096深度的ROM来装码表,计算频率控制字还是要通过N=32来计算,截位产生的误差为2\pi /2^{20}=6\times 10^{-6}

例化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)产生多级延迟方波信号,方便自行选择。

举报

相关推荐

0 条评论