调频信号FM的原理与matlab与FPGA实现

news2024/11/21 2:29:02

平台:matlab r2021b,vivado2023.1

本文知识内容摘自《软件无线电原理和应用》

调频(FM)是载波的瞬时频率随调制信号成线性变化的一种调制方式,音频调频信号的数学表达式可以写为:

s(t)=A[cos(\omega _{c}t+k_{\Omega }\int_{0}^{t}v_{\Omega (t)dt})]

Fm频率调制,载波的幅度随着调制波形的幅度变化而变化。

其中\omega _{c}为载波频率,v_{\Omega }t为调制信号,k_{\Omega }为调制角频率。

下面是FM调制的matlab实现

clc;
clear;
% 设置参数
fs = 312.5e6;       % 采样率
fc = 20e6;          % 载波频率
fm = 1e6;           % 调制信号频率,内调制最大3mhz
t1 = 0:1/fs:2;      % 时间序列,1微秒
t = t1(1:5000);     %RW需要取整数计算出的频率是真实
% 生成调制信号
m = cos(2*pi*fm*t);%正弦波
% m = square(2*pi*fm*t);%方波
% m = sawtooth(2*pi*fm*t, 0.5);%三角波
% m = sawtooth(2*pi*fm*t);% 锯齿波
% 例如,y=x^2;t=1-5;
% Q=cumtrapa(t,y);
% q0=0;
% q1=0.5*(4+1)+0=2.5;
% q2=0.5*(9+3)+2.5=9;
% q3=0.5*(16+9)+9=21.5;
% q4=0.5*(25+16)+21.5=42;
% 计算积分累计积分结果,返回一个向量
integral_term = cumtrapz(t, m);

% 生成载波信号
c = cos(2*pi*fc*t);
% FM调制,
kf = 100e6; % 调频系数
k = 2*pi*fc*t;
k1= kf*integral_term;
s = cos(2*pi*fc*t + kf*integral_term);
% 绘制时域波形
figure(1);
subplot(3,1,1);
plot(t*1e6, m);
title('调制信号');
xlabel('时间 (μs)');
ylabel('幅度');

subplot(3,1,2);
plot(t*1e6, c);
title('载波信号');
xlabel('时间 (μs)');
ylabel('幅度');

subplot(3,1,3);
plot(t*1e6, s);
title('调制后信号');
xlabel('时间 (μs)');
ylabel('幅度');

figure(2);
subplot(1,1,1);
plot(t*1e6, c, 'r', 'LineWidth', 2); % 使用红色绘制载波信号,线条宽度为2
title('载波信号');
xlabel('时间 (μs)');
ylabel('幅度');
hold on;

plot(t*1e6, s, 'k', 'LineWidth', 2); % 使用黑色绘制调制后信号,线条宽度为2
title('调制后信号');
xlabel('时间 (μs)');
ylabel('幅度');



% 绘制频域波形
figure(3);
% 计算频谱
N = length(t);
f = (-fs/2:fs/N:fs/2-fs/N); % 频率向量
M = fftshift(fft(m));
C = fftshift(fft(c));
S = fftshift(fft(s));

subplot(3,1,1);
plot(f, abs(M)/N,'b');
title('调制信号频谱');
xlabel('频率 (GHz)');
ylabel('幅度');

subplot(3,1,2);
plot(f, abs(C)/N,'g');
title('载波信号频谱');
xlabel('频率 (GHz)');
ylabel('幅度');

subplot(3,1,3);
plot(f, abs(S)/N,'r');
title('调制后信号频谱');
xlabel('频率 (GHz)');
ylabel('幅度');

调制波为余弦波时时域和频域图像

当调制信号为方波时。

为锯齿波时

FPGA的实现

当我们的调制波是一个余弦波时。

可以看到我们的调制波形是一个余弦波。载波也是一个余弦波,调制波的频率随着调制波形的积

分变化而变化。其变化规律如下。

余弦波时,积分量在0,pi和2pi时最小,对应着在0时频偏最小,在pi/2时频率与载波相同,在pi时

频偏正向最大。在3*pi/2时又与载波频率相同。在2pi时达到了最小频偏。

在逻辑中有几种产生正余弦波形的方式,基于DDS的波形发生器,基于cordic的波形发生器。这里我们使用cordic来产生我们的载波和调制波。

关于cordic的频率控制字这里说明一下。Cordic是你对其输入一个角度,他给你计算出y(cos,sin)的一个结果。所以我们需要对频率控制字执行一个累加的过程。其中cordic的角度范围表示为(-pi,pi)。

关于输出的频率计算公式为

f_{o}=\tfrac{phase*fs}{2^{N-2}}

其中f_{o}为输出频率,phase为相位控制字,f_{s}为采样率。2^{N-2}是因为cordic将数据的范围量化到(-pi,pi)。

所以我们需要控制cordic的累加量

p=p+pi+po

其中p为频率控制字,pi为载波的频率控制字,po为频偏控制字。

例如我们要载波为fi,最大频偏为fo。假定现在的采样率时钟为fs。根据公式

可以算出载波的频率控制字为

pi=\frac{​{​{}2^{14}}*fi}{fs}

可以算出最大频偏控制字为

po=\frac{​{​{}2^{14}}*fo}{fs}

所以又调制波的幅度最大为16’h4000=16’d16384表示最大为正1v。
所以po与幅度的对应关系为

k=\frac{​{​{}2^{14}}*fo}{fs*2^{14}}=\tfrac{fo}{fs}

所以最大频偏和调制波幅度的关系为

po=\frac{fo}{fs}*x

其中x为调制波幅度

逻辑实现现在假定调制波为1mhz,载波为8mhz,最大频偏为2mhz,采样率为512mhz。

插入FPGA代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/06/06 21:09:44
// Design Name: 
// Module Name: vtf_cordic
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module vtf_cordic;

reg             aclk;
reg             rst_n;
reg             s_axis_phase_tvalid;
reg  [15 : 0]   s_axis_phase_tdata;
reg  [15 : 0]   s_axis_phase_tdata_0;

wire            m_axis_dout_tvalid;
wire [31 : 0]   m_axis_dout_tdata;

wire [15:0]     sin ;
wire [15:0]     cos ;
wire [15:0]     sin0 ;
wire [15:0]     cos0 ;




cordic_0 u_cordic_0 (
    .aclk                         (aclk                         ),// input wire aclk
    .s_axis_phase_tvalid          (s_axis_phase_tvalid          ),// input wire s_axis_phase_tvalid
    .s_axis_phase_tdata           (s_axis_phase_tdata           ),// input wire [15 : 0] s_axis_phase_tdata
    .m_axis_dout_tvalid           (m_axis_dout_tvalid           ),// output wire m_axis_dout_tvalid
    .m_axis_dout_tdata            ({sin,cos}                    )// output wire [31 : 0] m_axis_dout_tdata
);

cordic_0 u_cordic_1 (
    .aclk                         (aclk                         ),// input wire aclk
    .s_axis_phase_tvalid          (s_axis_phase_tvalid          ),// input wire s_axis_phase_tvalid
    .s_axis_phase_tdata           (s_axis_phase_tdata_0           ),// input wire [15 : 0] s_axis_phase_tdata
    .m_axis_dout_tvalid           (                             ),// output wire m_axis_dout_tvalid
    .m_axis_dout_tdata            ({sin0,cos0}                  )// output wire [31 : 0] m_axis_dout_tdata
);


initial
begin
        aclk    =0;

        rst_n   =0;

        #100;
        rst_n   =1;

        #100;
        s_axis_phase_tvalid =1;

end

reg     [15:0]      wave_add;
reg     [15:0]      phase_tdata;
reg     [15:0]      phase_tdata_0;
//产生一个载波
always@(posedge aclk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin
                wave_add  <= 16'b0;
        end
        else begin
                wave_add  <= 16'd32;
        end
end
always@(posedge aclk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin
                phase_tdata  <= 16'b0;
        end
        else begin
                phase_tdata  <= phase_tdata + wave_add;
        end
end
always@(posedge aclk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin
                phase_tdata_0  <= 16'b0;
        end
        else if(phase_tdata >= 16'h0 && phase_tdata <= 16'h4000 )begin
                phase_tdata_0  <= phase_tdata;
        end
        else if(phase_tdata > 16'h4000 && phase_tdata <= 16'h8000 )begin
                phase_tdata_0  <= phase_tdata - 16'h4000;
        end
        else if(phase_tdata > 16'h8000 && phase_tdata <= 16'hc000 )begin
                phase_tdata_0  <= phase_tdata - 16'h8000;
        end
        else if(phase_tdata > 16'hc000 && phase_tdata <= 16'hffff )begin
                phase_tdata_0  <= phase_tdata - 16'hc000;
        end
        else begin
                phase_tdata_0  <= phase_tdata;
        end
end
always@(posedge aclk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin
                s_axis_phase_tdata  <= 16'b0;
        end
        else begin
                s_axis_phase_tdata  <= 16'he000 + phase_tdata_0;
        end
end

//-------------------------------------------------------------------
reg     [15:0]      wave_add_m;
reg     [15:0]      phase_tdat_m;
reg     [15:0]      phase_tdata_0_m;

wire    [15:0]      sinsin={sin[15],
                             sin[15],
                             sin[15],
                             sin[15],
                             sin[15],
                             sin[15],
                             sin[15],
                             sin[15],
                             sin[15:8]};
//产生一个方波
always@(posedge aclk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin
                wave_add_m  <= 16'b0;
        end
        else begin
                wave_add_m  <= sinsin + 16'd262;
        end
end
always@(posedge aclk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin
                phase_tdat_m  <= 16'b0;
        end
        else begin
                phase_tdat_m  <= phase_tdat_m + wave_add_m;
        end
end
always@(posedge aclk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin
                phase_tdata_0_m  <= 16'b0;
        end
        else if(phase_tdat_m >= 16'h0 && phase_tdat_m <= 16'h4000 )begin
                phase_tdata_0_m  <= phase_tdat_m;
        end
        else if(phase_tdat_m > 16'h4000 && phase_tdat_m <= 16'h8000 )begin
                phase_tdata_0_m  <= phase_tdat_m - 16'h4000;
        end
        else if(phase_tdat_m > 16'h8000 && phase_tdat_m <= 16'hc000 )begin
                phase_tdata_0_m  <= phase_tdat_m - 16'h8000;
        end
        else if(phase_tdat_m > 16'hc000 && phase_tdat_m <= 16'hffff )begin
                phase_tdata_0_m  <= phase_tdat_m - 16'hc000;
        end
        else begin
                phase_tdata_0_m  <= phase_tdat_m;
        end
end
always@(posedge aclk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin
                s_axis_phase_tdata_0  <= 16'b0;
        end
        else begin
                s_axis_phase_tdata_0  <= 16'he000 + phase_tdata_0_m;
        end
end


always#0.977 aclk = ~aclk;


    
endmodule


仿真为

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不同材质的不锈钢氮气柜优缺点和使用场景分析

不锈钢氮气柜是一种用于存储对湿度敏感的物品的专用储藏设备&#xff0c;通过充入干燥的氮气来降低柜内湿度&#xff0c;保护存储物免受氧化或腐蚀。 根据不同的材质&#xff0c;不锈钢氮气柜可分为&#xff1a; 一、201不锈钢氮气柜&#xff1a; 201不锈钢因其较低的镍含量而成…

【揭秘新潮流】实践教学新宠SmartEDA,让电子设计课“潮“起来!

在信息时代的浪潮下&#xff0c;电子设计课程早已不再是枯燥乏味的代名词。随着技术的飞速发展&#xff0c;一种名为SmartEDA的实践教学新选择正逐渐崭露头角&#xff0c;为电子设计课程注入了前所未有的活力与趣味性。今天&#xff0c;就让我们一起走进SmartEDA的世界&#xf…

25届最近4年中国科学技术大学自动化考研院校分析

中国科学技术大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近4年考研分数情况 四、近4年招生录取情况 五、最新一年分数段图表 六、历年真题PDF 七、初试大纲复试大纲 八、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、…

Maven列出所有的依赖树

在 IntelliJ IDEA 中&#xff0c;你可以使用 Maven 插件来列出项目的依赖树。Maven 插件提供了一个名为dependency:tree的目标&#xff0c;可以帮助你获取项目的依赖树详细信息。 要列出项目的依赖树&#xff0c;可以执行以下步骤&#xff1a; 打开 IntelliJ IDEA&#xff0c;…

Kubernetes之Controller详解

本文尝试从Kubernetes Controller的种类、交互逻辑、最佳实践、伪代码示例及历史演进5个方面对其进行详细阐述&#xff0c;希望对您有所帮助&#xff01; 一、Kubernetes Controller种类 Kubernetes Controller Manager 是 Kubernetes 集群的核心组件之一&#xff0c;负责管理…

CCS的安装步骤

CCS的安装步骤 安装之前有几件重要的事情要做&#xff1a; 首先肯定是要下载安装包啦&#xff01;点击此处是跳到官网下载地址安装包不能处的路径中不能包含中文关闭病毒防护和防火墙&#xff0c;以及其他杀毒软件最后是在重启后进行安装 主要的步骤如下&#xff1a; 找到安…

想布局短视频赛道,云微客AI矩阵系统告诉你诀窍

随着人工智能技术的不断发展&#xff0c;越来越多的企业和个人创作者开始意识到智能化的重要性。而现阶段&#xff0c;随着短视频市场的膨胀扩大&#xff0c;批量成片、智能创作、定时发布是当下重要的趋势&#xff0c;企业如果想在短视频赛道分一杯羹&#xff0c;智能化的平台…

python目录树生成器

代码如下&#xff1a; import os from colorama import Fore, Style, init from tkinter import Tk, Label, Entry, Button, Text, Scrollbar, RIGHT, Y, END# 初始化 colorama init(autoresetTrue)def print_directory_tree(root_dir, text_widget, indent, lastTrue):"…

allWebPlugin助力iWebOffice2015插件在高版本浏览器使用

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX插件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持谷歌、火狐等浏…

STM32CubeMX与RT-Thread Studio协助使用(实现点亮LED)

1创建自己的项目 1-1选择板子 1-2生成的项目 运行一下看是否创建成功 零警告零错误 2配置STM32Cude 2-1找打如图图标点击&#xff08;CubeMX的图标&#xff09; 2-2输入自己安装的路径选中exe文件 点击Browse 找到如图选中&#xff0c;在打开&#xff08;STM32CubeMX的安装路…

Python量化交易学习——Part9:基于放量技术因子的策略实战

话不多说&#xff0c;直接进入正题 股票池&#xff1a;沪深300 买入策略&#xff1a;选择过去收盘价标准差小于0.05&#xff0c;且量比大于3的股票&#xff0c;当第二天高开的时候进行买入&#xff1b; 卖出策略&#xff1a;卖出条件为收益30%或者亏损7%&#xff1b; 首先我们可…

Python复数的加、减、乘、除运算

一、复数 复数由实部和虚部组成&#xff0c;形如abi(a,b均为实数)的数为复数&#xff0c;其中&#xff0c;a被称为实部&#xff0c;b被称为虚部&#xff0c;i为虚数单位&#xff0c;。复数通常用z表示&#xff0c;即zabi&#xff0c;当z的虚部b&#xff1d;0时&#xff0c;则z…

基于CNN卷积神经网络的MQAM调制识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 CNN模型结构 4.2 损失函数与优化 4.3 训练与测试 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#xff0…

Labview_映射表

1.创建映射表 创建映射表时&#xff0c;该映射表内的所有键为同一类型、键为同一类型。映射表键名可以为任意类型。 PS:生成映射表在使用时请保证唯一键名&#xff0c;如使用同一键名&#xff0c;则在最终输出时只能搜索到最新插入的键值对信息。 2.插入映射表 按照已创建的映…

《TopFormer: Token Pyramid Transformer for Mobile Semantic Segmentation》

期刊&#xff1a;CVPR 年份&#xff1a;2022 代码&#xff1a;https://github.com/hustvl/TopFormer 摘要 尽管视觉Transformer(ViTs)在计算机视觉领域取得了巨大的成功&#xff0c;但沉重的计算成本阻碍了它们在密集预测任务中的应用&#xff0c;如移动设备上的语义分割。…

JavaScript通用下载方法,但jpg图片下载打不开

通用下载方法&#xff0c;通过Blob的方式&#xff0c;访问Url地址&#xff0c;下载对应的图片&#xff0c;excel等文件。 axios({method: "get",url,responseType: "blob",}).then((res: any) > {const link document.createElement("a");co…

Java基础:常用类(四)

Java基础&#xff1a;常用类&#xff08;四&#xff09; 文章目录 Java基础&#xff1a;常用类&#xff08;四&#xff09;1. String字符串类1.1 简介1.2 创建方式1.3 构造方法1.4 连接操作符1.5 常用方法 2. StringBuffer和StringBuilder类2.1 StringBuffer类2.1.1 简介2.1.2 …

信息学奥赛初赛天天练-36-CSP-J2021阅读程序-ASCII、运算符优先级、二进制补码存储、模拟算法应用

PDF文档公众号回复关键字:20240626 2021 CSP-J 阅读程序2 1 阅读程序(判断题1.5分 选择题3分 共计40分 ) #include<stdio.h> #include<string.h>char base[64]; char table[256]; char str[256]; char ans[256];void init() {for(int i0;i<26;i) base[i]Ai;fo…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-23卷积神经网络LeNet

23卷积神经网络LeNet import torch from torch import nn import liliPytorch as lp import matplotlib.pyplot as plt# 定义一个卷积神经网络 net nn.Sequential(nn.Conv2d(1, 6, kernel_size5, padding2), # 卷积层1&#xff1a;输入通道数1&#xff0c;输出通道数6&#x…

方法的其他形式——方法使用时常见的问题

示例&#xff1a; public class MethodDemo02 {public static void main(String[] args) {//目标&#xff1a;掌握按照方法的实际业务需求不同&#xff0c;设计出合理的方法形式来解决问题//需求&#xff1a;打印三行Hello World.printfHelloWorld();System.out.println("…