我是靠谱客的博主 难过冰淇淋,最近开发中收集的这篇文章主要介绍verilog设计简易正弦波信号发生器_FPGA学习(一)——产生频率可控的正弦波,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

c93d76e117ca1b24110917b7adde36cb.png

2018.5.17更新如下

作为小透明,没想到随手一写的学习过程也能被看见,看到有人点赞也还是很高兴的,希望能以后自己忘了,还能来看懂,如果对大家能有所帮助,那就再好不过了。

对于输出的正弦波周期有两种算法,在这里记录一下。

因为和昨天使用的不是同一个文件,所以名称会和昨天的不一样,不过原理一样。

另外,在仿真的时候可以不用添加约束文件,只需要仿真时可以直接跳过,如果需要下载进板子的话就必须要写了。下一篇会介绍。

1.使用DDS输出的最高位去计算,具体操作如图

eb7b4531ec0208faa6ae4c8a322e029f.png
步骤1.2.3,注意黄线的位置和数值

点击两次上图3的图标

b46039192c6ba1fac7e66894c1eaa1d6.png
根据两次的数值就能算出输出正弦波的周期

可能会觉得频率控制字可以控制输出波形的频率,而输出位宽又可以计算输出波形周期,那改变输出波形会影响什么呢?会影响输出波形周期吗?答案是不会。

具体看图,我将输出位宽改为10位的仿真结果。

7a752999f62ac0d615dc4f5c156d13c0.png
圈圈圈

输出位宽影响的是输出波形的幅度(0^◇^0)/

了解DDS的原理就明白了。

2.第二种就是昨天解释原理时用频率控制字控制输出频率时,fre_word取1的值。

具体算法见原答案。

两种区别就是一个取最高位,一个取最低位,刚开始容易理不清。


原答案如下

信号调制和解调功能。写下其中过程当做自己的学习记录吧。本篇讲的是如何产生一个正弦波。

  1. 使用的软件是Vivado 2016.4
  2. 实验室板卡是Nexys Video

1.原理说明

采用的是自带DDS IP核,DDS直接数字式频率合成器(Direct Digital Synthesizer),相信所有人看到这个名字就觉得不会陌生。

DDS由频率控制字(Frequency Control Word)寄存器、相位累加器(Phase Accumulator)和正余弦查找表(Sine/Cosine LUT)三部分组成,通过控制相位累加器的位宽和查找表的位宽,可以实现不同频率和动态范围的正弦信号的产生。

关于DDS是如何产生我们需要的波形信号可以查看这篇文章:

用FPGA实现DDS任意波形发生器 | 电子创新网赛灵思中文社区​xilinx.eetrend.com
a37383c052ff5eb48d86c8f75343cc06.png

而我们现在不用关心太多原理,经过实验的过程,自然就能明白其工作原理。

我们只需要知道如何控制其输出频率就行了,首先记住两个术语(jargon):

a. 相位累加器:Phase = Phase + fre_word,可以暂且理解为i = i + 1一样的东西。

b. 频率控制字:fre_word,这个东西的值直接影响输出信号的频率。

我们的输出频率就是由fre_word来控制。

具体怎么算的呢?

DDS核频率分辨率计算公式如下:

fff5ac39345e0bed8e921c97034f1ac3.png

其中Δθ就是我们的频率控制字取值后文用fre_word表示,Bθ(n)是相位累加器位宽后文用B表示,fclk为DDS工作时钟。

频率分辨率就是当Δθ=1时的fout。

先假如我们需要的信号频率范围:1M-10MHz,分辨率0.01MHz。

取Δθ=1,fout=0.01MHz,B=10bit,我们可得DDS工作时钟fclk=10.24MHz。

到这里我们就知道,产生一个正弦波信号需要2部分即可:

  1. 时钟分频器(因为我们的软件系统时钟为100MHz,而我们算出的DDS工作时钟为10.24MHz)
  2. DDS IP核

2.具体操作过程

打开vivado,新建工程

2c840a7aa8ef935a9c1f21aaa41bc704.png

给工程命名,路径不能出现中文

1469949d1b79a27b2b8c5b76ded80261.png

如图勾选,我们后面自己建源文件

54147f4f2221682c284bdbea51b4542c.png

选择板卡(这个板卡需要在安装后自己添加了才会有),点击接下来的next,finish。

05aa0da6d3387339a50b182e66521663.png

添加源文件

0856be93e38eec5d5bbe8813c17e95fc.png

取名

e62f4487a57b039ca50dae16d018da73.png

现在不用添加管脚,点击ok,yes即可

a7132280ca399a691ca60b0d3627a791.png

添加IP 核,找到DDS,蓝色的都是一样的,随便选一个双击

2c1fb14f64827c070fab9f8211df044d.png

命名,选择dds工作时钟10.24MHz,选择使用硬件参数,位宽根据前面计算的结果填写(相位位宽就是我们的频率控制字位宽,而输出位宽影响ROM表深度 (大小为

表示输出的正弦波一个周期的采样值,因为DDS是数字信号经DA输出模拟信号))。

b67e2388e7e2d5403b75d6efa04bd40e.png

选择可编程(因为由fre_word控制),输出sine,不需要观测相位输出

f7a5c95d4a37d042c645def20071fff1.png

因为是10位,改为0000000001

708faac11489c8176766387ee46a57a1.png

查看summary,可知最小频率为0.01MHz,点击ok

fa249bedcbf1b9f2826d2b792185ed79.png

点击生成

8c8149e2b97e04eb6adb43773bb46720.png

用时钟管理核生成时钟分频模块,步骤如图,不再描述

a030077e690e6d76cb1aeab40872105f.png

6897ef4bc0c6b73c58308159b207d05c.png

dd02ff8c43167908c9ae093e9209e881.png

03c6c03f18b1452938e4a309834d3e97.png

咦,,,,好像点击图片可以直接描述,第一次用知乎写,还不会。。。。后面的图片描述在图片下方的描述区。。。

8bf65c261aa569ed1ad966581ba3090b.png
接下来就是例化IP核,首先是时钟分频模块,双击.veo文件,因为是Verilog语言写的

56f2e40feac4b58d2a47ad9c71a03a0a.png
接下来就是例化IP核,首先是时钟分频模块,双击.veo文件(因为是Verilog语言写的),将程序复制到主程序中去

b26cd3bcf13a78551c7ad714e117d8f2.png
同样的方式例化DDS模块,修改例化模块的名字,2.3步

1252dac07fdc2d6e8701d569c906e022.png
建立顶层约束文件

955f495d00d3dd991bd9a311f156432e.png

d33163c6836fe6d7c1f0438ce25d21ba.png
添加代码,涉及到时序,说起来太麻烦,具体语句就不解释了,最后会附代码,复制就行

d745c178e782bbcff74d1683eb959536.png
添加仿真文件

c7874d363f8a0745c8621e0c8e9169f2.png
注意名称

fb045220e1b2a481256f673b309f1845.png

3343466d3b2def5f7072ffce6239ea6e.png
编写仿真代码

159bde87c27559aa2774574bc72ad0c6.png
重点重点!!!!名字一定要一样,否则会有惊喜的。mmp被坑惨了

5dfbdf9632d46e42333c033ea72aed73.png
运行仿真

c02e13ba8139f5b6471cd586872baa28.png
右键将需要观测的假如波形窗口

a104a4fefbdcd432b92c00d31a12af0c.png
选中,右键,修改为有符号数10进制表示,波形选择为模拟波形

f0085e15265a8e724e635353bc61a5f2.png
周期为100us,我们运行200us查看波形

3.代码只要所建名字一样,可以直接复制使用

主程序

顶层约束文件

set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports sysclk]
############################
#https://mp.weixin.qq.com/s/3WoAO4aHYTqTWLTnF56zMA关于时序约束#
############################
create_clock -period 10.000 -name sysclk -waveform {0.000 5.000} [get_ports sysclk]

仿真文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2018/05/16 19:29:18
// Design Name: 
// Module Name: ZXB_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module ZXB_tb(

    );
    
        reg clk;
//    wire [7:0] data;
         reg [9:0] fw_z;
        
    ZXB dut(
                .sysclk(clk),
                .fw_z(fw_z),
    //                .led(data));
    // 初始化    
    initial
    begin
        clk = 0;
        fw_z = 10'b0000000001;
    end
    
    //产生100MHz时钟信号
    always
    begin
         #5 clk = ~clk;
    end
endmodule

4.本来应该添上VIO和ILA的,不过没有板子在,写了也用不了,就不写了,大概和这个差不多,主要区别就是VIO是外部板子给信号,而仿真就是软件假装的,所以在主程序中会有所不同。会Verilog就懂了。

5.第一次写,很简单的一个功能,居然写了这么多,说明理解还不是很到位,表达也不是很简洁明了,ε=(´ο`*)))唉溜了溜了

最后

以上就是难过冰淇淋为你收集整理的verilog设计简易正弦波信号发生器_FPGA学习(一)——产生频率可控的正弦波的全部内容,希望文章能够帮你解决verilog设计简易正弦波信号发生器_FPGA学习(一)——产生频率可控的正弦波所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部