Menu Close

Vivado下锯齿波通过ROM 查找表转换成正弦波

正弦波(sine wave)在工程中有着重要的意义,因为正弦波是交流信号变化的最基本和最常见的波形,并且傅里叶定理指出所有可能的波形都可以由无数个正弦波组成。

正弦波也在有电感和电容的振荡电路(oscillator circuit)中自然产生。 如果将电容和电感以正确的方向放置在电路中,则电路将产生与电路中电感和电容的量成正比的正弦波。 因此,正弦波在许多电路和设备中自然产生,这也是工程师对它们进行研究的原因。在数字电路中,正弦波可以直接由EDA软件生成,本文介绍Vivado下一种常见的使用锯齿波(sawtooth wave)生成正弦波的方法。图1所示是正弦波和锯齿波。

 

图 1 (1)正弦波

图 1 (2)锯齿波

 

之前的文章中介绍了Vivado下关于ROM的使用,参考下列文章了解更多信息。

 

1.工程设计思路

本文将使用在Verilog中常见的锯齿波,通过ROM查找表,生成正弦波。主要做法是将连续的正弦波离散化,并将离散化后,一个周期内的幅值数据全部转化成非负数据,储存进ROM,在Verilog中使用递增的地址(对应为锯齿波)控制ROM中读出正弦波数据,并在仿真中用波形模拟观察结果,如图2所示。图2中红色的线是正弦波被相同周期的锯齿波上的点采样得到的离散值。

 

图2 使用锯齿波采样正弦波

 

 

2.工程建立步骤

(1)生成相应的*.coe文件

这里使用的是Vivado的仿真工程来生成*.coe文件,关于Vivado仿真工程生成coe/mif文件的信息,参见文章Verilog 仿真工程应用-生成coe/mif 文件。

代码如下:


 

注意这行代码:


SAMPLE_AMPLITUDE是通过(2**INPUT_DATA_WID)/2计算出来的。例如,数据宽度为8位时,可表达的无符号数量程是(0,2^8 -1 )= (0,255),那么正弦函数的峰峰值(peak to peak amplitude)应该是255,那么该正弦波的量程应该是(-128,127)。这里为了换算方便,舍弃最小值(-127,127),并将整个正弦波向上平移127,使其量程变为(0,254)。

这就是公式是标红部分所表达的逻辑:


注意生成正弦波使用的是Verilog的系统函数$sin(不可综合,只可在仿真中使用)。数据深度= INPUT_DATA_DEPTH,表示在正弦波一个周期内的采样点个数,例如,将正弦波的输入分为256份,INPUT_DATA_DEPTH= 256。在(0,2*pi)一个周期内每次采样的点位置应该是

这里特别需要注意的是:i是范围在(0,255)之间的整数,i/256的结果永远是0,这里可以通过交换乘除法的位置,将整数运算结果类型转换到实数范围,所以可以执行

因为Verilog下没有π,所以这里使用了3.1415926近似值,如果对精度有更高要求,可以使用更精确的值。注意这个时候 i X 3.1415926 的结果是用实数表示的,即使之后再除以256,结果也不是整数。之后的运算都是有小数部分,最后的结果也是由实数temp承接。

生成的*.coe文件如下(注册用户可下载):

[content_control] test.zip [/content_control]

图 3  生成*.coe文件部分截图

注意下列代码生成*.coe文件的位置指示的是…\verilog_coe_mif\verilog_coe_mif.sim\sim_1\behav\xsim 的往前数第三级目录,即…\verilog_coe_mif\verilog_coe_mif.sim


 

(2)生成ROM IP核

这里选用的是Block Memory Generator,在Interface Type处选择 Native,Memory Type处选择Single Port ROM,如图4所示:

图 4

 

Port A Width 选择8,Port A Depth选择256。Enable Port Type选择Always Enabled,勾选Primitives Output Register。

图 5

 

在Memory Initialization下勾选Load Init File,并将上面仿真工程生成的test.coe文件装载,完成ROM IP核的生成。

图 6

 

(3)顶层例化文件

例化文件如下所示:


 

注意这里


表示的是生成最大幅值为255,周期为256个时钟周期的锯齿波。

 

3.工程仿真

仿真程序如下:


 

仿真波形如下:

图 7

 

从仿真图中可以看出ROM的输出比地址要慢两个时钟周期,符合预期结果。并且地址中的值与*.coe文件对比也是正确的。

接下来,观察输入和输出的波形,右键点击data和addr,选择Waveform Style > Analog,如图所示。

图 8

最终的波形图如下所示,注意需要缩小时间范围来观察,因为一个完整的正弦波形需要占用5 us左右:

图 9 仿真波形

 

4.扩展实验-自建sine函数IP

前文提到过$sin函数是系统函数,只可进行仿真,不能进行综合。如果在实体程序中需要使用sine函数,需要在工程中自建。有了前文实验的基础,实现起来并不难。接下来,就带领大家做一个扩展工程,建立一个可以综合的sine函数。

工程主要构成如下:

  • 由Vivado仿真工程采样系统函数$sin生成的*.coe文件
  • 使用ROM IP核装载*.coe文件
  • 在顶层工程中将ROM地址(锯齿波)输入ROM IP核,读出ROM中存储的波形离散点,组合变化后生成相应的正弦波后输出

(1)工程设计

  • 通过Vivado仿真工程采样$sin系统函数。采样间隔是1度,采样区间在[0,90] (以360度为一个正弦函数周期划分),幅值为 127,如图10所示。这里利用了正弦函数波形的规律,只采样连续的1/4波形,然后在适当变换后还原一个完整周期的波形。这样做可以节省内存资源。

图 10 采样区间和采样递增区间

 

  • 通过参数传递,可以选择将ROM中的sine函数的幅值拉伸;同时也可以选择波形的符号:波形可以和原始的正弦函数一样,既有正值,也有负值;或是全为正值,如图11所示。

图 11 选择波形的符号

 

(2)工程建立步骤

  • 稍微修改下用来生成*.coe文件的Vivado的仿真工程,工程如下:


 

修改的位置主要如下:


注意这里仿真重新生成的*.coe文件,需要再次加载到ROM IP核中(以防Vivado使用之前缓存住的IP核信息)。

 

  • sine函数模块

顶层模块代码如下:


 

在上面的模块中主要将ROM IP核中的结果读出来,并由1/4周期的波形,拼凑出一个完整的时钟周期。并根据传递进来的参数进行波形幅值,符号的变换。

 

(3)工程仿真结果

仿真工程代码如下:


 

仿真波形如图12所示:其中绿色的波形rom_data是从ROM IP核中读出来的数据,注意这个时候还没有加上符号,蓝色的波形signed_rom_data已经将波形范围调整为[-127,127],粉色的波形是根据仿真时传递的幅度和符号进行调整后的波形。其中,可以明显的看到粉色波形amplified_data全为正,蓝色波形signed_rom_data有负值(见黄色光标处对应的值)。

 

图 12

 

图12中黄色光标停留显示的是粉色波形amplified_data和蓝色波形signed_rom_data的最低值,图13显示的是两个波形的最大值。可以看出经过放大后,粉色波形amplified_data最大值由蓝色波形signed_rom_data的127放大到1022(因为WAVE_AMPLITUDE_WIDTH为10)。

图 13

 

接下来,试着修改下传入参数WAVE_SIGN , 由“POSITIVE” 改为“NEGATIVE_POSITIVE”,WAVE_AMPLITUDE_WIDTH不变,还是设为10。仿真结果如图14所示:

图 14

 

从图14中可以看出粉色波形amplified_data的符号有负值,粉色波形amplified_data最低值由图12的0变为了-511。图15中可以看出粉色波形amplified_data的最大值是511。

图15

图12-13,对比图14-15,可以看出同样WAVE_AMPLITUDE_WIDTH=10的波形,WAVE_SIGN 为“POSITIVE”时,生成波形的量程是[0,1022];WAVE_SIGN 为“NEGATIVE_POSITIVE”时,生成波形的量程是[-511,511],符合实验的设计。

通过分析以上波形,可以看出自建sine函数IP可以正确工作,并且可以控制传入参数WAVE_SIGN ,WAVE_AMPLITUDE_WIDTH,来控制最终生成波形的幅值和符号。之后,如果需要在实体工程使用$sin函数,可以用这个自建sine函数IP,并且可以根据当前项目的需要,自行调整。如果需要更高精度的sine函数,可以将采样间隔缩小,如从每一度采一次样变为每0.5度采一次样。

5.实验思考和讨论

  • 将INPUT_DATA_DEPTH 不同值(离散采样点多和少)或INPUT_DATA_WID不同值(采样数据精度不同)得到的正弦波比较并分析。
  • 利用*.coe文件,使用ROM生成余弦波,双曲线正弦波等。
Posted in FPGA, FPGA 教材教案, FPGA开发板, Verilog, Vivado, Vivado, 开发工具, 开发工具, 开发板, 开发语言, 教材与教案, 文章, 编程语言