琦谓 发表于 2025-6-2 22:59:57

verilog利用线性插值实现正弦波生成器(dds)

verilog实现线性插值实现正弦波生成器

​        最近在项目上遇到一个需要在低资源FPGA上实现FFT逻辑的项目,而且要求实现窗函数。对于窗函数来说,莫非是实现正弦波生成器,正弦波生成器可以利用DDS模块,CORDIC模块,或者查找表的方式实现,以下主要讲解ROM核线性插值相结合的波形生成器,用于生成正弦波。
1.线性插值

​        线性插值是一种数据估值算法,由于其拟合线是一条直线,所以叫做线性插值。即通过需要估值点的左右两个点的权重以及距离,对估值点的权重进行计算的一种算法。
(x1,y1)(x1,y1)(x0,y0)(x0,y0)(x,y)(x,y)Text is not SVG - cannot display由于估值拟合线是直线那么,已知(x0,y0)和(x1,y1),以及x到两点的距离,对y进行计算。

\[\begin{split}&\frac{y_1-y_0}{x_1-x_0}= \frac{y-y_0}{x-x_0} \\ &y = y_0 + \frac{(y_1-y_0)*(x-x_0)}{x_1-x_0}\end{split}\]
对正弦函数进行估值:
(x1,y1)(x1,y1)(x0,y0)(x0,y0)(x,y)(x,y)(x2,y2)(x2,y2)Text is not SVG - cannot display其中(x,y)表示估算值,(x2,y2)表示真实值,误差为y2-y,即当x1-x0越小,估算值越准确。样本点越多越精确。
2.样本生成

以下matlab代码用于生成正弦函数样本值,用于进行数据估算。
clc,clear,close all
%% 生成 rom 数据
Width=16;
Depth=256;
phi=linspace(0,2*pi,Depth+1);
phi=phi(1:end-1)';
cos_sig=cos(phi);
cos_sig=floor(cos_sig*(2^(Width-1)-1));
plot(cos_sig)
%% 生成.coe文件
filename='.\cos_rom.coe';
fid = fopen(filename,'w');
radix = 10;
fprintf(fid,"memory_initialization_radix=%d;\n",radix); %使用的进制
fprintf(fid,"memory_initialization_vector=");
for i=1:size(cos_sig,1)
    fprintf(fid,"\n%d",cos_sig(i));
end
fprintf(fid,";");
fclose(fid);3.verilog实现线性插值

以下将使用参数:样本深度256,相位最大值65536进行讲解。
​        对某一个点进行线性估值的时候,我们需要知道当前点在样本中对应相应点的邻近点。样本邻近两点相位差65536/256 = 256,假设插值相位位置为phase,则相邻点为floor(phase/256)和floor(phase/256)+1,floor表示向下取整,rom表示查找表数据。
那么

\[\begin{equation}y = y_0 + \frac{(y_1-y_0)*(x-x_0)}{x_1-x_0} = rom(floor(phase/256)) + \frac{(rom(floor(phase/256) + 1)-rom(floor(phase/256)))*(phase-floor(phase/256)*256)}{256}\end{equation}\]
以下为VERILOG代码实现:
`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // // Create Date: 2025/03/29 15:47:50// Design Name: // Module Name: cos_gen_pipeline// Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:// //////////////////////////////////////////////////////////////////////////////////module cos_gen_pipeline(    input                          clk   ,    input               rst   ,    input               valid   ,          input                  phase   ,        //相位,0~65535对应0~2pi)    output            rdy   ,       output        reg         cos_out    );    regvalid_d;    always @(posedge clk) begin      if(rst)begin            valid_d        8)    ;    assign        addr2        = (phase>>8)+1;    assign        phase1        = addr1
页: [1]
查看完整版本: verilog利用线性插值实现正弦波生成器(dds)