【FPGA、maltab】基于FPGA的SOQPSK调制解调技术的设计与实现

2024-05-16 04:04

本文主要是介绍【FPGA、maltab】基于FPGA的SOQPSK调制解调技术的设计与实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于FPGA的SOQPSK调制解调技术的设计与实现

  • SOQPSK
    • 一、QPSK、OQPSK、SOQPSK之间的关系
    • 二、SOQPSK调制原理
  • matlab 仿真
  • FPGA 实现
    • 顶层设计
    • 发射模块
    • 接收模块
    • 顶层调制解调FPGA代码

SOQPSK

一、QPSK、OQPSK、SOQPSK之间的关系

SOQPSK(Shaped Offset Quadrature Phase Shift Keying),整形偏移四相相移键控。其中,S(shaped)指的是信号的波形经过特殊设计,以优化传输性能,O(offset)表示信号的相位被偏移以改善调制方案的性能。

SOQPSK是一种基于QPSK调制方式的改进版本,通过特殊的波形设计和相位调整来改善性能。在QPSK中,将基带码元分成I、Q两路,相邻码元的最大相位差为180°,这样的相位突变在频带受限的系统中会引起信号包络的很大起伏,为了减小此相位突变,在OQPSK中,将I、Q两路在时间上错开半个码元,使之不可能同时改变,此时相邻码元的相位差的最大值为90°,从而减小了信号振幅的起伏,包络恒定,相对于传统的QPSK,它具有更好的抗多径衰落和功率放大器非线性的性能,其频谱旁瓣要低于QPSK信号的旁瓣,且有较高的功率利用率。
在这里插入图片描述
在这里插入图片描述
然而,OQPSK依旧具有90°的相位跳变,并且变化并不连续,使得OQPSK的高频滚降变慢,频带变宽。从OQPSK到SOQPSK的实现方式是通过改变附加相位中的频率成形函数,以保证相位的连续变化。在OQPSK中频率成形函数是冲激函数,对应的相位成形函数是矩形函数,因此相位不连续。若要相位成形函数连续,可采用矩形函数或升余弦函数作为频率成形函数,由此得到的相位成形函数是连续的,因而频谱较窄,频谱利用率较高。是连续相位调制(CPM)中的一种特殊调制方式,适用于功率受限且频带受限的通信信道中。
在这里插入图片描述
在这里插入图片描述
QPSK、OQPSK、SOQPSK的相位曲线
在这里插入图片描述

二、SOQPSK调制原理

SOQPSK作为一种特殊的CPM调制方式,区别于传统CPM的一个明显特征是,实际传输的三元符号集{ }为{-1,0,1}。
SOQPSK调制的时域表达式为:
在这里插入图片描述
代表一个码元的持续时间, 代表 时间内码元的能量, 代表SOQPSK时域信号的载波频率, 为相位函数, 为初始相位 。其中,
在这里插入图片描述
频率脉冲函数为
在这里插入图片描述相位函数q(t)为频率脉冲函数的积分,即

在这里插入图片描述
因此,可得到相位信息
在这里插入图片描述
在这里插入图片描述
为原始输入的二进制数据 ,取值为{0,1},经过预编码
在这里插入图片描述
得到,取值为{0,+1,-1}。经过与编码的 ,1和-1不相邻,保证了SOQPSK相邻码元的相位变化最大为 。

matlab 仿真

根据以上SOQPSK的基本原理,对SOQPSK在基带上调制解调过程进行matlab仿真。基本参数设置如下
在这里插入图片描述
对随机产生的二进制码元进行turbo编码后,对其进行预编码,转化为三进制码元,并进行四倍采样,得到的采样序列如图所示
在这里插入图片描述
I路和Q路以及SOQPSK调制后的的基带调制波形如下

在这里插入图片描述
在这里插入图片描述
可以看出SOQPSK为恒包络信号
其相位曲线为
在这里插入图片描述星座图
在这里插入图片描述
当采样率足够大时,该星座图为一个连续的圆,即SOQPSK相位连续;采样率为1时,SOQPSK星座图与QPSK的星座图相同。
信号频谱如下
在这里插入图片描述
可以看出,经过SOQPSK调制后的信号频谱较窄,频谱利用率高。
在信道内加入高斯白噪声,信噪比为20db
在这里插入图片描述
加入噪声后的相位曲线:
在这里插入图片描述
星座图
在这里插入图片描述
频谱
在这里插入图片描述
硬判决:
对加噪后的相位曲线每隔一个码元周期对其进行最小二乘拟合,得到的斜率为
在这里插入图片描述
以+0.5和-0.5作为判决门限,得到的判决结果为
在这里插入图片描述
与原二进制编码后的输入数据几乎相同
在这里插入图片描述

matlab 代码如下(仅仅显示核心代码)

clear ;                  % 清除所有变量
close all;                  % 关闭所有窗口
clc;                        % 清屏%% 基本参数
M=224*8;                       % 产生码元数    
Ns=4;                      % 每码元复制L次,每个码元采样次数4
Tb=1;                   % 每个比特的持续时间1
Rb=1/Tb;                    % 码元速率1
dt=Tb/Ns;                    % 采样间隔0.25
Fs=1/dt;                    % 采样间隔的倒数即采样频率4%% 产生二进制数据 %%
M_data = 0x1:0xE0;
binStr = dec2bin(M_data);
binData = binStr - '0';
data = reshape(binData',M,1)';%% turbo编码
encoded_data=TurboEncode(data); %% SOQPSK 调制
s = soqpsk_mod(encoded_data);%% 信道
s_n=awgn(s,-20,'measured');%加入高斯白噪声20db% 度量
L=length(DI);%分支度量
gammaI_0 = zeros(1,length(DI));
gammaI_1 = zeros(1,length(DI));
gammaI_2 = zeros(1,length(DI));
gammaI_3 = zeros(1,length(DI));
gammaQ_0 = zeros(1,length(DI));
gammaQ_1 = zeros(1,length(DI));
gammaQ_2 = zeros(1,length(DI));
gammaQ_3 = zeros(1,length(DI));%前向度量
%初始化前向度量
alphaI_0 = zeros(1, L+1);
alphaI_1 = zeros(1, L+1);
alphaQ_0 = zeros(1, L+1);
alphaQ_1 = zeros(1, L+1);%前向度量的递推%后向度量
%初始化后向度量
betaI_0 = zeros(1, L+1);
betaI_1 = zeros(1, L+1);
betaQ_0 = zeros(1, L+1);
betaQ_1 = zeros(1, L+1);%后向度量的递推% 计算软信息
decoded_data = [llrQ,llrI];%Turbo译码
turbodecoded_data=lteTurboDecode(decoded_data');% 计算误码比特数
num_errors = sum(turbodecoded_data' ~= data);% 计算总比特数
total_bits = length(data);% 计算误码率
BER = num_errors / total_bits

得出的误码率为零。代码是示意代码。

FPGA 实现

上文已经描述了详细的原理和matlab仿真,下一步就是用FPGA进行实现;

顶层设计

在这里插入图片描述
包含了完整的信源和信宿、误码率比较;

包含有加扰和解扰;

包含有soqpsk调制和解调;

包含有turbo编译码;

发射模块

在这里插入图片描述
在这里插入图片描述

接收模块

在这里插入图片描述
在这里插入图片描述
最终输出的数据和发射的数据保持一致;

顶层调制解调FPGA代码


// 生成224 8Bit数据;
gen_Incremental_223 gen_Incremental_224(.clk        (clk        ),.rst        (rst        ),.start      (start_data ),.dout       (din        ),.dout_clk_p (           ),.dout_en    (din_clk_p  )
);// turbo  编码
//  1/3Turbo Encode
Turbo_Encode_1_3(.clk                (clk            ),.rst                (rst            ),.din_dout           (din_dout       ),.before_sc_dat_en   (before_sc_dat_en),.before_sc_dat_p    (before_sc_dat_p),.dat_choose         (dat_choose     ),.src_din_p          (src_din_p      ),.all_dat_clk_p      (all_dat_clk_p  )
);Scrambler
#( .FRAME_LENGTH(ALL_DAT-1) )     // 1792*3+12-1 = 5387
Scrambler (.clk(clk					),//系统时钟.rst(rst				    ),//系统复位,高有效.din(dat_choose				),//待加扰数据.din_p(src_din_p		    ),//待加扰数据帧头,脉冲型.din_en(all_dat_clk_p		),//帧同步后的使能信号,便于写入FIFO.dout(scr_dat				),//加扰后数据.dout_en(scr_en			    ),//加扰后数据使能信号.dout_p( 				    ) //加扰后数据帧头指示信号,脉冲型
);// tb:判断是否完成调制
soqpsk_mod(.clk            (clk            ),.rst            (rst            ),.scr_dat        (scr_dat        ),.scr_en         (scr_en         ),.is_End_SOQPSK_Mod(is_End_SOQPSK_Mod),.pulses_dout_i  (pulses_dout_i),.pulses_dout_q  (pulses_dout_q),.pulses_dout_clk_p(),.ram_cnts_write (ram_cnts_write)
);// 组帧
blk_mem_24_32768 blk_mem_24_32768 (.clka(clk),    // input wire clka.ena(1'b1),      // input wire ena.wea(1'b1),      // input wire [0 : 0] wea.addra(ram_cnts_write ),  // input wire [14 : 0] addra_write.dina({pulses_dout_i,pulses_dout_q}),    // input wire [23 : 0] dina.clkb(clk),    // input wire clkb.enb(1'b1),      // input wire enb.addrb(addrb_read),  // input wire [14 : 0] addrb_read.doutb({lut_dout_i,lut_dout_q})  // output wire [23 : 0] doutb
);soqpsk_demod_gamma(.clk                 (clk               ),.rst                 (rst               ),.start               (is_End_SOQPSK_Mod ),.addrb_read          (addrb_read        ),.lut_dout_i          (lut_dout_i        ),.lut_dout_q          (lut_dout_q        ),.is_End_SOQPSK_gamma (is_End_SOQPSK_gamma),.gammaI_0_ram        (gammaI_0_ram      ),.gammaI_1_ram        (gammaI_1_ram      ),.gammaI_2_ram        (gammaI_2_ram      ),.gammaI_3_ram        (gammaI_3_ram      ),.gammaQ_0_ram        (gammaQ_0_ram      ),.gammaQ_1_ram        (gammaQ_1_ram      ),.gammaQ_2_ram        (gammaQ_2_ram      ),.gammaQ_3_ram        (gammaQ_3_ram      ), // Q28.22.read_gamma_addrb    (read_gamma_addrb  ));// 解调第四步: 前向度量
soqpsk_demod_alpha (.clk                 (clk                   ),.rst                 (rst                   ),.start               (is_End_SOQPSK_gamma   ),.gammaI_0_ram        (gammaI_0_ram          ),.gammaI_1_ram        (gammaI_1_ram          ),.gammaI_2_ram        (gammaI_2_ram          ),.gammaI_3_ram        (gammaI_3_ram          ),.gammaQ_0_ram        (gammaQ_0_ram          ),.gammaQ_1_ram        (gammaQ_1_ram          ),.gammaQ_2_ram        (gammaQ_2_ram          ),.gammaQ_3_ram        (gammaQ_3_ram          ), .read_gamma_addrb    (read_gamma_addrb_forward),.is_End_SOQPSK_alpha (is_End_SOQPSK_alpha   ),.alphaI_0_ram        (alphaI_0_ram          ), .alphaI_1_ram        (alphaI_1_ram          ), .alphaQ_0_ram        (alphaQ_0_ram          ), .alphaQ_1_ram        (alphaQ_1_ram          ),.read_alpha_addrb    (read_gamma_addrb_IIr  )
);// 解调第五步: 后向度量
soqpsk_demod_beta(.clk                 (clk                   ),.rst                 (rst                   ),.start               (is_End_SOQPSK_alpha   ),.gammaI_0_ram        (gammaI_0_ram          ),.gammaI_1_ram        (gammaI_1_ram          ),.gammaI_2_ram        (gammaI_2_ram          ),.gammaI_3_ram        (gammaI_3_ram          ),.gammaQ_0_ram        (gammaQ_0_ram          ),.gammaQ_1_ram        (gammaQ_1_ram          ),.gammaQ_2_ram        (gammaQ_2_ram          ),.gammaQ_3_ram        (gammaQ_3_ram          ), .read_gamma_addrb    (read_gamma_addrb_backward),.is_End_SOQPSK_beta  (is_End_SOQPSK_beta    ),.betaI_0_ram         (betaI_0_ram), .betaI_1_ram         (betaI_1_ram), .betaQ_0_ram         (betaQ_0_ram), .betaQ_1_ram         (betaQ_1_ram),.read_beta_addrb     (read_gamma_addrb_IIr + 1)
);// 解调第六步: 计算软信息
soqpsk_demod_llr(.clk                 (clk                   ),.rst                 (rst                   ),.start               (is_End_SOQPSK_beta    ),.gammaI_0_ram        (gammaI_0_ram),.gammaI_1_ram        (gammaI_1_ram),.gammaI_2_ram        (gammaI_2_ram),.gammaI_3_ram        (gammaI_3_ram),.gammaQ_0_ram        (gammaQ_0_ram),.gammaQ_1_ram        (gammaQ_1_ram),.gammaQ_2_ram        (gammaQ_2_ram),.gammaQ_3_ram        (gammaQ_3_ram), .read_gamma_addrb    (read_gamma_addrb_IIr),.betaI_0_ram         (betaI_0_ram), .betaI_1_ram         (betaI_1_ram), .betaQ_0_ram         (betaQ_0_ram), .betaQ_1_ram         (betaQ_1_ram),.read_beta_addrb     (),.alphaI_0_ram        (alphaI_0_ram), .alphaI_1_ram        (alphaI_1_ram), .alphaQ_0_ram        (alphaQ_0_ram), .alphaQ_1_ram        (alphaQ_1_ram),.read_alpha_addrb    (),.is_End_SOQPSK_llr   (is_End_SOQPSK_llr),.llrI                (llrI          ),.llrQ                (llrQ          ),.llr_clk_p           (llr_clk_p     )
);// 转化为串行的数据流
soqpsk_demod_2p1s 
# ( .ALL_DAT        (ALL_DAT        ),.ALL_DAT_PADDING(ALL_DAT_PADDING) )
soqpsk_demod_2p1s(.clk                 (clk),.rst                 (rst),.bs_cut_i            (llrI[26:19]),.bs_cut_q            (llrQ[26:19]),.dout_cut_en         (llr_clk_p),.bs_din              (bs_din),.bs_din_p            (bs_din_p),.bs_din_en           (bs_din_en)
);/*-----------------------------------------------------------------------下面是进入解扰的模块
-----------------------------------------------------------------------*/    Descrambler
# ( .ALL_DAT(ALL_DAT) )
Descrambler(.clk                 (clk       ),.rst                 (rst       ),.bs_din              (bs_din    ),.bs_din_p            (bs_din_p  ),.bs_din_en           (bs_din_en ),.soft_din            (soft_din),.soft_din_clk_p      (soft_din_clk_p)
);   //准备送入Turbo 译码器
Turbo_Decode_1_3 Turbo_Decode_1_3(.clk(clk),.rst(rst),.soft_din(soft_din),.soft_din_clk_p(soft_din_clk_p),.dout(turbo_dout),.dout_clk_p(turbo_dout_clk_p)
);// 解调第八步: turbo译码// tb: 误码率统计fifo_1_8 FIFOS (.clk(clk            ),                      // input wire clk.srst(rst           ),                    // input wire srst.din(turbo_dout        ),                      // input wire [0 : 0] din.wr_en(turbo_dout_clk_p),                  // input wire wr_en.rd_en(  rd_en11       ),                  // input wire rd_en.dout( fifo_dout11     ),                    // output wire [7 : 0] dout.full(           ),                    // output wire full.empty(         ),                  // output wire empty.rd_data_count(rd_data_count )  // output wire [9 : 0] rd_data_count
);

这篇关于【FPGA、maltab】基于FPGA的SOQPSK调制解调技术的设计与实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Spring Boot拦截器Interceptor与过滤器Filter深度解析(区别、实现与实战指南)

《SpringBoot拦截器Interceptor与过滤器Filter深度解析(区别、实现与实战指南)》:本文主要介绍SpringBoot拦截器Interceptor与过滤器Filter深度解析... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现与实

C#实现访问远程硬盘的图文教程

《C#实现访问远程硬盘的图文教程》在现实场景中,我们经常用到远程桌面功能,而在某些场景下,我们需要使用类似的远程硬盘功能,这样能非常方便地操作对方电脑磁盘的目录、以及传送文件,这次我们将给出一个完整的... 目录引言一. 远程硬盘功能展示二. 远程硬盘代码实现1. 底层业务通信实现2. UI 实现三. De

SpringBoot后端实现小程序微信登录功能实现

《SpringBoot后端实现小程序微信登录功能实现》微信小程序登录是开发者通过微信提供的身份验证机制,获取用户唯一标识(openid)和会话密钥(session_key)的过程,这篇文章给大家介绍S... 目录SpringBoot实现微信小程序登录简介SpringBoot后端实现微信登录SpringBoo

使用Vue-ECharts实现数据可视化图表功能

《使用Vue-ECharts实现数据可视化图表功能》在前端开发中,经常会遇到需要展示数据可视化的需求,比如柱状图、折线图、饼图等,这类需求不仅要求我们准确地将数据呈现出来,还需要兼顾美观与交互体验,所... 目录前言为什么选择 vue-ECharts?1. 基于 ECharts,功能强大2. 更符合 Vue

使用WPF实现窗口抖动动画效果

《使用WPF实现窗口抖动动画效果》在用户界面设计中,适当的动画反馈可以提升用户体验,尤其是在错误提示、操作失败等场景下,窗口抖动作为一种常见且直观的视觉反馈方式,常用于提醒用户注意当前状态,本文将详细... 目录前言实现思路概述核心代码实现1、 获取目标窗口2、初始化基础位置值3、创建抖动动画4、动画完成后

uniapp小程序中实现无缝衔接滚动效果代码示例

《uniapp小程序中实现无缝衔接滚动效果代码示例》:本文主要介绍uniapp小程序中实现无缝衔接滚动效果的相关资料,该方法可以实现滚动内容中字的不同的颜色更改,并且可以根据需要进行艺术化更改和自... 组件滚动通知只能实现简单的滚动效果,不能实现滚动内容中的字进行不同颜色的更改,下面实现一个无缝衔接的滚动

C#通过进程调用外部应用的实现示例

《C#通过进程调用外部应用的实现示例》本文主要介绍了C#通过进程调用外部应用的实现示例,以WINFORM应用程序为例,在C#应用程序中调用PYTHON程序,具有一定的参考价值,感兴趣的可以了解一下... 目录窗口程序类进程信息类 系统设置类 以WINFORM应用程序为例,在C#应用程序中调用python程序

利用Python实现可回滚方案的示例代码

《利用Python实现可回滚方案的示例代码》很多项目翻车不是因为不会做,而是走错了方向却没法回头,技术选型失败的风险我们都清楚,但真正能提前规划“回滚方案”的人不多,本文从实际项目出发,教你如何用Py... 目录描述题解答案(核心思路)题解代码分析第一步:抽象缓存接口第二步:实现两个版本第三步:根据 Fea

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

python利用backoff实现异常自动重试详解

《python利用backoff实现异常自动重试详解》backoff是一个用于实现重试机制的Python库,通过指数退避或其他策略自动重试失败的操作,下面小编就来和大家详细讲讲如何利用backoff实... 目录1. backoff 库简介2. on_exception 装饰器的原理2.1 核心逻辑2.2