AM解调 FPGA(寻找复刻电赛电赛D题的)

设计平台

  • Quartus II10.3
  • mif产生工具
  • modelsimSE (仿真用)

DDS(直接数字式频率合成器)

从前面的内容可知,我们需要产生一个载波,并且在仿真时,我们还需要一个较低频率的正弦波信号来充当我们的调制信号,但FPGA要怎么去生成一个正弦波呢?答案是利用DDS。

  • DDS是什么呢?

Direct Digital Synthesis,直接数字频率合成器。以这个项目为例,简单来说,就是可以利用FPGA上的资源,来输入一定的频率控制字(控制具体产生频率),从而来生成一定的正弦/余弦波,有些也可以输出相位。

在Quartus II 中 有自带的DDS生成工具(NCO),在IP核向导 MegaWizard Plug-In Manager中可以找到该IP核,如图:

quartus II 中的DDS 内核 (NCO)

但在本次设计中,我们采用写ROM的形式来实现我们的DDS。

  • 如何来写ROM?
    在quartus的ROM设置向导中(只需在上面的图片中搜索rom,选择1port的即可),有以下设置:

ROM_PIC1

ROM_PIC2

其中,
1:
是设置ROM的位宽,以及深度,在这里我们选择8bits的位宽,256bits的深度,这个选项要和待会给ROM初始化文件mif的数据的宽度,深度有关,要和mif文件的内容相匹配
2:
选择block memory的类型。在这里我们不对这些类型进行讨论,选择自动。
3:
选择给输入,输出的时钟是同一个,还是两个不同的时钟。我们选择一个时钟Single clock。
4:
位于ROM Wizard界面的第三页中的Men Init中,这是是添加一个ROM初始化文件xx.mif,以便来初始化ROM中的数据内容。mif文件也有一定的格式,一般可以通过MATLAB,或者其他mif格式生成工具来生成(网上已经有很多关于mif文件生成的代码或者软件,请自行寻找,此处不作介绍)。


mif文件的格式以及部分解释如下:

DEPTH = 256;		//深度
WIDTH = 8;		//宽度
ADDRESS_RADIX = HEX;  //地址输入的数据格式
DATA_RADIX = HEX;        //数据的数据格式
CONTENT 		//初始化开始 格式为: [address] : [ data ];
	BEGIN
0000 : 0080;
0001 : 008C;
0002 : 0098;
0003 : 00A5;
0004 : 00B0;
0005 : 00BC;
...
...
...
...
[final address] : 0073;
END ;		//初始化结束,深度多少,就有多少行初始化描述

完成以上4步之后就可以点击Next按钮,在EDA界面勾选上Generate netlist选项,继续next:

ROM_PIC3

我们可以在这个界面来选择我们最后生成的文件类型,这里我选择勾选inist的文件,方便我们调用,完成后即可点击finish完成ROMIP核的设置

ROM_PIC4

接着在界面左边的Files中就可以找到我们生成的ROM了:

Files中的ROM文件

点开rom.v文件,复制模块开头的端口描述语句,就可以进行调用啦:

module sigan_rom (
	address,
	clock,
	q);

//例化模板:
sigan_rom  yourRomName(
	.address(),//[7:0]
	.clock(),
	.q()//[7:0]
	);

以上,ROM的配置介绍就到此结束。


调制信号发生模块

新建一个项目,选择好自己的器件之后,新建一个Verilog文件,取名为:modelsim_signal_generator(大家可以自己随意取名,知道是什么模块就行)

开写!那我们需要什么内容呢?
我们现在想要得到的是一个比较低频的正弦波调制信号,那我们应该怎么去规定这个频率呢?
回到DDS上,DDS生成一个波形靠的是地址按一定步进变化之后,输出的数据流组成的。我们刚才创建的ROM核也有一个addr的地址输入端,于是,我们自然而然地可以想到”输入一定步进的地址,输出一定频率的波形“。我们把这个一定步进叫做频率控制字(也有叫相位控制字)。具体的频率控制字(PINC)公式如下,在此不展开详解:

����=�������∗����2����ℎ+2

其中,Fsystem为系统时钟,Fout为DDS输出的正弦波频率,PINC为频率控制字,depth为ROM的深度。

具体代码实现如下:

//module name : modelsim_signal_generator
//module function:generate a signal for simulation
//author: wataru
//2021.11.16
module modelsim_signal_generator(
	input clk,
	input rst,
	output [7:0] signal

);

parameter PINC = 8'd3;//freqCtrlWord;fsys = 50MHZ,fout ~=146_484.375Hz 

reg[7:0] cnt;	//	pinc_cnt,counter
wire[7:0] addr;//Rom address_in 
//addr cnt
always@(posedge clk,posedge rst)begin
	if(rst)begin
		cnt <= 8'd0;
	end// if
	else begin
		cnt <= cnt + PINC; //addr ++
	end//else
end

assign addr = cnt;
//---------------------------
//rom 
sigan_rom  siganRom(
	.address(addr),//[7:0]
	.clock(clk),
	.q(signal)//[7:0]
	);
endmodule//modelsim_signal_generator

同理,我们也可以利用此代码产生一个载波:

//module name :carrier_generator
//module function : carrier generate
//author:wataru
//2021.11.16
module carrier_generator(
	input clk,
	input rst,
	output[7:0] carrier
);


parameter PINC_cARRIER = 8'd42;//freqCtrlWord

reg[7:0] cntCarrier;	//	pinc_cnt
wire[7:0] addrCarrier;//Rom address_in

//addr cnt
always@(posedge clk,posedge rst)begin
	if(rst)begin
		cntCarrier <= 8'd0;
	end// if
	else begin
		cntCarrier <= cntCarrier + PINC_cARRIER;
	end//else
end

assign addrCarrier = cntCarrier;
//-----------------------------
//rom 
sigan_rom  carrierRom(
	.address(addrCarrier),//[7:0]
	.clock(clk),
	.q(carrier)//[7:0]
	);
	
endmodule

至此,我们编写的模拟的调制波,载波已经描述完毕。


AM调制

AM调制可以通过一个乘法器来实现,非常简单。调用乘法器IP核:

LPM_MULT

乘法器模块部分设置,输出为Signed,即有符号数

数据位宽

文件输出选项

完成MULT乘法器创建之后,我们就可以把模块链接起来,创建一个AM调制波啦,顶层代码如下:

//module :top
//module function:only used for simulation
//author:wataru
//2021.11.16
module ammodtest(
						input 		 clk,
						input 		 rst,
						output[7:0] INsignal,
						output[7:0] carrier,
						output[15:0] ammodOut
);

wire[7:0] INsignal_temp;
wire[7:0] carrier_temp;
wire[15:0] ammodOut_temp;
//signal_in
modelsim_signal_generator signalIn(
	.clk(clk),
	.rst(rst),
	.signal(INsignal_temp)//unsigned

);
assign INsignal = INsignal_temp - 8'd127;//因为我的mif文件是无符号数的,要去掉一定的直流分量。
//carrier
carrier_generator carrierGenerator(
	.clk(clk),
	.rst(rst),
	.carrier(carrier_temp)//unsigned
);
assign carrier = carrier_temp - 8'd127;//因为我的mif文件是无符号数的,要去掉一定的直流分量。
//ammod
mult multmod(
	.dataa(INsignal),
	.datab(carrier),
	.result(ammodOut_temp)//[15:0] signed
	);
assign ammodOut = ammodOut_temp ;
endmodule//endmodule

至此,我们的全部模块已经编写完毕,可以编写一个tb文件来进行仿真啦!


仿真

我们这里选择使用quartus II 与modelsim进行联合仿真。这里使用quartus生成tb.vt文件。该文件为testbench文件,操作如下:

操作界面按钮

生成之后,就可以在项目的所在文件夹里面找到一个simulation的文件夹,可以在里面找到一个测试文件。通常该文件名称为[projectName.vt],如图:

文件地址

之后,选择我们的仿真工具,modelsim。(此处请参考网上关于quartus与modelsim联合仿真的教程),选择我们的testbench文件,操作如下:

步骤1

图中的是我的tb文件,请无视,请点击new

简单说一下这个界面:

1、是你的仿真文件的名字;

2、是该仿真文件中你的模块的名字;

3、是仿真文件里面调用的模块的名字,通常默认为i1,

以上3个内容均可以在生成的[projectName.vt]中找到。

设置完毕之后,打开[projectName.vt]进行编写我们所需要的仿真设置,我的改动如下:

//module function :simulation
`timescale 1 ps/ 1 ps //仿真时间,不做处理
module ammodtest_vlg_tst();

//reg eachvec; //有时钟仿真时,请注释掉这一行

reg clk;
reg rst;
// wires                                               
wire [7:0]  INsignal;
wire [15:0]  ammodOut;
wire [7:0]  carrier;
                         
ammodtest i1 (
  
	.INsignal(INsignal),
	.ammodOut(ammodOut),
	.carrier(carrier),
	.clk(clk),
	.rst(rst)
);
initial                                                
begin                                                  
                       
rst = 1;
clk =  0;
#5 rst = 0;                                                      
// --> end                                             
$display("Running testbench");                       
end                                                    
always                                                 
              
begin                                                  
                        
     #10 clk = ~clk;                                                  
//@eachvec;   //有时钟仿真时,请注释掉这一行                                           
                                          
end                                                    
endmodule

完成后,就可以对项目进行综合,综合完毕后请启动仿真:

仿真按钮

之后我们就可以在打开的modelsim的wave窗口中查看我们的波形了!效果如图:

第三个信号为调制信号,第四个信号为已调波,第五个为载波信号

到这里,我们的仿真完毕。


尾言

到这里,我们的AM调制部分就编写完毕,在下板应用时,请把模拟的调制波输入,换成自己的信号输入端,进行管脚绑定之后就可以正常使用了!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/576869.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

划重点:用这个技巧,抖音粉丝涨不停!

在这个信息爆炸的时代&#xff0c;如何在抖音上脱颖而出&#xff0c;吸引大量粉丝&#xff0c;成为了每一个创作者心中的痛。你是否曾经在发布作品后焦急等待评论&#xff0c;期待着每一次互动&#xff1f;如果你有这样的困扰&#xff0c;那么这篇文章将为你打开一扇新的大门&a…

【Claude 3 Opus】Claude 3 Opus 模型正式上线抢先体验

文章目录 1. Claude 3 Opus介绍2. Claude 3 Opus 支持的应用场景3. 申请Claude 3 Opus访问4. Claude 3 Opus初体验5. 『云上探索实验室』Bedrock 体验又更新啦6. 参考链接 1. Claude 3 Opus介绍 近期&#xff0c;亚马逊云宣布 Anthropic 的 Claude 3 Opus 模型已在 Amazon Bed…

大数据分析与应用实验(黑龙江大学)

实验一 Hadoop伪分布式实验环境搭建与WordCount程序 一、实验目的 1、学习搭建Hadoop伪分布式实验环境 2、在伪分布式实验环境下运行WordCount程序 二、实验内容 1、搭建Hadoop伪分布式实验环境&#xff0c;并安装Eclipse。 2、在Eclipse环境下&#xff0c;编写并执行Wor…

【JVM】从i++到JVM栈帧

【JVM】从i到JVM栈帧 本篇博客将用两个代码例子&#xff0c;简单认识一下JVM与栈帧结构以及其作用 从i与i说起 先不急着看i和i&#xff0c;我们来看看JVM虚拟机&#xff08;请看VCR.JPG&#xff09; 我们初学JAVA的时候一定都听到过JAVA“跨平台”的特性&#xff0c;也就是…

西瓜书学习——线性判别分析

文章目录 定义LDA的具体步骤1. 计算类内散布矩阵&#xff08;Within-Class Scatter Matrix&#xff09;2. 计算类间散布矩阵&#xff08;Between-Class Scatter Matrix&#xff09;3. 求解最佳投影向量4. 数据投影5. 分类 定义 线性判别分析&#xff08;Linear Discriminant A…

安装svn网络有问题怎么办?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

【C++进阶之路】C++11(下) —— 线程库

序言 本篇文章主要是填之前C11留下的坑以及了解与熟悉线程库&#xff0c;有读者感兴趣之前的内容的话可见「C进阶之路」专栏中标题为「C11」的内容&#xff0c;废话不多说&#xff0c;先来概括一下本文的内容&#xff0c;首先我们会从历史的角度分别谈及Linux以及Windows下的线…

JetBrains GoLand v2024.1 激活版 (Go语言集成开发IDE)

前言 JetBrains GoLand是一款专门为Go语言开发人员构建的跨平台的集成开发环境。动态错误检测和修复建议、快速安全重构、智能代码完成、无效代码检测和文档提示可以帮助新手和有经验的Go开发人员高效地创建可靠的代码。GoLand还支持JavaScript&#xff0c;TypeScript&#xf…

AIX7环境上一次艰难的Oracle打补丁经历

系统环境 AIX &#xff1a;7200-05-03-2148 Oracle&#xff1a;11.2.0.4 PSU: 11.2.0.4.201020&#xff08;31718723&#xff09; perl:5.28 问题一&#xff1a;AUTO patch #/u01/app/11.2.0/grid/OPatch/opatch auto /tmp/31718723 错误信息如下&#xff1a;匹配mos 2516761.1…

K8s: 公有镜像中心和私有镜像中心的搭建

公有镜像中心的搭建和使用 1 &#xff09;在 官方docker镜像中心推送 在 hub.docker.com 上注册账号 (国内一般访问不了&#xff0c;原因不多说) 找到 Create Repository 按钮就行仓库的创建 这样就在官方创建了一个仓库&#xff0c;比如地址为: xx/y-y xx 是我的账户名y-y 是…

MATLAB - 机器人动力学 - 质心(Center of Mass)

系列文章目录 前言 一、用法 com centerOfMass(robot) com centerOfMass(robot,configuration) [com,comJac] centerOfMass(robot,configuration) 二、说明 com centerOfMass(robot) 计算机器人模型在原点构型处相对于基础坐标系的质心位置。com centerOfMass(robot,conf…

TCP关闭连接时的一些思考

TCP协议是TCP/IP栈中最复杂的协议&#xff0c;它最大的优点是传输的可靠性&#xff0c;这通过面向连接、按序传输、超时重传、流量控制等机制保证其传输的可靠性。但这并不是我们今天要讨论的重点&#xff01; TCP通信的过程分别是三个阶段&#xff1a;建立连接、传输数据、关…

VMware ESXi虚拟机备份的方法和步骤

关于虚拟机备份 VMware ESXi 是 VMware vSphere 企业虚拟化套件的核心组件。在版本4.1之前&#xff0c;它一直被称为ESX。ESXi是一种裸机管理程序&#xff0c;直接安装在物理服务器上&#xff0c;它提供对底层资源的直接访问和控制&#xff0c;允许您在单个物理主机上创建和运…

私有化部署 Llama3 大模型, 支持 API 访问

私有化部署 Llama3 大模型, 支持 API 访问 视频 https://www.bilibili.com/video/BV1wD421n75p/ 前言 原文 https://ducafecat.com/blog/llama3-model-api-local 通过 ollama 本地运行 Llama3 大模型其实对我们开发来说很有意义&#xff0c;你可以私有化放服务上了。 然后通…

练习题(2024/4/26)

1所有可能的路径 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特定顺序&#xff09; graph[i] 是一个从节点 i 可以访问的所有节点的列表&#xff08;即从节点 i 到节点 graph…

科普童话新课堂杂志社科普童话新课堂编辑部2024年第16期目录

作品选 封2,封3-封4 探索新知《科普童话》投稿&#xff1a;cn7kantougao163.com 泱泱国之风 悠悠诗之情 沈灿宇1-3 试论"文化意识"视角下的高中英语阅读教学 董娜4-6 立足小组合作探究优化写作能力培养 时同祥7-9 以"导"促学:全面提升学生的文学核心素养 吴…

[网络安全] apt攻击是什么?

什么是APT攻击&#xff1a;APT攻击的主要特征包括&#xff1a;APT攻击的防御措施&#xff1a;零基础入门学习路线视频配套资料&国内外网安书籍、文档网络安全面试题 什么是APT攻击&#xff1a; APT&#xff08;Advanced Persistent Threat&#xff0c;高级持续性威胁&…

软件过程与项目管理期末复习

文章目录 1. 课程导论1) 什么是项目&#xff1f;具有什么特征&#xff1f;2) 项目管理的4阶段5过程的具体内容是什么&#xff1f;3) 项目管理的10大知识域是哪些&#xff1f;其中4个是核心知识域&#xff1f;4个核心知识域之间是什么关系&#xff1f;4) 什么是质量管理三角形&a…

汇舟问卷:做国外问卷调查需要准备些什么

大家好&#xff0c;我是汇舟问卷。海外问卷调查在这两年一直是个热门的项目&#xff0c;做这个项目所需要投入的成本是多少&#xff1f;如果我们要做这个项目需要准备什么以及要花多少钱&#xff1f;今天我来为大家讲解一下: 首先准备一台电脑 (内存建议16G&#xff0c;处理器…

C语言进阶:进阶指针(下)

一、 函数指针数组 我们都知道 数组是一个存放相同类型数据的存储空间 那我们已经学习了指针数组 那么函数有没有对应的指针数组呢&#xff1f; 如果有那应该怎么定义呢&#xff1f; 1. 函数指针数组的定义 我们说 函数指针数组的定义 应该遵循以下格式 int (*p[10])(); 首…