我是靠谱客的博主 贤惠羊,最近开发中收集的这篇文章主要介绍Xilinx Zynq实现任意波形发生器仿真,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

       DDS(Direct Digital Synthesizer)直接数字式频率合成器,是一种新型频率合成技术,具有低成本、低功耗、高分辨率、相对带宽大和频率转换时间短等优点。较容易实现频率、相位以及幅度的数控调制,广泛应用在电信与电子仪器和通信领域。波形发生器是一种数据信号发生器,在调试硬件时,常常需要加入一些信号,以观察电路工作是否正常。加入的信号有:正弦波、三角波、方波和任意波形等。

      其中设计方案如下图所示,我们将所需要的信号存在ROM中,当需要信号的时候,FPGA从ROM中读取信号,最后经过DA芯片转换,得到我们所需要的信号。在本文中,只介绍DDS形成数字信号的仿真过程,所用的FPGA为Xilinx Zynq7020,开发环境为Vivado 2015.4,以及matlab 2017。

                            

1.建立vivado工程

2.例化IP(dds_ddr_0)

`timescale 1ns / 1ps
module dds_addr (clk, rst_n, addr_out);
input clk, rst_n;
//系统时钟复位
output [7:0] addr_out;
//输出的地址,对应到ROM内的数据
parameter N = 32;
parameter PWORD = 128;
//相位控制字 (x/360)*256
parameter FWORD = 429497; //频率控制字F_out=B*(F_clk/2**32),fword=B
//5KHZ
reg [N-1:0] addr;
//32位累加器
always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
addr <= 0;
end
else
begin
/*每隔fword的大小,输出一位地址,若频率控制字FWORD等于2,那么地址计数器输出的就依次是0,2,4.....*/
addr <= addr + FWORD;
end
end
/*将累加器的地址的高八位赋值给输出的地址(ROM的地址*/
assign addr_out = addr[N-1:N-8] + PWORD;
endmodule 

            将此Verilog代码例化为IP核,添加至工程中。(在vivado中例化IP的教程可以参考:                    https://blog.csdn.net/FPGADesigner/article/details/75309278)

3.添加Vivado自带ROM的IP核(rom)

这里的rom.coe文件是存放在rom中的波形信息,用matlab生成,以下为matlab中生成正弦信号的程序。

clear
clc
n = 0:255 ;
yn = sin(2*pi/256*n) ;
yn = round((yn+1)*127);
plot(n,yn);
fid = fopen('rom.coe','wt');
fprintf(fid,'memory_initialization_radix = 10;nmemory_initialization_vector = ');
for i = 1 : 256
if mod(i-1,8) == 0
fprintf(fid,'n');
end
fprintf(fid,'%4d,',yn(i));
end

                                                    

     题外话:一些原始数据需要满足断电不丢失的的需求,要存储在ROM里,而在FPGA中,一般存入ROM中的文件格式有.mif、.hex、.coe这三种格式,.hex、.coe格式一般是用于Xilinx版本,.mif、.hex格式一般用于altera版本的ROM。

4.新建主程序(dds_main)

在新建的dds_main文件中添加以下代码:

`timescale 1ns / 1ps
module dds_main (clk, rst_n, q);
input clk, rst_n;
//系统时钟复位
output [7:0] q;
//输出波形数据
wire [7:0] addr_out;
//8位地址,对应到ROM内的数据
/*****相位累加器模块*****/
dds_addr_0 dds_addr_inst (
.clk(clk),
// input wire clk
.rst_n(rst_n),
// input wire rst_n
.addr_out(addr_out)
// output wire [7 : 0] addr_out
);
/*****波形数据模块*****/
rom rom_inst (
.clka(clk),
// input wire clka
.addra(addr_out),
// input wire [7 : 0] addra
.douta(q)
// output wire [7 : 0] douta
);
endmodule 

其中添加例化的IP进工程的方法为:

(1)在IP_Source中打开dds_addr_0.veo文件。

(2)复制dds_addr.veo代码中标红的部分。

(3)在主程序中粘贴代码,并修改名称和信号名称。

                                     

5.添加testbench文件

同上面方法一样建立dds_testbench文件,代码如下所示:

`timescale 1ns / 1ps
//
//
module dds_testbench;
reg clk, rst_n;
wire [7:0] q;
initial begin
clk = 1;
rst_n = 0;
#200.1
rst_n = 1;
#50_000_000 $stop;
end
dds_main dds_dut(
.clk(clk),
.rst_n(rst_n),
.q(q)
);
always #10 clk = ~clk;
endmodule 

最终工程如下所示:

6.仿真

 配置没有问题就可以点击“Run Simulation”,开始仿真。   

                       

最终仿真结果如下:     

   注意:上面显示数字为十六进制,而在上面用matlab生成的.coe文件为十进制。若想生成.MIF文件的小伙伴可以用一个小工具生成,很方便,链接为:https://pan.baidu.com/s/1I7IffSSBXQQ4Bxziylw5vw)  

借鉴了博客上很多小伙伴的资料,在这里一并感谢!

工程文件地址:https://github.com/EdwardBao1006/DA_ZYNQ 

最后

以上就是贤惠羊为你收集整理的Xilinx Zynq实现任意波形发生器仿真的全部内容,希望文章能够帮你解决Xilinx Zynq实现任意波形发生器仿真所遇到的程序开发问题。

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

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

评论列表共有 0 条评论

立即
投稿
返回
顶部