FPGA:RS编码仿真过程

news2025/1/21 3:03:26

FPGA:RS编码仿真过程

RS码是一种纠错性能很强的线性纠错码,能够纠正随机错误和突发错误。RS码是一种多进制BCH码,能够同时纠正多个码元错误。

之前已经记录了在MATLAB中进行rs编解码的过程,现在利用FPGA的IP核实现RS编码的过程,方便使用RS编码。

这个过程分成两部分来记录,这篇主要记录rs编码过程。

1. 开始准备

在FPGA设计通信系统的过程中进行rs编译码,需要用到rs编译码的IP核,这个IP核已经分享,可以直接下载。也已经通过程序自己编写编译码的过程,但是完全没有必要,现成的IP核用好就可以了。

同时为了更好的理解FPGA中rs编码的过程,这个仿真程序的参数是可以与记录的MATLAB教程相对应的。

同时在使用IP核的重要的一步,需要下载对应的pdf文档,这个能够帮助更好的使用IP核,编写自己的程序。

2. RS编码IP核

RS编码IP核全名 Reed-Solomon Encoder,首先看这个rs编码IP核的需要设置的参数。

IP核设置

这里面和MATLAB仿真对应的参数设置是Symbol Width,这个对应MATLAB中的参数m,也就是符号的位宽,Data Symbols(k)Symbols Per Block(n)分别对应kn。这里的设置注意,k的限制是和n相差正偶数。简单来说就是每一次k个数据被编码,然后生成n个数据,每个数据的位宽是m,然后参数Field Polynomial是多项式,这个所对应的和MATLAB中的也是一样的,这在文档中有。

在这里插入图片描述

然后注意剩下的参数,其中第一个Code Specification参数选择第一个选项Custom,其他的选项可以对应不同的协议的,这个详细的可以查看文档,这个直接选择Custom,然后参数Scaling Factor(h)这个参数可以设置成默认的1,然后注意Generator Start参数设置为1.
这两个参数的解释参照技术文档中的说法是h是生成器多项式根索引的比例因子,第二个参数是生成多项式第一个根的伽罗瓦域对数,这两个参数直接都设置成1就可以了。

然后再Implementation参数设置页面中,需要设置的参数相对较少。

在这里插入图片描述

可以参考如上设置,选择一个通道,然后把m_axis_output_tready信号勾选上。同时注意Latency的数值是多少,这个可以与生成的编码数据对应上,这里main设置完为5,相当于编码后的输出延时5个clk

3. 代码编写

接下来进行代码编写,直接上代码rs_encoder.v。在这里是利用自然数进行编码,0-15。大体思路是用有效信号控制输入的数据,使得在有效的时候依次输入0-15。这里面的ready信号和valid信号相关控制可以直接看程序,和最后的仿真时序。编码的参数如上面的设置m=4,n=15,k=3,ploy=19

`timescale 1ns / 1ps

module rs_encoder(
    input clk,          //时钟
    input rst_n         // 复位  高电平复位
//    input [7:0] data_in,  // 输入的待编码数据
//    output [7:0] dataout      // 输出的解码数据
    );

wire rs_encode_input_tready;  // 编码输入准备信号
reg rs_encode_input_tvalid_reg;  // 编码输入有效信号
reg rs_encode_input_tready_reg;
wire rs_encode_input_tlast;
reg rs_encode_input_tlast_reg;
wire[7:0] rs_encode_data;
wire rs_encode_output_tvalid;
wire rs_encode_output_tlast;
wire rs_enocde_output_tready;
reg rs_enocde_output_tready_reg;

parameter K = 3;   //  对应MATLAB仿真中的k和n的值,这个在IP核设置中已经有体现
parameter N = 4;   //
parameter L = 15;  // 编码之后的数据长度

reg [3:0] datain_num; // 每一组编码的原始数据个数
reg [5:0] dataout_num;  //输出编码数据的个数

// 设计输入数据
reg [3:0] datain;
always@(posedge clk)begin
    if(~rst_n)begin
        datain <= 4'b0;
        rs_encode_input_tready_reg <= 1'b0;
        rs_encode_input_tvalid_reg <= 1'b0;
        rs_encode_input_tlast_reg <= 1'b0;
        rs_enocde_output_tready_reg <= 1'b0;
        datain_num <= 4'b0;
    end
    else begin
        rs_encode_input_tready_reg <= rs_encode_input_tready;
        rs_encode_input_tvalid_reg <= 1'b1;
        if(rs_encode_input_tready == 1'b1 && rs_encode_input_tvalid_reg == 1'b1)begin // 在ready 和valid信号都有效的时候才开始编码数据,可以在这里计数编码的个数。
            datain <= datain + 4'b1;
            datain_num <= 4'b1 + datain_num;
            rs_enocde_output_tready_reg <= 1'b1;
        end
        else begin
        end
    end
end

// 根据每一组编码的组数来确定数据顺序 控制最后一个tlast信号。
always@(posedge clk)begin
    if(~rst_n)begin
        rs_encode_input_tlast_reg <= 1'b0; // 这个信号是需要在一组中的最后一个数据时候信号处于高电平 和k的大小对应
    end
    else begin
        if(datain_num >= K)begin
            rs_encode_input_tlast_reg <= 1'b1;
        end
        else begin
            rs_encode_input_tlast_reg <= 1'b0;  //然后重新置零
        end
    end
end

wire [3:0] data_in;
assign data_in = datain;

rs_encoder_0 rs_encoder_0_ins (   //latency 5clk
  .aclk(clk),                                                      // input wire aclk
  .aresetn(rst_n),                                                // input wire aresetn
  .s_axis_input_tdata(data_in),                          // input wire [7 : 0] s_axis_input_tdata
  .s_axis_input_tvalid(rs_encode_input_tvalid_reg),                        // input wire s_axis_input_tvalid
  .s_axis_input_tready(rs_encode_input_tready),                        // output wire s_axis_input_tready
  .s_axis_input_tlast(rs_encode_input_tlast_reg),                          // input wire s_axis_input_tlast
  .m_axis_output_tdata(rs_encode_data),                        // output wire [7 : 0] m_axis_output_tdata
  .m_axis_output_tvalid(rs_encode_output_tvalid),                      // output wire m_axis_output_tvalid
  .m_axis_output_tready(rs_enocde_output_tready_reg),                      // input wire m_axis_output_tready
  .m_axis_output_tlast(rs_encode_output_tlast)                       // output wire m_axis_output_tlast
);

// 通过编码模块输出的valid信号和ready信号来记录输出数据的个数
always@(posedge clk)begin
    if(~rst_n)begin
        dataout_num <= 6'b0;
    end
    else begin
        if(rs_encode_output_tvalid==1'b1 && rs_enocde_output_tready_reg==1'b1)begin
            dataout_num <= dataout_num + 6'b1;
            if(dataout_num >= 6'd15)begin
                dataout_num <= 6'b0;
            end
        end
        else begin
            
        end
    end
end

endmodule

首先利用MATLAB仿真看一下[0,1,2,3,4,5,6,7,8]这几个编码后的数据是多少,在MATLAB仿真中用的是矩阵,所以结果得到的也是矩阵,三个数据一组,所以相当于进行了三次编码

在这里插入图片描述

4. 仿真测试

然后添加一个testbench文件然后程序运行起来。rs_tb.v,这个程序比较简单,就是进行初始化,设置时钟和复位信号。

`timescale 1ns / 1ps

module rs_tb();

reg l_clk;
reg rst_n;

rs_encoder rs_test_ins(
    .clk(l_clk),          //时钟
    .rst_n(rst_n)         // 复位  高电平复位
//    input [7:0] data_in,  // 输入的待编码数据
//    output [7:0] dataout      // 输出的解码数据
    );

initial l_clk = 1;
always #5 l_clk= !l_clk;  //15.625   


initial begin
    rst_n <= 0;
    #40;
    rst_n <= 1;
    #320;
    //#50000000;
    #320;
//    $stop;
end
endmodule

然后运行仿真,可以得到.

在这里插入图片描述

首先看第一个蓝色标线,ready信号和valid信号同时为高,此时输入的编码数据有三个,分别为0,1,2,然后经过5个clk延迟,第2个蓝色标线处,编码输出的ready信号和valid信号同时为高,表示编码输出有效,得到的编码结果为0,1,2,1,15,0,12,3,2,12,14,3,15,13,13,然后是第二组编码数据的结果3,4,5MATLAB仿真的结果是能够对应的上的。

这个仿真中的s_tlast信号可以调整一下,每输入三个数据拉高一次,防止出错。

等下一部分进行rs解码的仿真。

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

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

相关文章

Hlang社区-社区导航栏实现

文章目录 前言项目结构导航实现创作中心移动小球消息提示完整代码前言 okey,这里的话是我们社区导航栏的实现: 废话不多说,看看效果: 我甚至为此用New Bing生成了一个Logo。 项目结构 废话不多说,先来看到我们的项目结构: 在这里导航栏是一个组件。 在App.vue里面直…

POST请求负载form-data表单数据需要同步修改header的Content-type

需要读公司的一个接口&#xff0c;显示负载是“表单数据” 一开始没注意类型&#xff0c;按照公司其他接口的情况用了json&#xff0c;结果返回的数据时间阶段没有体现dct的要求&#xff0c;脚本如下&#xff08;错误示范&#xff09; from requests import post from json im…

企业权限管理(十六)-aop日志

SysLog实体类 public class SysLog {private String id;private Date visitTime;private String visitTimeStr;private String username;private String ip;private String url;private Long executionTime;private String method;public String getId() {return id;}public v…

Request+Response

文章目录 1. 介绍2. Request对象2.1 Request继承体系2.2 Request获取请求数据1.获取请求行2.获取请求头3.获取请求体4. 请求参数的通用方式5. 解决中文乱码问题 2.3 Request请求转发请求转发资源间共享数据: 3. Response对象3.0 Response 继承体系3.1 Response设置响应数据的功…

RK3288Android7.1上10寸mipi屏兼容

需求&#xff1a;RK3288Android7.1上10寸mipi屏兼容 思路&#xff1a; 1、修改屏幕厂商提供的屏幕初始化指令为rk可以识别的格式存放在panel-init-sequence 2、修改屏参display-timings 3、确定reset-gpio 实现&#xff1a; 首先根据屏幕厂商提供的初始化指令将panel-init-seq…

AMS的起源,SystemServer的前世今生

作者&#xff1a;OpenGL 前世 SystemServer的创建还得追溯到之前的Zygote进程中的ZygoteInit代码中。这里的Zygote.forkSystemServer()方法就是实现分裂的关键代码。它内部调用了native方法实现了进程分裂。 执行完这行代码之后。我们的系统中就会出现两个一模一样的进程&…

复现基于PYNQ-Z2的手写数字识别卷积加速器设计

来源雪天鱼 基于PYNQ-Z2的手写数字识别卷积加速器设计【持续更新】_雪天鱼的博客-CSDN博客 一、设计思路 1、输入28 x 28 的图片&#xff0c;非png格式&#xff0c;而是txt格式&#xff0c;将图片数据进行量化&#xff0c;存入到txt文件当中。 2、在PL端实现卷积神经网络LeN…

关于Linux Docker springboot jar 日志时间不正确 问题解决

使用Springboot项目的jar&#xff0c;制作了一个Docker镜像&#xff0c;启动该镜像后发现容器和容器中的Springboot 项目的日志时间不正确。 解决 查看容器时间命令为&#xff1a; docker exec 容器id date 1. 容器与宿主机同步时间 在启动镜像时候把操作系统的时间通过&q…

可白嫖的4家免费CDN,并测试其网络加速情况(2023版)

网站加载速度优化过程中&#xff0c;不可避免的会用上CDN来加速资源的请求速度。但是市面上的CDN资源几乎都是要收费的&#xff0c;而且价格还不便宜&#xff0c;对于小公司站长来讲&#xff0c;这将是一笔不小的开销。不过还是有一些良心公司给我们提供了免费的资源&#xff0…

SASS 学习笔记

SASS 学习笔记 总共会写两个练手项目&#xff0c;成品在 https://goldenaarcher.com/scss-study 可以看到&#xff0c;代码在 https://github.com/GoldenaArcher/scss-study。 什么是 SASS SASS 是 CSS 预处理&#xff0c;它提供了变量&#xff08;虽然现在 CSS 也提供了&am…

【C# 基础精讲】异常的类型和处理方法

异常&#xff08;Exception&#xff09;是在程序执行过程中发生的意外或异常情况&#xff0c;例如除零错误、空引用访问、文件不存在等。在C#及其他编程语言中&#xff0c;异常处理是一种重要的机制&#xff0c;用于捕获和处理程序运行时可能出现的错误&#xff0c;以保证程序的…

939. 最小面积矩形;2166. 设计位集;2400. 恰好移动 k 步到达某一位置的方法数目

939. 最小面积矩形 核心思想&#xff1a;枚举矩形的右边那条边的两个点&#xff0c;并用一个哈希表存储相同纵坐标的最近出现的列的列数,不断更新最近出现的左边那条边。 2166. 设计位集 核心思想&#xff1a;这题主要是时间复杂度的优化&#xff0c;用一个flag来标记当前翻转…

word在页眉页脚添加第几页

如果直接在页脚添加数字&#xff0c;整个文档的页脚会是统一的。 这里我们需要的是每一页按照页码排布的文档&#xff0c;所以首先打开页脚设置&#xff1a; 在插入内选择页脚 在弹出的下拉窗口中选择空白即可 在菜单栏会多出“页眉和页脚”的选项卡&#xff0c;选择其中的页…

使用拦截器+Redis实现接口幂等

文章目录 使用拦截器Redis实现接口幂等1.思路分析2.具体实现2.1 创建redis工具类2.2 自定义幂等注解2.2 自定义幂等拦截器2.3 注入拦截器到容器 3.测试 使用拦截器Redis实现接口幂等 1.思路分析 接口幂等有很多种实现方式&#xff0c;拦截器/AOPRedis&#xff0c;拦截器/AOP本…

以对话为场景本质,AIGC 将如何改变游戏规则

8 月 17 日&#xff08;本周四&#xff09;&#xff0c;融云直播课从排查问题到预警风险&#xff0c;社交产品如何更好保障体验、留住用户&#xff1f;欢迎点击报名~ 生成式 AI 公司 MosaicML 以约 13 亿美元的价格被大数据巨头 Databricks 收购&#xff0c;这个发生于 6 月底的…

python获取音乐文件

浏览器打开音乐地址 http://www.htqyy.com/top/hot 点击第一首歌曲&#xff0c;会打开新的网页并且可以获取 改歌曲的id&#xff0c;就是url中的33 在播放页面点击F12&#xff0c;打开开发者调试功能 如下图所示&#xff0c;在script脚本中可以获取歌曲的下载数据 host&#…

【DICOM医学影像1】数据格式存储于显示,基本知识科普指南

DICOM&#xff08;Digital Imaging and Communications in Medicine&#xff09;数据格式&#xff0c;是医学影像存储中的标准格式。无论是X光、CT&#xff0c;还是MRI等等影像&#xff0c;采集的原理不同&#xff0c;但是存储的格式一般都是统一的。本文就对DICOM文件的图像显…

Hands on RL 之 Deep Deterministic Policy Gradient(DDPG)

Hands on RL 之 Deep Deterministic Policy Gradient&#xff08;DDPG&#xff09; 文章目录 Hands on RL 之 Deep Deterministic Policy Gradient&#xff08;DDPG&#xff09;1. 理论部分1.1 回顾 Deterministic Policy Gradient(DPG)1.2 Neural Network Difference1.3 Why i…

大模型PEFT技术原理(三):Adapter Tuning及其变体

随着预训练模型的参数越来越大&#xff0c;尤其是175B参数大小的GPT3发布以来&#xff0c;让很多中小公司和个人研究员对于大模型的全量微调望而却步&#xff0c;近年来研究者们提出了各种各样的参数高效迁移学习方法&#xff08;Parameter-efficient Transfer Learning&#x…

java17新特性+ZGC

ZGC垃圾收集 11引入的追求低延迟的垃圾回收器 1.ZGC的内存布局 1.1 region 和G1一样&#xff0c;也是基于Region的堆内存布局。但是ZGC的Region具有动态性&#xff1a;动态创建、动态销毁、动态数据容量。 1.2 垃圾回收机制 相较于CMS&#xff0c;ZGC只有6个阶段&#xff1…