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

目录

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

 

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

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

相关文章

PHP报错 Notice: Undefined index: action in

upload靶场PHP报错 Notice: Undefined index: action in 修改 php.ini 中的 error配置下错误显示方式&#xff1a;将error_reporting E_ALL 修改为 error_reporting E_ALL & ~E_NOTICE 修改后重启下APCHE服务即可。

Mysql超详细安装配置教程(保姆级图文)

MySQL是一种流行的开源关系型数据库管理系统&#xff0c;它广泛用于网站和服务的数据存储和管理。MySQL以其高性能、可靠性和易用性而闻名&#xff0c;是许多Web应用程序的首选数据库解决方案之一。 一、下载安装包 &#xff08;1&#xff09;从网盘下载安装文件 点击此处直…

UE5中搭建一个简单的海岛

本文将用UE的WaterSystem与地形搭建一个简单的海岛&#xff0c;通过WaterSystem的参数设置&#xff0c;可以更好的自定义海岸线等效果。 1.基础风貌 1.1.首先新建一个Basic基础场景&#xff0c;切换到地形编辑模式刷出一块高地&#xff0c;用于沙滩。 1.2.引入UE官方插件Wat…

【EXCEL_VBA_实战】两组数据比对是否一致(字符串数组)

工作背景&#xff1a;比对两组数据是否一致&#xff08;位置非一一对应&#xff09; 思路构建&#xff1a;两组数据转换为两组字符串数组&#xff0c;比对所包含元素是否相同 问题点&#xff1a;A数组的第一个元素不一定与B数组的第一个元素对应&#xff0c;此时无法通过公式…

C++开源库glog使用封装--自定义日志输出格式,设置日志保留时间

glog下载和编译 glog开源地址 https://github.com/google/glog glog静态库编译 cd /home/wangz/3rdParty/hldglog/glogmkdir out mkdir build && cd buildcmake .. -DCMAKE_INSTALL_PREFIX../out -DCMAKE_BUILD_TYPERelease -DBUILD_SHARED_LIBSOFF本文选择的glo…

HashMap中添加元素

一、HashMap底层使用了3种结构 hash数组(定位)、链表(存储元素)、红黑树(存储元素,提高查询效率) 二、添加流程描述&#xff1a; 添加元素时&#xff0c;先为元素计算出一个hash值&#xff0c;再用hash值%数组长度得到元素位置&#xff0c;将元素(k:v)封装到Node对象中&…

sql server【 特定分隔符隔开的字符串转表】和【 列转逗号隔开的字符串】

文章目录 引言I 特定分隔符隔开的字符串转表II Sql Server 列转逗号隔开的字符串2.1 多列转行,逗号分隔(字段拼接/字段分割)2.1 案例引言 Sql Server 列转逗号隔开的字符串 和 逆转,常用于数据导出和数据查询。 I 特定分隔符隔开的字符串转表 CREATE FUNCTION [dbo].[GetIDLi…

python科研数据可视化之折线图

例如 &#xff1a; 下面的配色表画出的图很好看。选择喜欢的颜色&#xff0c;找到代码中颜色部分进行修改即可。 代码部分已经有详细的注释&#xff0c;就不一一解释了。另外&#xff0c;如果想要坐标轴从设定的值开始就把下面代码中的范围xlim&#xff0c;ylim进行注释。 imp…

MySQL的备份及恢复

目录 5、MySQL的备份及恢复 5.1 MySQL日志管理 5.1.1 MySQL日志类型 5.1.2 错误日志 5.1.3 通用查询日志 5.1.4 慢查询日志 5.1.5 二进制日志 开启日志 二进制日志管理>又叫日志滚动 二进制日志还原数据 删除二进制日志文件&#xff1a; 5.1.6实例&#xff1a; 使用mysqlbi…

windows远程桌面无法连接,轻松解决 Windows远程桌面无法连接问题的故障排查

Windows远程桌面是一个强大且实用的工具&#xff0c;它允许用户远程访问和操作另一台计算机。然而&#xff0c;有时您可能会遇到无法连接的问题&#xff0c;这无疑会严重影响工作效率和体验。但别担心&#xff0c;本文将为您揭示解决这一问题的关键策略&#xff0c;让您轻松恢复…

2024042701-disjoint-set

并查集 Disjoint-Set 一、前言 并查集的历史 1964年&#xff0c; Bernard A. Galler 和 Michael J. Fischer 首次描述了不相交的并查集&#xff0c;1975 年&#xff0c;Robert Tarjan 是第一个证明O(ma(n))&#xff08;逆阿克曼函数&#xff09;算法时间复杂度的上限&#x…

简易CAD程序:Qt多文档程序的一种实现

注&#xff1a;文中所列代码质量不高&#xff0c;但不影响演示我的思路 实现思路说明 实现DemoApplication 相当于MFC中CWinAppEx的派生类&#xff0c;暂时没加什么功能。 DemoApplication.h #pragma once#include <QtWidgets/QApplication>//相当于MFC中CWinAppEx的派生…

c语言:strcmp

strcmp函数是用于比较两个字符串的库函数&#xff0c;其功能是根据ASCII值逐一对两个字符串进行比较。 语法&#xff1a;strcmp(str1, str2) 返回值&#xff1a; 如果str1等于str2&#xff0c;则返回0。 如果str1小于str2&#xff0c;则返回负数&#xff08;具体值取决于C…

【数据分析面试】51. 读取大型csv文件

题目 假设你是一家科技公司的数据分析师。近期由于管理层变动&#xff0c;新的总经理上任&#xff0c;他想要了解公司过往的交易情况数据&#xff0c;并且这个任务由数据分析团队负责完成。历史交易数据下载导出完成后&#xff0c;团队发现Csv文件大小超过了5个G&#xff0c;使…

解决Wordpress中Cravatar头像无法访问问题

一、什么是Cravatar Gravatar是WordPress母公司Automattic推出的一个公共头像服务&#xff0c;也是WordPress默认的头像服务。但因为长城防火墙的存在&#xff0c;Gravatar在中国时不时就会被墙一下&#xff0c;比如本次从2021年2月一直到8月都是不可访问状态。 在以往的时候&…

OVS名词解释(随手记)

qbr&#xff1a;Linux网桥&#xff0c;为虚拟机提供安全组服务&#xff0c;负责安全隔离&#xff0c;有关安全组的实现。 veth-pair&#xff1a;一对虚拟端口设备 br-int&#xff1a;OVS的核心网桥之一。二三层流量均需经过该网桥&#xff0c;通过local vlan tag实现主机内部不…

Greco:使用ZKP来证明FHE参与方的RLWE密文格式正确

1. 引言 以太坊基金会Enrico Bottazzi 2024年论文Greco: Fast Zero-Knowledge Proofs for Valid FHE RLWE Ciphertexts Formation&#xff0c;开源代码见&#xff1a; https://github.com/privacy-scaling-explorations/greco&#xff08;Rust & Python&#xff09;【基于…

2024最新彩虹聚合DNS管理系统源码v1.3 全开源

简介&#xff1a; 2024最新彩虹聚合DNS管理系统源码v1.3 全开源 聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、DNSLA、CloudFlare。 本系统支持多用户&#xff0c;每个用户可…

数据库|SQLServer数据库管理系统基本使用

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 此处学习是以SQL Server为例。 学习数据服务打开、服务器名称的集中写法、TCP/IP协议的打开和登录模式修改的四个步骤,以下为学习笔记。 数据库管理系统包括&#xff1a;客户端服务端&#xff08;运行在服务器上面的一…

Python编程-后端开发之Django5应用请求处理与模板基础

Python编程-后端开发之Django5应用请求处理与模板基础 最近写项目&#xff0c;刚好用到了Django&#xff0c;现在差不多闲下来&#xff0c;个人觉得单体项目来讲django确实舒服&#xff0c;故写此总结 模板语法了解即可&#xff0c;用到了再看&#xff0c;毕竟分离已经是主流操…