基于FPGA的AM调制与解调(Verilog语⾔)
⼀、概述
说是概述,但是你还是得必须容我先瞎扯⼀番的。⼜是课程的作业,要通过FPGA实现AM信号的产⽣与解调。我们最开始⼿上是有硬件的板卡的,型号是叫Nexys Video。(当然现在被⽼师收⾛了,所以下⾯的程序只能讲解到仿真的层次)要求是通过VIO控制载波频率、调制信号频率、调制深度可调,然后通过ILA观察AM信号和解调后的信号。我记得载波信号的频率要求是1M~10M,调制信号的频率要求是1K~10K,调制深度从0到1、步进0.1。当然他规定了⼀定的精度。(VIO与ILA只能通过硬件板卡实现,下⾯的讲解中演⽰不了)。这个程序虽然说不算难吧,但是我确实忙活了⼀个星期才搞明⽩,每天都得超过12点睡觉。最让我崩溃的是:考试验收的那⼀天,我竟然忘记把昨天晚上最后改好的程序考到U盘上来,⼜是各种原因不能回去拿电脑。我的那个⼼凉的。。。从头⼀点点开始写啊,然后还有各种各样的波折,害的我都以为这门课是要来年重修的节奏。还好,最后⼀刻顺利完成。好,瞎扯到此为⽌,下⾯进⼊正题。
⼆、平台
软件: Vivado 2016.4
硬件:Nexys Video(这个不重要)
三、要求
为了更好的说明下⾯⼀些参数设定的意义,把我们课程的部分要求贴上来
完成AM信号调制和解调功能,具体要求如下:
(1)载波信号频率范围:1M-10MHz,分辨率0.01MHz;
(2)调制信号为单频正弦波信号,频率范围:1kHz-10kHz,分辨率0.01kHz;
(3)调制深度0-1.0,步进0.1,精度优于5%;
(4)调制信号和解调信号位宽为8位,AM信号16位,其他信号位宽⾃定义。
四、原理
虽然这部分简单,但却是最最重要的,把这部分看懂,所有的程序也就明⽩了。
1. AM信号:(A+m a*cos(w0t))*cos(w c t)
⼀步步来嘛,⾸先肯定要产⽣两个频率不同的余弦波cos(w0t),cos(w c t)。⽴马想到调⽤系统⾃带
的DDS IP核来实现嘛,这是最简单的⽅法。我在⽹上还看到⼀个⾃⼰通过导coe⽂件来模拟DDS然后来产⽣余弦波的,这⾥就不说了。
产⽣两个余弦波后,再来两个乘法器(现在没有彻底想明⽩“*”这个符号和乘法器的区别,这⾥就不说了,我还是乖乖的调系统的乘法器吧)、⼀个加法器(后⾯程序直接⽤的“+”号,没有⽤加法器ip 核),运算⼀把不就搞定了吗。
2.AM信号⽣成中的注意点(这个有点绕)
⾸先看⼀下调制深度的问题。调制深度通常为已调波的最⼤振幅与最⼩振幅之差对载波最⼤振幅与最⼩振幅之和的⽐。就是⽣成AM波包络的最⼤值与最⼩值之差除以最⼤值与最⼩值之和。包络其实就是(A+m a*cos(w0t))。它的最⼤值是
A+m a,最⼩值是A-m a。最后可以算出调制深度就是m a/A。A为1时,调制深度就是m a,其实只要A的值和后⾯的余弦波的最⼤值是相同的,调制深度就会为m a,为0~1之间。
但是有⼀个重要的问题不要忘了,就是在硬件描述语⾔中表⽰⼩数并不像C语⾔那么简单直接(其实所谓的⼩数只是我们对每个字节中的0和1的解释⽅式不同⽽已,在硬件描述语⾔中,我们会很⾃然的会把0和1两种状态直接转换为⼗进制,⽐如8'b0000_0011,我们会很⾃然的把它看做3,那么这样的
话,硬件描述语⾔中是没有⼩数的)。我们上⾯⽣成的余弦信号cos(w0t)并不是在0~1范围内。假如我们让DDS的输出位宽为8位,那么这个余弦信号的幅度⼤⼩-128~127。我们就当做是-127~127,那么这⾥先假设A为127。再来再算⼀下调制深度。这时包络最⼤值为127+m a*127,最⼩值为127-m a*127。最后调制深度还会是m a,这个m a的范围还是0~1。m a是从0~1之间变的话,还是有不能直接表⽰⼩数这个问题。有两种解决⽅法:
1.让A=1270,也就是包络最⼤值为1270+m a*127,最⼩值1270+m a*127。算出调制深度最后应该为m a/10的。这时便可以设
定m a为1~10来改变调制深度了。
2,.下⾯的程序是⽤的是以下这种⽅法。⽐如说(127*256)>>8(要知道右移⼀位相等于除2,右移8位的话等于除以256),就相当于127*1。⽽(127*128)>>8就相当于127*0.5=63。也就是这样产⽣我们的⼩数m a的,通过设定⼀个8位的变量depth_con乘以127,然后将得到的结果右移8位,那么我们就可以通过depth_con来控制调制深度depth了。他们的关系也就是depth=depth_con/256。当然这些推理是在保持A=127的情况下进⾏的,也就是AM信号包络为127+(depth_con*COS)>>8。(COS是DDS产⽣的8位信号)
前⾯的127+(depth_con*COS)>>8得到后,再经过乘法器乘以8位的载波就⾏了,这个乘法器的输
出的就是我们要的AM信号了。这⾥还有⼀点就是127+(depth_con*COS)>>8的结果的范围是0~256。这时可以将乘法器的⼀个输⼊改为8⽆符号数,正好可以满⾜0~256的范围。乘以8位的载波信号后,得到的AM波正好是我们要求的那样,输出16位的AM波。(主要就是因为这才选的这种⽅法)
3.AM信号的解调
⾸先来谈⼀下解调⽅法:
相⼲解调,就是在AM波的基础上再乘以载波⼀次,然后经过低通滤波,隔直便可以得到我们要的解调信号。在频域分析也就是乘以载波后有了会产⽣⼀个w0的频率分量和⼏个⾼频分量,将这⼏个⾼频分量滤除便可以得到原始的调制信号。这个原理简单。
然⽽我⽤的还是下⾯的这种⽅法不知道算不算包络解调(我觉得不算吧),就是将AM波进⾏全波整流(就是取绝对值)或者半波整流(就是把负半轴的信号不要),然后低通滤波便可以得到我们要的解调信号了。这个原理最开始我是百思不得其解,因为最开始不知听谁说这种⽅法算包络解调,所以我⼀直在想为什么AM信号直接低通滤波后提取不了包络,⽽整流后低通滤波就可以提取包络了呢?但是其实再回头看,原理也挺简单。跟本不算提取包络吧。下⾯是AM信号进⾏全波整流后的频谱图(MATLAB)。调制信号频率为1KHz,载波频率为100KHz。
放⼤前
放⼤后
可以看出全波整流后的AM波在调制信号频率处有了新的频率分量,所以再经过低通滤波就可以得到最开始的调制信号。
理论推导的话,这⼏天也⼤概搞明⽩了。⾸先(1+cosw0t)coswct全波整流后得到(1+cosw0t)|coswct|(肯定要保
证(1+cosw0t)⼤于0的)
其实你只要得到|cosw c t|的傅⾥叶级数就可以明⽩了。|cosw c t|的傅⾥叶级数具体我记不清了,但是我记得展开后有⼀个常数项2/pi,然后加上后⾯的⼀⼤坨(上⽹上搜⼀下就知道了)。主要就是有了这个常数项2/pi,它和前⾯的(1+cosw0t)相乘后就会得到w0的频率分量,也就是我们调制信号的频率。然后滤波⼀下,你懂得。
⾄于半波整流⼀样分析吧。
再来说⼀下滤波器在vivado⾥的实现
直接调⽤系统⾃带的fir IP核,点开后第⼀个界⾯。选COE⽂件,然后导⼊。
这个COE⽂件可以通过MATLAB⽣成(我也只知道这⼀种⽅式)。在MATLAB窗⼝输⼊命令:》fdatool
有些东西并不⼀定按照我这么选,⽐如FIR滤波器的种类(Window,Hamming),选其余的应该没什么⼤问题。主要是要保证截⽌频率,我设的是20K,因为要求调制信号的频率是1~10K,我稍微设⾼了⼀点。采样频率的话最少⽐载波频率⼤2倍(采样定理)我设的100M
还要进⾏量化后才能导出COE⽂件。如下
选择Fixed-point后可能要等⼏秒钟。稍微等⼀会。量化完后就可以导出了,就是点Targets⾥的选项,
就不给图了
fir IP核第⼆,第三个设置窗⼝基本上不⽤改什么。下⾯的Input Sampling Frequency最好不要太⼤。我设成100时,程序运⾏好久都运⾏不完,太慢。
fir IP核设置完后,基本就没什么说的了。直接给程序吧,对照着前⾯的原理看,看懂应该不是问题。
五、程序
代码的话,先直接全部贴上来吧,还是⽐较简单的,不像我最开始从⽹上看到的⼀个,各种各样的模块叠加在⼀起。⼀些注意点讲解在后⾯。
`timescale 1ns / 1ps
//
// Company: Haerbin Engineering University
// Engineer: huangshang
//
// Create Date: 2018/05/16 14:02:46
// Design Name:
// Module Name: AM_generate2modulate
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
/
/
module AM_generate2(
input sysclk
);
wire [15:0] AM_out;
wire [15:0] carrier_con=2620 ;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论