OFDM 802.11a的FPGA实现(二十一)发射主控模块MCU(含代码)

news2024/12/29 1:36:26

目录

1.前言

2.主控逻辑

3.Matlab

4.verilog

5.ModelSim

6.ModelSim仿真结构与Matlab自动化对比


完整工程链接(含verilog和Matlab代码)

https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxNjM0NDk2Nw==&action=getalbum&album_id=3409621333838200834#wechat_redirecticon-default.png?t=N7T8https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxNjM0NDk2Nw==&action=getalbum&album_id=3409621333838200834#wechat_redirect 

1.前言

  对于发射部分的OFDM 802.11a的FPGA实现,已经接近闻声了,现在是万事俱备只欠东风,所有功能模块已经设计完成,目前还需要一个主控模块,其作用是:
(1)与MAC通信进行数据交互;
(2)控制一包发射数据按照PPDU帧结构的顺序进行发送。

  下面这两张图一直放出来,不觉得厌烦,这是协议的核心。

PPDU帧结构

PPDU帧结构

PPDU帧结构

PPDU帧结构

2.主控逻辑

  由于最终生成的OFDM符号有着严格的格式与时序要求,并且各个功能模块的处理延迟也能保持稳定,因此主控单元MCU需要对数据流向实现控制功能。另外,每次发射处理都是由MAC层,收到物理层传输完成信号,所发起的,且需要传输大量数据,以及配置信息,所以MCU与MAC层之间的通信也采用AXI Stream协议。

  当MCU收到MAC层发来的start信号后,对发射各模块硬件进行复位,并且接收参数配置信息。MAC层发来参数配置是21位信号,其中包含的是待发射PSDU帧长(LENGTH,12bits)、发射速率(RATE,6bits)和发射功率等级(TXPWR,3bits)三个发射参数。

  接收到参数配置信息,送往tx_gen_pkt_sig模块,生成signal域数据帧,并以字节形式输出。不清楚的,回顾之前的文章:OFDM 802.11a的FPGA实现(十九)signal域帧生成(含代码)

  复位之后,通过AXI Stream协议,向MAC层接收要发送的字节数据,并且控制训练序列开始输出。不清楚的,回顾之前的文章:OFDM 802.11a的FPGA实现(十七)PLCP的前导部分:长短训练序列组合加窗(含代码)

  复位之后,加载扰码器的初始状态。不清楚的,回顾之前的文章:OFDM802.11a的FPGA实现(四)扰码

  无论是signal域数据帧,还是MAC传来的待发送字节,都要送往并串转换模块,最终以bit的形式输出。MCU模块控制signal域数据帧,最先送往并串转换模块,接着MAC传来的待发送字节再送。

  TxPWR为发射功率等级,输出给后面的DAC使用。

  当一包数据发送完成,MCU模块接收到指令后,给MAC送去准备好信号,mcu_config_dout_rdy。

  tx_mcu模块输出依次连接扰码、卷积编码、删余、一级交织、二级交织、调制映射、插入导频、ifft、DAC模块(此模块后面一章节进行设计)。如下图所示:

连接方式

连接方式

  DAC模块,主要是将时域的输出按照前导码、signal帧、data域的顺序进行排列,将数据速率从125M的突发形式,转换为20M的连续形式,然后送往硬件DAC输出模拟信号。这个模块后面一个章节再来讲解设计。

3.Matlab

  matlab生成signal帧数据代码如下:

%% signal帧数据生成 
%RATE = [R1 R2 R3 R4] 字段
tx_rate = 48 * M * code_rate / 12 /4;
switch(tx_rate)
    case 6
        RATE = [1 1 0 1];
    case 9
        RATE = [1 1 1 1];
    case 12
        RATE = [0 1 0 1];
    case 18
        RATE = [0 1 1 1];
    case 24
        RATE = [1 0 0 1];
    case 36
        RATE = [1 0 1 1];
    case 48
        RATE = [0 0 0 1];
    case 54
        RATE = [0 0 1 1];
    otherwise
        disp('tx_rate_error');
end
%保留位
R = 0;
%LENGTH字段:LSB-MSB(bit5-16)
byte_len = dec2bin(leng_num_in/8,12);
for m = 1:12
    LENGTH(12-m+1) = str2num(byte_len(m)); 
end
%偶校验位
EVEN_PARITY = mod(sum([RATE,R,LENGTH]),2);
%尾bit
TAIL = [0 0 0 0 0 0];
%组帧
signal_preamble = [RATE,R,LENGTH,EVEN_PARITY,TAIL];

4.verilog

发射主控模块

发射主控模块

`timescale 1ns / 1ps
module tx_mcu(
 
 input       clk     ,
    input      rst_n    ,
 //MAC层发来参数配置,21位信号,其中包含的是待发射PSDU帧长(LENGTH,12bits)、
 //发射速率(RATE,6bits)和发射功率等级(TXPWR,3bits)三个发射参数。
 input       [20:0]        mcu_config_din  ,
 input                 mcu_config_din_vld ,
    input                 mcu_config_din_start,
 output reg     mcu_config_dout_rdy ,
 //MAC层发来的信息byte
    input  [7:0]   mcu_mac_din   ,
 input      mcu_mac_din_vld  ,
 output      mcu_mac_dout_rdy ,
 //输出信息串行bit流
 input      mcu_din_rdy   ,
 output      mcu_dout   ,
 output      mcu_dout_vld  ,
 output      mcu_dout_sig_flag ,
 output  [3:0]   mcu_dout_rate_con ,
 //扰码器初始值配置
 output  reg [6:0]     mcu_dout_scram_seed , //扰码器初始状态
 output  reg              mcu_dout_scram_load ,
 //物理层硬件软复位
 output reg     phy_rst_n   ,
 //输入一包数据发送完成信号
 input      tx_end    ,      
 //输出发射功率等级
 output  [2:0]   TxPWR    
);

parameter  SEED = 7'b1011101;
//signal
wire [ 5:0] sig_din_tx_rate  ;
wire [11:0] sig_din_tx_length;
wire   sig_din_vld   ;
wire   sig_din_rdy   ;
wire [7:0] sig_dout   ;
wire   sig_dout_vld  ;
wire   sig_dout_rdy  ;
wire [3:0] sig_dout_rate_con;
wire   sig_dout_last  ;
wire   sig_dout_sig_flag;
//连接并-串
wire [7:0] P2S_din    ;
wire   P2S_din_vld   ;
wire   P2S_din_rdy   ;
wire   P2S_dout   ;
wire   P2S_dout_vld  ;
wire   P2S_dout_rdy  ;
//MAC层发来传输信号mcu_config_din_start后,对硬件复位
always@(posedge clk or negedge rst_n)begin
 if(!rst_n)
  phy_rst_n <= 1'b1;
 else if(mcu_config_din_start)
  phy_rst_n <= 1'b0;
 else
  phy_rst_n <= 1'b1;
end
//发完一包数据后,准备好再次向MAC层接收数据
always@(posedge clk or negedge rst_n)begin
 if(!rst_n)
  mcu_config_dout_rdy <= 1'b1;
 else if(tx_end)
  mcu_config_dout_rdy <= 1'b1;
 else
  mcu_config_dout_rdy <= 1'b0;
end
//生成signal数据帧结构
assign sig_din_tx_rate = mcu_config_din[8:3]; 
assign  sig_din_tx_length = mcu_config_din[20:9];
assign  TxPWR = mcu_config_din[2:0];
assign  sig_din_vld = mcu_config_din_vld;
//assign sig_dout_rdy = mcu_config_dout_rdy;
assign sig_din_rdy = sig_dout_sig_flag ? P2S_dout_rdy : 1'b0;

tx_gen_pkt_sig u_tx_gen_pkt_sig(
 .clk    (clk    ),
 .rst_n    (rst_n    ),
 .sig_din_tx_rate (sig_din_tx_rate ),
 .sig_din_tx_length (sig_din_tx_length ),
 .sig_din_vld  (sig_din_vld  ),
 .sig_din_rdy  (sig_din_rdy  ),
 .sig_dout   (sig_dout   ),
 .sig_dout_vld  (sig_dout_vld  ),
 .sig_dout_rdy  (sig_dout_rdy  ),
 .sig_dout_rate_con (sig_dout_rate_con ),
 .sig_dout_last  (sig_dout_last  ),
 .sig_dout_sig_flag (sig_dout_sig_flag )
);

assign mcu_dout_rate_con = sig_dout_rate_con; 
assign mcu_dout_sig_flag = sig_dout_sig_flag;

assign P2S_din = sig_dout_sig_flag ? 
     {sig_dout[0],sig_dout[1],sig_dout[2],
     sig_dout[3],sig_dout[4],sig_dout[5],
     sig_dout[6],sig_dout[7]} : mcu_mac_din;
assign P2S_din_vld = sig_dout_sig_flag ? sig_dout_vld : mcu_mac_din_vld;
assign P2S_din_rdy = mcu_din_rdy;

Par2Ser #( .WIDTH  (4'd8),
   .LSB_FIRST (1'b1))
Par2Ser_u2(
 .clk  (clk   ),
 .rst_n  (rst_n   ),
 .din  (P2S_din  ),
 .din_vld (P2S_din_vld ),
 .din_rdy (P2S_din_rdy ),
 .dout  (P2S_dout  ),
 .dout_vld (P2S_dout_vld ),
 .dout_rdy   (P2S_dout_rdy   )
);

assign mcu_dout = P2S_dout;
assign mcu_dout_vld = P2S_dout_vld;
assign mcu_mac_dout_rdy = P2S_dout_rdy;
//扰码器初始值配置
always@(posedge clk or negedge rst_n)begin
 if(!rst_n)begin
  mcu_dout_scram_load <= 1'b0;
  mcu_dout_scram_seed <= 'd0;
 end
 else begin
  mcu_dout_scram_load <= ~phy_rst_n;
  mcu_dout_scram_seed <= SEED;
 end
end

endmodule

5.ModelSim

  等最后一个DAC模块设计完成再一起进行整个发射部分联调,现在先对MUC模块进行简单测试,粗略查看下控制时序是否正确,以及输出signal的数据是否能对应上matlab生成的。testbench测试逻辑部分如下:

always@(posedge clk or negedge rst_n)
 if(!rst_n)
  mcu_config_din_start <= 1'b0;
 else if(mcu_config_dout_rdy)
  mcu_config_din_start <= 1'b1;
 else
  mcu_config_din_start <= 1'b0;
  
always@(posedge clk or negedge rst_n)
 if(!rst_n)begin
  mcu_config_din <= 'd0;
  mcu_config_din_vld <= 1'b0;
 end
 else if(mcu_config_din_start)begin
  mcu_config_din <= {LEGENTH,6'd36,3'd0};
  mcu_config_din_vld <= 1'b1;
 end
 else
  mcu_config_din_vld <= 1'b0;
  
assign mcu_mac_din = P2S_din;
assign mcu_mac_din_vld = P2S_din_vld;
assign mcu_din_rdy = P2S_din_rdy;
assign tx_end = cnt_last; 
 
tx_mcu u_tx_mcu(
 .clk     (clk     ),
 .rst_n     (rst_n     ),
 .mcu_config_din      (mcu_config_din   ),
 .mcu_config_din_vld     (mcu_config_din_vld  ),
 .mcu_config_din_start   (mcu_config_din_start ),
 .mcu_config_dout_rdy (mcu_config_dout_rdy ),
 .mcu_mac_din   (mcu_mac_din   ),
 .mcu_mac_din_vld  (mcu_mac_din_vld  ),
 .mcu_mac_dout_rdy     (mcu_mac_dout_rdy  ),
 .mcu_din_rdy   (mcu_din_rdy   ),
 .mcu_dout       (mcu_dout    ),
 .mcu_dout_vld      (mcu_dout_vld   ),
 .mcu_dout_sig_flag     (mcu_dout_sig_flag  ),
 .mcu_dout_rate_con     (mcu_dout_rate_con  ),
 .mcu_dout_scram_seed   (mcu_dout_scram_seed   ),
 .mcu_dout_scram_load   (mcu_dout_scram_load   ),
 .phy_rst_n       (phy_rst_n    ),
 .tx_end                 (tx_end              ),
 .mcu_dout_train_rdy  (mcu_dout_train_rdy  ),
 .TxPWR        (TxPWR     )
);

仿真截图

仿真截图

6.ModelSim仿真结构与Matlab自动化对比

%% MCU
FPGA_mcu_dout = load([PATH,'mcu_data_out.txt'])';
disp(FPGA_mcu_dout);
check_signal_preamble = signal_preamble == FPGA_mcu_dout(1:24);
disp(check_signal_preamble);

  对比结果如下:

check_signal_preamble =

  1×24 logical 数组

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

 完整工程链接(含verilog和Matlab代码)

https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxNjM0NDk2Nw==&action=getalbum&album_id=3409621333838200834#wechat_redirecticon-default.png?t=N7T8https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxNjM0NDk2Nw==&action=getalbum&album_id=3409621333838200834#wechat_redirect

 

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

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

相关文章

MySql:多表设计-关联查询

目录 多表设计 代码 运行 数据库设计范式 设计三范式 1、第一范式&#xff1a; 2、第二范式&#xff1a; 3、第三范式&#xff1a; 多表设计_关联查询 外键 外键约束 代码 运行 注意&#xff1a; 应用 代码 运行 代码 运行 关联查询 含义&#xff1a; …

<项目> 云备份

目录 一、简单认识 二、实现目标 三、服务端程序负责功能及功能模块划分 四、客户端程序负责功能及功能模块划分 五、环境搭建 &#xff08;一&#xff09;gcc 7.3 &#xff08;二&#xff09;安装jsoncpp库 &#xff08;三&#xff09;下载bundle数据压缩库 &#xf…

通义千问AI免费批量写文章

简数采集器支持调用阿里通义千问AI大模型API接口&#xff0c;对采集的数据进行研究分析&#xff0c;内容创作等。 通义千问AI快速使用方法&#xff08;不用编程对接&#xff09; 目录 1. 注册申请通义千问API 2. 简数对接通义千问AI 3. 设置通义千问AI指令 4. 通义千问AI…

微软Edge

微软Edge浏览器概述 功能介绍 微软Edge是一款基于Chromium开源项目的网页浏览器&#xff0c;旨在提供更快的网页加载速度、更高的安全性和更好的用户体验。它支持多种操作系统&#xff0c;包括Windows、macOS、Android和iOS&#xff0c;能够满足不同用户的需求。Edge浏览器拥…

【论文极速读】 LLava: 指令跟随的多模态大语言模型

【论文极速读】 LLava: 指令跟随的多模态大语言模型 FesianXu 20240331 at Tencent WeChat Search Team 前言 如何将已预训练好的大规模语言模型&#xff08;LLM&#xff09;和多模态模型&#xff08;如CLIP&#xff09;进行融合&#xff0c;形成一个多模态大语言模型&#xf…

「云渲染课堂」3dmax渲染影响时间的原因有哪些

在3ds Max使用过程中经验丰富的用户普遍了解&#xff0c;渲染大型场景往往需要消耗更多的时间&#xff0c;尤其是在硬件配置相同的情况下。但有时候&#xff0c;我们可能会遇到一个反直觉的现象&#xff1a;在相同的硬件配置下&#xff0c;渲染小型场景所需的时间竟然超过了大型…

数据挖掘与机器学习——机器学习概述

一、什么是机器学习 机器学习的英文名称叫Machine Learning&#xff0c;简称ML&#xff0c;该领域主要研究的是如何使计算机能够模拟人类的学习行为从而获得新的知识。 机器学习与数据挖掘的联系&#xff1a;简单来说&#xff0c;机器学习就是让计算机从大量 的数据中学习到相关…

大创项目推荐 深度学习手势识别 - yolo python opencv cnn 机器视觉

文章目录 0 前言1 课题背景2 卷积神经网络2.1卷积层2.2 池化层2.3 激活函数2.4 全连接层2.5 使用tensorflow中keras模块实现卷积神经网络 3 YOLOV53.1 网络架构图3.2 输入端3.3 基准网络3.4 Neck网络3.5 Head输出层 4 数据集准备4.1 数据标注简介4.2 数据保存 5 模型训练5.1 修…

MagicAnimate: Temporally Consistent Human Image Animation using Diffusion Model

show lab NUS&bytedancehttps://github.com/magic-research/magic-animate 问题引入 输入参考图片 I r e f I_{ref} Iref​和动作序列 p 1 : N [ p 1 , ⋯ , p N ] p^{1:N}[p_1,\cdots,p_N] p1:N[p1​,⋯,pN​]&#xff0c;其中 N N N表示的是帧数&#xff0c;输出的是 …

MySQL主从复制+读写分离(ShardingJDBC)

MySQL主从复制读写分离 MySQL主从复制介绍二进制日志&#xff1a; MySQL的主从复制原理如下搭建主从复制准备工作主库配置从库配置 测试 读写分离案例ShardingJDBC介绍数据库环境初始工程导入读写分离配置测试1). 保存数据2). 修改数据3). 查询数据4). 删除数据 MySQL主从复制 …

ipad air6电容笔推荐,2024十大高性价比电容笔排行榜!

​电容笔作为ipad的最佳拍档&#xff0c;为学生党和打工人带来了极大的便利&#xff0c;二者搭配效率真的大大提升&#xff0c;但是&#xff0c;如何选购一支适合自己的电容笔呢&#xff1f;作为一个对数码设备非常感兴趣并且有一定了解的人&#xff0c;我根据自己多年的使用经…

deepseek是哪家公司

deepblue是什么公司 DeepSeek是杭州深度求索人工智能基础技术研究有限公司的简称。12 杭州深度求索人工智能基础技术研究有限公司&#xff0c;成立于2023年&#xff0c;位于浙江省杭州市&#xff0c;是一家专注于研究和试验发展的企业。该公司的注册资本为1000万人民币&…

安装和使用图像处理软件GraphicsMagick @FreeBSD

GraphicsMagick是一个用于处理图像的读取、写入和操作的工具软件。它被誉为图像处理领域的“瑞士军刀”&#xff0c;短小精悍&#xff0c;支持超过88种图像格式&#xff0c;包括DPX、GIF、JPEG、JPEG-2000、PNG、PDF、PNM和TIFF等。 GraphicsMagick的主要特点包括&#xff1a;…

pyqt6水平布局

效果预览 main_window.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>MainWindow</class><widget class"QMainWindow" name"MainWindow"><property name"geo…

【AI基础】反向传播

文章目录 1. 先写出第一步2.将其封装成函数3. pytorch版 1. 先写出第一步 # 定义输入值和期望输出 x_1 40.0 x_2 80.0 expected_output 60.0 初始化# 定义权重 w_1_11 0.5 w_1_12 0.5 w_1_13 0.5 w_1_21 0.5 w_1_22 0.5 w_1_23 0.5w_2_11 1.0 w_2_21 1.0 w_2_31 1…

【Android】WorkManager(章二)

剩余的三部分 官方文档 案例 实现下载器&#xff0c;并监听下载进度 界面 定义Worker 在官方案例的前提下&#xff0c;进行完善 下载download 下载进度 授予权限 开始工作并监听 完整代码 MainActivity.java package com.test.downloadworkerapplication;import static…

【SpringBoot】整合百度文字识别

流程图 一、前期准备 1.1 打开百度智能云官网找到管理中心创建应用 全选文字识别 1.2 保存好AppId、API Key和Secret Key 1.3 找到通用场景文字识别&#xff0c;立即使用 1.4 根据自己需要&#xff0c;选择要开通的项目 二、代码编写 以通用文字识别&#xff08;高精度版&am…

AI图书推荐:用OpenAI API 开发AI应用详细指南

随着人工智能不断重塑行业&#xff0c;OpenAI 处于人工智能研究的前沿&#xff0c;了解如何创建聊天机器人、虚拟助手、内容生成器和生产力增强器等创新应用程序是一个游戏规则改变者。本书《用OpenAI API 开发AI应用详细指南》&#xff08;OpenAI API Cookbook&#xff09;&am…

Docker访问文件权限受限问题解决

问题描述 运行项目的docker环境&#xff0c;新添加了一个数据集&#xff0c;但是数据集的访问权限受限&#xff08;Permission dinied&#xff09;&#xff0c;运行的命令如图所示 问题解决 chmod 777 xxx YYDS&#xff01;&#xff01;&#xff01;但是单纯直接运行会因为权限…

LLaVA UHD:一种可感知任意纵横比和高分辨率图像的LMM

LLaVA-UHD: an LMM Perceiving Any Aspect Ratio and High-Resolution Images (2024-03-18) 文章概要作者: Ruyi Xu; Yuan Yao; Zonghao Guo; Junbo Cui; Zanlin Ni; Chunjiang Ge; Tat-Seng Chua; Zhiyuan Liu; Maosong Sun; Gao Huang期刊: arXiv 预印版DOI: 10.48550/arXiv…