EDA/IC设计
一、实验内容
在FPGA上设计一个DDS模块,在DE0 开发板上运行,在FPGA芯片内部合成出数字波形即可。不用输出模拟信号,本模块满足以下条件:
使用板载晶振的50MHz时钟,合成以下频率的信号
- 1 、500KHz 正弦波信号。 2、1MHz 正弦波信号。 3、3MHz 正弦波信号。
-频率字字长32位,波表ROM尺寸为 10比特地址,1024个word
- 波形格式为2补码格式,12比特量化
- 每个CLK输出一个有效样点。
- 输入信号为频率字和频率字输入使能信号
- 使用板载的拨码开关(Switch)控制生成的波形信号的不同频率。
二、设计思路RTL电路图
设计中根据DDS输出波形频率的计算公式:
确定输出频率。
上式中为输出频率,为输入频率,即为系统基准时钟频率50MHz。m为地址加法器的宽度,K为频率控制字。设计中通过控制K的大小控制输出频率,由于K只能取整数,输出频率可能会有一定偏差。
三、Quartus扫描生成的RTL电路图
四、实验相关程序代码
1、地址加法器模块
module addr_cnt(CLK,sel_K,CLR,En,ROMaddr);
input CLK;
input [1:0] sel_K;
input En,CLR;
output [9:0] ROMaddr;
reg [9:0] cnt_out;
assign ROMaddr=cnt_out;
always @ (posedge CLK or negedge CLR)
if(~CLR)
cnt_out《=10‘d0;
else if(~En)
cnt_out《=cnt_out;
else begin
case(sel_K)
2’b00:cnt_out《=cnt_out+10‘b00000_01010;
2’b01:cnt_out《=cnt_out+10‘b00000_10100;
default:cnt_out《=cnt_out+10’b00001_11101;
endcase
end
endmodule123456789101112131415161718192021222324
2、顶层设计模块
module Sine_Signal (Dout,ROMaddr,CLK,CLR,En,sel_K); //顶层模块
output [11:0] Dout; //离散的正弦波形输出
output [9:0] ROMaddr; //ROM的地址
input CLK /* synthesis chip_pin=“G21” */ ; //50MHz时钟
input CLR /* synthesis chip_pin=“H2” */ ; //清零KEY0
input En /* synthesis chip_pin=“J6” */; //使能SW0
input [1:0] sel_K /* synthesis chip_pin=“H6,H5” */; //输出频率控制字选择SW2、SW1
addr_cnt U0_inst( //实例引用地址计数器模块
.CLK(CLK),
.CLR(CLR),
.En(En),
.sel_K(sel_K),
.ROMaddr(ROMaddr)
);
myROM myROM_inst( //实例引用上面定制的ROM模块
.address(ROMaddr), //ROM的地址输入端
.clken(En),
.clock(CLK), //时钟输入端
.q(Dout) //数据输出端
);
endmodule123456789101112131415161718192021
3、正弦波形存储模块C语言程序
#include《stdio.h》
#include《math.h》
#define PI 3.141593
#define DEPTH 1024 /* 数据深度,即存储单元的个数 */
#define WIDTH 12 /* 存储单元的宽度 */
int main(void)
{
int n,temp;
float v;
FILE * fp;
/* 建立文件名为sine1024.mif新文件,允许写入数据,
文件名随意,但扩展名必须为.mif */
fp = fopen(“sine1024.mif”,“w+”);
if(NULL==fp)
printf(“Can not creat file! ”);
else
{
printf(“File created successfully! ”);
/* 生成文件头,注意不要忘了“;” */
fprintf(fp,“DEPTH=%d; ”,DEPTH);
fprintf(fp,“WIDTH=%d; ”,WIDTH);
fprintf(fp,“ADDRESS_RADIX = HEX; ”);
fprintf(fp,“DATA_RADIX = HEX; ”);
fprintf(fp,“CONTENT ”);
fprintf(fp,“BEGIN ”);
/* 以十六进制输出地址和数据 */
for(n=0;n《DEPTH;n++)
{
/* 周期为1024个点的正弦波 */
v=sin(2*PI*n/DEPTH);
/* 将-1~1之间的正弦波的值扩展到0~4095之间 */
temp=(int)((v+1)*4095/2); //v+1将数值平移到0~2之间
/* 以十六进制输出地址和数据 */
fprintf(fp,“%x : %x; ”,n,temp);
}
fprintf(fp,“END; ”);
fclose(fp); //关闭文件
}
}123456789101112131415161718192021222324252627282930313233343536373839
4、matlab正弦波频谱分析程序
将signal tap采集的正弦波数据生成.txt文件保存,导入到matlab中分析频谱。
clear all; close all;
varnum; %调用signal tap 采集的正弦波数据,列矢量
signal=transpose(VarName); %转置
fs=50E6; %采样频率
N=1024; %采样点数
t=[0:1/fs:(N-1)/fs]; %采样时刻
figure(1);plot(t,signal);
title(‘正弦波信号’);
xlabel(‘Time (s)’);
ylabel(‘Magnitude’);
Y = fft(signal,N); %做FFT变换
Ayy = abs(Y); %取模
Ayy=Ayy/(N/2); %换算成实际的幅度
Ayy(1)=Ayy(1)/2;
F=([1:N]-1)*fs/N; %换算成实际的频率值,Fn=(n-1)*Fs/N
figure(2);
stem(F(1:N/2),Ayy(1:N/2)); %显示换算后的FFT模值结果
axis([0 5E6 0 2500]);
title(‘正弦信号频谱图’);
xlabel(‘Frequency (Hz)’);
ylabel(‘Magnitude’);12345678910111213141516171819202122
五、实验结果
1、signal tap 数据截图
(1)f1=500kHz正弦波,地址位宽m=10,频率控制字K=10
(2)f2=1MHz正弦波,地址位宽m=10,频率控制字K=20
(2)f2=3MHz正弦波,地址位宽m=10,频率控制字K=61
2、matlab频谱分析
由频谱图可以看出DDS输出的频率略小于实验要求的频率。这是由于实验中频率控制字只能取整数,略去了小数位,实际取值小于理论计算值。实验结果与理论推算结果是一致的。
全部0条评论
快来发表一下你的评论吧 !