OFDM 802.11a的FPGA实现(十六)长训练序列:LTS(含Matlab和verilog代码)

news2024/11/13 16:15:50

目录

  • 1.前言
  • 2.原理
  • 3.Matlab生成长训练序列
  • 4.硬件实现
  • 5.ModelSim仿真
  • 6.和Matlab仿真结果对比

原文链接(相关文章合集): OFDM 802.11a的xilinx FPGA实现

1.前言

  在之前已经完成了data域数据的处理,在构建整个802.11a OFDM数据帧的时候,还剩下前导码和signal域的数据帧,这两部分的内容。 PLCP的前导部分由一组重复10次的短训练序列和一组加了一个长型保护间隔与重复2次的有效OFDM符号组成的长训练序列组成。上一节实现了短训练序列,这一节实现长训练序列。

PPDU帧结构

PPDU帧结构

2.原理

从时域的帧结构来看,在短训练序列之后是长训练序列,其长度为8us,其中包括两个有效()FDM符号的长度(每个3.2us)和一个长型保护间隔的长度(1.6us)。长训练序列主要用于精确的频率偏差估计和信道估计。从频域来看,长训练序列符号与正常的OFDM符号一样由53(包括直流处一个取“0”值的空符号)个子载波组成,分别占据从一26~26的子信道。长训练的作用之一是在频率进行信道均衡。为了简化接收端的信道估计运算,传输的数据是BPSK调制的,即

长训练序列

在实际使用过程当中,由与短训练序列和长训练序列是固定的,因此可以先使用matlab,python等工具先将短训练序列和长训练序列生成出来,然后将序列存储在ROM当中,在使用的时候,直接从ROM当中读取出来就可以了。

3.Matlab生成长训练序列

由于Data域数据在IFFT处理之前会扩大8倍,相应的长训练序列在进行IFFT处理之前也需要扩大8倍。同时长训练序列也是需要经过加窗处理的,即多输出一个样值,该值为第一个样值,同时将第一个样值与最后一个样值缩小一倍。

lts = [ 0,1,-1,-1,1,1,-1,1,-1,1,-1,-1,-1,-1,-1,1,1,-1,-1,1, ...
    -1,1,-1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,-1,-1,1,1,-1,1,-1,1,1,1,1,1,1,...
    -1,-1,1,1,-1,1,-1,1,1,1,1 ];
lts_time = 8 * ifft(lts,64);        %长训练序列进行ifft
q = quantizer('fixed','round','saturate',[8,6]);%复数以8位定点数形式进行输出,格式为:1位符号位,一位整数位,6位小数位,负数以补码形式表示。
lts_time_q = num2bin(q,lts_time);%量化,存到FPGA的ROM
lts_rom = [0.5*lts_time(33),lts_time(34:end),lts_time,lts_time,0.5*lts_time(1)];    %长训练序列加窗     

长训练序列时域值(复数以8位定点数形式进行输出,格式为:1位符号位,一位整数位,6位小数位,负数以补码形式表示):

    '01010000 + 00000000i'
    '11111101 + 11000010i'
    '00010100 + 11000111i'
    '00110010 + 00101010i'
    '00001011 + 00001110i'
    '00011111 + 11010011i'
    '11000101 + 11100100i'
    '11101100 + 11001010i'
    '00110010 + 11110011i'
    '00011011 + 00000010i'
    '00000001 + 11000101i'
    '10111010 + 11101000i'
    '00001101 + 11100010i'
    '00011110 + 11111000i'
    '11110100 + 01010010i'
    '00111101 + 11111110i'
    '00100000 + 11100000i'
    '00010011 + 00110010i'
    '11100011 + 00010100i'
    '10111101 + 00100001i'
    '00101010 + 00101111i'
    '00100100 + 00000111i'
    '11100001 + 00101010i'
    '11100011 + 11110101i'
    '11101110 + 10110011i'
    '11000010 + 11111000i'
    '10111111 + 11110110i'
    '00100110 + 11011010i'
    '11111111 + 00011100i'
    '11010001 + 00111011i'
    '00101111 + 00110110i'
    '00000110 + 00110010i'
    '10110000 + 00000000i'
    '00000110 + 11001110i'
    '00101111 + 11001010i'
    '11010001 + 11000101i'
    '11111111 + 11100100i'
    '00100110 + 00100110i'
    '10111111 + 00001010i'
    '11000010 + 00001000i'
    '11101110 + 01001101i'
    '11100011 + 00001011i'
    '11100001 + 11010110i'
    '00100100 + 11111001i'
    '00101010 + 11010001i'
    '10111101 + 11011111i'
    '11100011 + 11101100i'
    '00010011 + 11001110i'
    '00100000 + 00100000i'
    '00111101 + 00000010i'
    '11110100 + 10101110i'
    '00011110 + 00001000i'
    '00001101 + 00011110i'
    '10111010 + 00011000i'
    '00000001 + 00111011i'
    '00011011 + 11111110i'
    '00110010 + 00001101i'
    '11101100 + 00110110i'
    '11000101 + 00011100i'
    '00011111 + 00101101i'
    '00001011 + 11110010i'
    '00110010 + 11010110i'
    '00010100 + 00111001i'
    '11111101 + 00111110i'

4.硬件实现

LTS Generator的设计原理与实现方式与STS Generator相似。标准规定,LTS 包括两个周期的 Symbol(每个有64个样值)和一个长度为32个采样点的长型CP(LTS64个样值中的后32个)。为此,存储LTS的片内ROM被设定为64字X16位,如上面所示,读取时通过对Read Address的控制先输出后32个地址空间中的样值形成CP,然后再将整个ROM中的样值按顺序重复读取两次。verilog代码如下:

assign	En_cnt = LTS_din_rdy & ~cnt_last;
assign	addr = cnt - 6'd32;

counter #(.CNT_NUM('d161),
		.ADD(1'b1))
u_counter(
.clk		(clk				),	
.rst_n		(rst_n				),
.En_cnt		(En_cnt				),      
.cnt		(cnt				),	
.cnt_last	(cnt_last			)
);

always @(posedge clk or negedge rst_n) 
	if(!rst_n)begin
		LTS_dout_last <= 1'b0;
		LTS_dout_Index <= 'd0;
	end
	else begin
		LTS_dout_last <= cnt_last;
		LTS_dout_Index <= cnt;
	end
		
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin  //时域样值Im       Re
        Long_Mem[0]  <= {8'b00000000 , 8'b01010000};					
        Long_Mem[1]  <= {8'b11000010 , 8'b11111101};
        Long_Mem[2]  <= {8'b11000111 , 8'b00010100};
        Long_Mem[3]  <= {8'b00101010 , 8'b00110010};
        Long_Mem[4]  <= {8'b00001110 , 8'b00001011};
        Long_Mem[5]  <= {8'b11010011 , 8'b00011111};
        Long_Mem[6]  <= {8'b11100100 , 8'b11000101};
        Long_Mem[7]  <= {8'b11001010 , 8'b11101100};
        Long_Mem[8]  <= {8'b11110011 , 8'b00110010};
        Long_Mem[9]  <= {8'b00000010 , 8'b00011011};
        Long_Mem[10] <= {8'b11000101 , 8'b00000001};
        Long_Mem[11] <= {8'b11101000 , 8'b10111010};
        Long_Mem[12] <= {8'b11100010 , 8'b00001101};
        Long_Mem[13] <= {8'b11111000 , 8'b00011110};
        Long_Mem[14] <= {8'b01010010 , 8'b11110100};
        Long_Mem[15] <= {8'b11111110 , 8'b00111101};
		Long_Mem[16] <= {8'b11100000 , 8'b00100000};
		Long_Mem[17] <= {8'b00110010 , 8'b00010011};
		Long_Mem[18] <= {8'b00010100 , 8'b11100011};
		Long_Mem[19] <= {8'b00100001 , 8'b10111101};
		Long_Mem[20] <= {8'b00101111 , 8'b00101010};
		Long_Mem[21] <= {8'b00000111 , 8'b00100100};
		Long_Mem[22] <= {8'b00101010 , 8'b11100001};
		Long_Mem[23] <= {8'b11110101 , 8'b11100011};
		Long_Mem[24] <= {8'b10110011 , 8'b11101110};
		Long_Mem[25] <= {8'b11111000 , 8'b11000010};
		Long_Mem[26] <= {8'b11110110 , 8'b10111111};
		Long_Mem[27] <= {8'b11011010 , 8'b00100110};
		Long_Mem[28] <= {8'b00011100 , 8'b11111111};
		Long_Mem[29] <= {8'b00111011 , 8'b11010001};
		Long_Mem[30] <= {8'b00110110 , 8'b00101111};
		Long_Mem[31] <= {8'b00110010 , 8'b00000110};
		Long_Mem[32] <= {8'b00000000 , 8'b10110000};
		Long_Mem[33] <= {8'b11001110 , 8'b00000110};
		Long_Mem[34] <= {8'b11001010 , 8'b00101111};
		Long_Mem[35] <= {8'b11000101 , 8'b11010001};
		Long_Mem[36] <= {8'b11100100 , 8'b11111111};
		Long_Mem[37] <= {8'b00100110 , 8'b00100110};
		Long_Mem[38] <= {8'b00001010 , 8'b10111111};
		Long_Mem[39] <= {8'b00001000 , 8'b11000010};
		Long_Mem[40] <= {8'b01001101 , 8'b11101110};
		Long_Mem[41] <= {8'b00001011 , 8'b11100011};
		Long_Mem[42] <= {8'b11010110 , 8'b11100001};
		Long_Mem[43] <= {8'b11111001 , 8'b00100100};
		Long_Mem[44] <= {8'b11010001 , 8'b00101010};
		Long_Mem[45] <= {8'b11011111 , 8'b10111101};
		Long_Mem[46] <= {8'b11101100 , 8'b11100011};
		Long_Mem[47] <= {8'b11001110 , 8'b00010011};
		Long_Mem[48] <= {8'b00100000 , 8'b00100000};
		Long_Mem[49] <= {8'b00000010 , 8'b00111101};
		Long_Mem[50] <= {8'b10101110 , 8'b11110100};
		Long_Mem[51] <= {8'b00001000 , 8'b00011110};
		Long_Mem[52] <= {8'b00011110 , 8'b00001101};
		Long_Mem[53] <= {8'b00011000 , 8'b10111010};
		Long_Mem[54] <= {8'b00111011 , 8'b00000001};
		Long_Mem[55] <= {8'b11111110 , 8'b00011011};
		Long_Mem[56] <= {8'b00001101 , 8'b00110010};
		Long_Mem[57] <= {8'b00110110 , 8'b11101100};
		Long_Mem[58] <= {8'b00011100 , 8'b11000101};
		Long_Mem[59] <= {8'b00101101 , 8'b00011111};
		Long_Mem[60] <= {8'b11110010 , 8'b00001011};
		Long_Mem[61] <= {8'b11010110 , 8'b00110010};
		Long_Mem[62] <= {8'b00111001 , 8'b00010100};
		Long_Mem[63] <= {8'b00111110 , 8'b11111101};
		LTS_dout <= 'd0;
		LTS_dout_vld <= 1'b0;
	end
	else if(LTS_din_rdy & LTS_dout_last)
		LTS_dout_vld <= 1'b0;
	else if(cnt == 'd0)begin
		LTS_dout <= {$signed(Long_Mem[32][15:8])>>>1,$signed(Long_Mem[32][7:0])>>>1}; 
		LTS_dout_vld <= 1'b1;
	end
	else if(cnt_last)begin
		LTS_dout <= {$signed(Long_Mem[0][15:8])>>>1,$signed(Long_Mem[0][7:0])>>>1};
		LTS_dout_vld <= 1'b1;
	end
	else if(cnt < 32)begin
		LTS_dout <= Long_Mem[{1'b1,cnt[4:0]}]; 
		LTS_dout_vld <= 1'b1;
	end
	else begin
		LTS_dout <= Long_Mem[addr[5:0]]; 
		LTS_dout_vld <= 1'b1;
	end
end

5.ModelSim仿真

仿真缩略图

仿真细节图

6.和Matlab仿真结果对比

%% LTS
FPGA_LTS_dout = readlines('D:/FPGA/OFDM_802.11a_my/TX/matlab/LTS_data_out.txt','EmptyLineRule','skip')';
display(FPGA_LTS_dout);
FPGA_Im_LTS_dout = extractBefore(FPGA_LTS_dout,9);
FPGA_Re_LTS_dout = extractAfter(FPGA_LTS_dout,8);
q = quantizer('fixed','round','saturate',[8,6]);
FPGA_Re_LTS_dout = bin2num(q,FPGA_Re_LTS_dout);
FPGA_Im_LTS_dout = bin2num(q,FPGA_Im_LTS_dout);
FPGA_Re_LTS_dout = cell2mat(FPGA_Re_LTS_dout);
FPGA_Im_LTS_dout = cell2mat(FPGA_Im_LTS_dout);
FPGA_LTS_dout = FPGA_Re_LTS_dout + 1j*FPGA_Im_LTS_dout;
lts_rom_q = num2bin(q,lts_rom);%量化
lts_rom = bin2num(q,lts_rom_q);%反量化
check_LTS = FPGA_LTS_dout == lts_rom.';
display(check_LTS);
check_LTS =

  1×161 logical 数组

  列 1 至 40

   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1

  列 41 至 80

   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1

  列 81 至 120

   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1

  列 121 至 160

   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1

  列 161

   1

今天在设计这部分时,发现前面OFDM 802.11a的FPGA实现中的文章在涉及到加窗操作的时候,使用到了移位操作,但是没有考虑到有符号数的问题。而恰好今天发现了这一问题,写了一篇文章详细对verilog中移位操作时,有符号数和无符号数的区别进行讲解,并且设计补码、反码、原码的知识。

感兴趣的可以前往查看https://mp.weixin.qq.com/s/5II3YzVeEXl9BoTe8MM5ZQ
原文链接(相关文章合集):OFDM 802.11a的xilinx FPGA实现

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

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

相关文章

QT基础 获取颜色

比如我们要获取图片上某个点的颜色&#xff0c;要怎么处理呢&#xff1f; 1.获取鼠标坐标 2.截图并将坐标代入途中获取RGB&#xff08;这里要考虑坐标不在范围&#xff09; 假如是通过mousePressEvent获取到鼠标坐标 void mousePressEvent(QMouseEvent* e) {QPoint orgPoint…

vue2 配置运行环境

vue2 配置运行环境 在 vue2 项目中配置运行环境 在项目中新建 .env.development 文件 和 .env.production 文件 .env.development NODE_ENV development //指定当前环境模式 VUE_APP_MODE development VUE_APP_BASE_URL "/dev-api".env.production NODE_ENV &q…

粒子系统技术在AI去衣应用中的创新探索

引言&#xff1a; 随着计算机视觉和人工智能技术的飞速发展&#xff0c;AI去衣技术逐渐走进公众视野。这一技术以其独特的应用前景和技术挑战引起了广泛的关注。在实现衣物去除的同时保持图像质量的关键技术之一&#xff0c;便是粒子系统技术。本文将深入探讨粒子系统技术在AI去…

文件系统,磁盘的物理存储结构和逻辑存储结构

问题导入 在计算机中不是所有的文件都是被打开的&#xff0c;只有我们要用的文件的被打开&#xff0c;大部分文件&#xff08;当前不需要访问的文件&#xff09;&#xff0c;都在磁盘中保存着。问题是没有被打开的文件是否需要管理&#xff1f; 这就好比我有十套衣服&#xff…

LBSS138LT1G 丝印J1 SOT-23 N沟道 50V/200mA 贴片MOSFET

LBSS138LT1G的应用领域广泛&#xff0c;主要因为它是一种N沟道金属氧化物半导体场效应晶体管&#xff08;MOSFET&#xff09;&#xff0c;具有低电荷、快速开关速度和高阻断特性。以下是一些典型的应用领域&#xff1a; 1. 消费电子产品&#xff1a;LBSS138LT1G常用于电视、音响…

【UE5.1 角色练习】01-使用小白人蓝图控制商城角色移动

目录 效果 步骤 一、导入资源 二、控制角色移动 三、更换角色移动动作 效果 步骤 一、导入资源 新建一个工程&#xff0c;然后在虚幻商城中将角色动画的相关资源加入工程&#xff0c;这里使用的是“动画初学者内容包”和“MCO Mocap Basics” 将我们要控制的角色添加进…

洗地机怎么挑?洗地机选购指南,2024洗地机测评选购攻略

在快节奏的生活中&#xff0c;繁琐的清洁工作往往令人头疼&#xff0c;随着洗地机的诞生&#xff0c;极大地简化了清洁的过程&#xff0c;洗地机凭借着它吸拖洗为一体的高效清洁特点&#xff0c;受到家庭和商业场所的广泛欢迎。那么&#xff0c;洗地机怎么挑&#xff0c;要注意…

什么是Zoho CRM客户关系系统管理?

以客户为中心的商业时代&#xff0c;卓越的客户体验已成为企业持续增长与成功的关键,为了在这场激烈的市场竞争中脱颖而出&#xff0c;企业需要一套强大、灵活且智能的客户关系管理系统——Zoho CRM应运而生&#xff0c;它不仅是管理客户信息的工具箱&#xff0c;更是驱动业务增…

数据结构篇3—《龙门客“栈”》

文章目录 &#x1f6a9;前言1、栈的概念2、栈的实现框架3、栈的代码实现3.1、栈的初始化和销毁3.2、入栈\出栈\返回栈顶元素\元素个数\判空3.3、栈定义注意事项 4、栈的应用实例——《括号匹配问题》 &#x1f6a9;前言 前面记录了关于顺序表和链表的数据结构&#xff0c;这一篇…

2.1.2 C++程序设计——程序基本概念

文章目录 展示大纲1、程序基本概念2、基本数据类型3、程序基本语句4、基本运算5、数学库常用函数6、结构化程序设计展示大纲 1、程序基本概念

数据结构初阶 顺序表的补充

一. 题目的要求 写出三种链表的接口函数 它们的功能分别是 1 查找数的位置 2 在pos位置插入值 3 在pos位置删除值 二. 实现pos 这个其实很简单 找到一步步遍历 找到这个数字就返回 找不到就提示用户下 这个数字不存在 int SLFind(SL* ps,SLDateType x) {assert(ps);int…

C# WinForm —— 21 RichTextBox 使用

1. 加载文件到控件中 加载文件时&#xff0c;要设置文件的路径和类型RichTextBoxStreamType&#xff0c;文件类型包含&#xff1a; RichText 0&#xff1a;富文本格式&#xff08;RTF&#xff09;流PlainText 1&#xff1a;纯文本流对象链接和嵌入&#xff08;OLE&#xff…

根据参考风格进行矢量图绘制

摘要 利用机器学习根据给定的文本描述生成图像的技术已经取得了显著的进步&#xff0c;例如CLIP图像-文本编码器模型的发布&#xff1b;然而&#xff0c;当前的方法缺乏对生成图像风格的艺术控制。我们提出了一种方法&#xff0c;用于为给定的文本描述生成指定风格的绘图&…

DIYGW UniApp可视化工具:低代码时代的前端开发新体验

摘要&#xff1a; 随着技术的不断发展&#xff0c;前端开发领域也迎来了低代码时代的浪潮。本文介绍了DIYGW UniApp可视化工具&#xff0c;这款工具以其傻瓜式、拖拽式、模块化的特性&#xff0c;为前端开发者提供了一个全新的开发体验。通过DIYGW UniApp&#xff0c;用户无需深…

【数据可视化-05】:Plotly数据可视化宝典

一、引言 数据可视化是机器学习流程中不可或缺的一部分。通过图形和图表展示数据&#xff0c;我们可以更直观地理解数据的分布、趋势和关联&#xff0c;从而更有效地进行数据分析、特征工程和模型评估。Plotly是一个功能强大且灵活的数据可视化库&#xff0c;它提供了丰富的图表…

解析C++ 网络输入输出缓冲区Buffer类的设计与实现(muduo库)

网络输入输出缓冲区&#xff08;Buffer&#xff09;是为了优化网络通信性能而设计的。通过将数据存储在缓冲区中&#xff0c;可以减少对网络的频繁访问&#xff0c;提高数据传输效率。缓冲区还可以帮助处理数据流中的突发性和短时延&#xff0c;使得数据的发送和接收更加稳定和…

SprintBoot案例-增删改查

黑马程序员JavaWeb开发教程 文章目录 一、准备工作1. 准备数据库表1.1 新建数据库mytlias1.2 新建部门表dept1.3 新建员工表emp 2. 准备一个Springboot工程2.1 新建一个项目 3. 配置文件application.properties中引入mybatis的配置信息&#xff0c;准备对应的实体类3.1 引入myb…

SC8908电机驱动芯片替代AN41908

SC8908 描述 五路H桥静音驱动电机驱动芯片&#xff0c;闭环直流电机光圈调节&#xff0c;支持霍尔位置检测&#xff0c; 2个步进电机。步进电机驱动带256微步细分。 主要特性 • 步进驱动H桥每路250mA最大驱动电流 • 光圈直流驱动H桥每路150mA最大驱动电流 • 单独…

XX集团IT需求解决方案和实施路线图(54页PPT)

一、资料介绍 文件格式&#xff1a;PPTX&#xff0c;文件为格式转化后文件 源文件格式&#xff1a;PDF 文件页数&#xff1a;54页 关注【数据化运营圈】下载更多数智解决方案 PPT开篇即明确指出了XX集团在信息化建设方面的核心需求&#xff0c;包括提高业务处理效率、优化数…

stack、queue、priority_queue以及仿函数

我们上次对std中的list进行实现&#xff0c;今天我们要实现stack、queue、priority_queue以及仿函数。 目录 stack堆堆的框架构造函数push插入pop删除size()大小empty()判断空top()取栈顶的元素 queue队列队列框架问题&#xff1a; 这里我们为什么用deque? 插入删除取头数据取…