当前位置: 首页 > news >正文

FPGA: RS译码仿真过程

FPGA: RS译码仿真过程

在上一篇中记录了在FPGA中利用RS编码IP核完成信道编码的仿真过程,这篇记录利用译码IP核进行RS解码的仿真过程,带有程序和结果。

1. 开始准备

在进行解码的过程时,同时利用上一篇中的MATLAB仿真程序和编码过程,IP核的下载是同样的地址。解码过程中的参数设置正好对应编码的过程。对0-15的自然数通过RS编码得到的数据进行解码,其中m=4,n=15,k=3,ploy=19

2. RS译码IP核

RS译码IP核全名Reed-Solomon Decoder,具体细节可以参照PDF技术文档,首先看IP核参数设置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R32PpUta-1692190030739)(1.png “rs解码IP核设置1”)]

已经通过RS编码IP核完成了编码的仿真过程,并且通过MATLAB对比对结果进行了验证,所以这个第一个页码的参数直接参照如图设置就可以,与编码是一一对应的,没有什么需要特别的说明。
在下面的Variable Check Symbol Options不需要勾选。

在这里插入图片描述

在第二个参数设置界面,都不需要勾选,勾选的话译码输出的结果会带有校验的数据。

在这里插入图片描述

在第三个参数设置界面中,把Reset选项勾选上。

在这里插入图片描述

完成这个IP核的设置。

补充

为了方便利用仿真过程中的译码过程,在之前完成编码过程后添加了一个fifo方便进行数据处理和信号控制,其中的fifoIP核的参数设置为如下。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这个fifo根据需要设置即可,主要是为了编码之后的数据和译码过程使用控制方便。

3. 代码编写

译码过程是在编码基础上添加的,编码过程的参数没有变化,对0-15的数据进行编码,然后再进行译码,在编码和译码过程中间有一个fifo,其中fifo的读控制信号利用empty信号和译码IP的s_ready信号,fifo的写信号编码信号的输出valid信号。详细的逻辑看代码。

代码如下rs_test.v

`timescale 1ns / 1psmodule rs_test(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;  //输出编码数据的个数wire fifo_full; // fifo 满信号// 设计输入数据
reg [3:0] datain;
always@(posedge clk)beginif(~rst_n)begindatain <= 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;endelse beginrs_encode_input_tready_reg <= rs_encode_input_tready;if(fifo_full==1'b1)beginrs_encode_input_tvalid_reg <= 1'b0;endelse beginrs_encode_input_tvalid_reg <= 1'b1;endif(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;endelse beginendend
end// 根据每一组编码的组数来确定数据顺序 控制最后一个tlast信号。
always@(posedge clk)beginif(~rst_n)beginrs_encode_input_tlast_reg <= 1'b0; // 这个信号是需要在一组中的最后一个数据时候信号处于高电平 和k的大小对应endelse beginif(datain_num >= K)beginrs_encode_input_tlast_reg <= 1'b1;endelse beginrs_encode_input_tlast_reg <= 1'b0;  //然后重新置零endend
endwire [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)beginif(~rst_n)begindataout_num <= 6'b0;endelse beginif(rs_encode_output_tvalid==1'b1 && rs_enocde_output_tready_reg==1'b1)begindataout_num <= dataout_num + 6'b1;if(dataout_num >= 6'd15)begindataout_num <= 6'b0;endendelse beginendend
end// rs 译码过程
// 在编码之后的数据添加一个fifo  方便管理valid信号和ready信号,减少耦合同时可以比配位宽
wire fifo_empty;
wire fifo_rd_en;wire[3:0] fifo_data;
reg fifo_flag;  // 这个是用来标致第一次从fifo中读取数据的过程wire [7:0] rs_decode_data_temp;
wire [3:0] rs_decode_data;
//in
wire rs_decode_data_s_ready;
wire rs_decode_data_s_valid;
reg rs_decode_data_s_valid_reg;  // 去掉fifo 输出的一个时钟延迟
reg rs_decode_data_s_tlast_reg;
assign fifo_rd_en = rs_decode_data_s_ready && (!fifo_empty);
// out
wire rs_decode_data_m_valid;
wire rs_decode_data_m_tlast;
wire rs_decode_data_m_ready;
// stat
wire [7:0] rs_decode_stat_data;
//wire rs_decode_stat_ready;
wire rs_decode_stat_valid;always@(posedge clk)beginif(~rst_n)beginfifo_flag <= 1'b0;endelse beginif(fifo_rd_en==1'b1)beginfifo_flag <= 1'b1;endend
endalways@(posedge clk)beginif(~rst_n)beginrs_decode_data_s_valid_reg <= 1'b0;endelse beginrs_decode_data_s_valid_reg <= fifo_rd_en;end
endfifo_generator_0 fifo_ins( // 这个输出有1clk延迟.clk(clk),      // input wire clk.srst(~rst_n),    // input wire srst.din(rs_encode_data[3:0]),      // input wire [3 : 0] din.wr_en(rs_encode_output_tvalid),  // input wire wr_en.rd_en(fifo_rd_en),  // input wire rd_en.dout(fifo_data),    // output wire [3 : 0] dout  .full(fifo_full),    // output wire full.empty(fifo_empty)  // output wire empty
);
// 输入编码中的有效信号
assign rs_decode_data_s_valid = (fifo_flag==1'b1)?fifo_rd_en:rs_decode_data_s_valid_reg; // 在第一次读取的时候 信号跟随reg信号,之后跟随en信号
reg[5:0] decode_num;
always@(posedge clk)beginif(~rst_n)begindecode_num = 6'b1;endelse beginif(rs_decode_data_s_valid==1'b1)begindecode_num <= decode_num + 6'b1;if(decode_num >= 6'd14)begindecode_num <= 6'b0;endendend
end
// 控制tlast信号
always@(posedge clk)beginif(~rst_n)beginrs_decode_data_s_tlast_reg <= 1'b0;endelse begin //当解码输入进入的数据为一组时,拉高tlast信号;if(decode_num >= 6'd14)beginrs_decode_data_s_tlast_reg <= 1'b1;endelse beginrs_decode_data_s_tlast_reg <= 1'b0;endend
endrs_decoder_0 rs_decoder_0_ins (.aclk(clk),                                                      // input wire aclk.aresetn(rst_n),                                                // input wire aresetn.s_axis_input_tdata(fifo_data),                          // input wire [7 : 0] s_axis_input_tdata.s_axis_input_tvalid(rs_decode_data_s_valid),                        // input wire s_axis_input_tvalid.s_axis_input_tlast(rs_decode_data_s_tlast_reg),                          // input wire s_axis_input_tlast.s_axis_input_tready(rs_decode_data_s_ready),                        // output wire s_axis_input_tready.m_axis_output_tdata(rs_decode_data_temp),                        // output wire [7 : 0] m_axis_output_tdata.m_axis_output_tvalid(rs_decode_data_m_valid),                      // output wire m_axis_output_tvalid.m_axis_output_tready(1'b1),                      // input wire m_axis_output_tready.m_axis_output_tlast(rs_decode_data_m_tlast),                        // output wire m_axis_output_tlast.m_axis_stat_tdata(rs_decode_stat_data),                            // output wire [7 : 0] m_axis_stat_tdata.m_axis_stat_tvalid(rs_decode_stat_valid),                          // output wire m_axis_stat_tvalid.m_axis_stat_tready(1'b1)                          // input wire m_axis_stat_tready
);assign rs_decode_data = rs_decode_data_temp[3:0];endmodule

4. 仿真测试

测试程序的testbench文件和之前保持一致,只需要把实例化的模块名字更改即可。

`timescale 1ns / 1ps
module rs_tb();reg l_clk;
reg rst_n;rs_test rs_test_ins(.clk(l_clk),          //时钟.rst_n(rst_n)         // 复位  高电平复位);
initial l_clk = 1;
always #5 l_clk= !l_clk;  //15.625   initial beginrst_n <= 0;#40;rst_n <= 1;#320;//#50000000;#320;
//    $stop;
end
endmodule

然后进入仿真过程,对照时序查看结果。

在这里插入图片描述

首先看试验大图,其中的蓝色线是解码之后的数据,从数据结果中可以看出每个数据间隔3,正好是编码之前的结果,拉开蓝色线就可以看到具体的数值。因为译码也是存在延时的,所以看起来数据会滞后,蓝色数据线的m_valid信号对应输出数据有效信号。

这里面有需要注意的地方,首先看仿真结果的前面部分。

在这里插入图片描述

这是fifo_rd_en有效的第一段,由于有1个clk的时钟延迟,所以把有效信号rs_decode_data_s_valid信号需要延迟一个clk,然后看接下来的fifo_rd_en第二个周期,需要把rs_decode_data_s_valid信号和fifo_rd_en信号对齐,否则会丢一个数据,后面的和第二个周期相同,只有第一个需要延迟一个周期,这个在程序中通过fifo_flag判断是不是第一个周期。

在这里插入图片描述

至此完成了译码的过程。

相关文章:

FPGA: RS译码仿真过程

FPGA: RS译码仿真过程 在上一篇中记录了在FPGA中利用RS编码IP核完成信道编码的仿真过程&#xff0c;这篇记录利用译码IP核进行RS解码的仿真过程&#xff0c;带有程序和结果。 1. 开始准备 在进行解码的过程时&#xff0c;同时利用上一篇中的MATLAB仿真程序和编码过程&#x…...

PostgreSQL 查询数据表、视图信息

--获得指定schema范围内的所有表和视图的列表&#xff0c;可指定一个排除表前缀模式with param as (select public,iit as schema_name,db2g% as exclude_pattern),base_info as (--获得所有基表select pg_namespace.nspname as schema_name, a.relname as tbl_name ,TBL as tb…...

手撕vector容器

一、vector容器的介绍 vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素&#xff0c;但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且它的大小会被容器自动处理。 总结&#xff1a;vector是一个动态…...

PyMuPDF`库实现PDF旋转功能

本文介绍了一个简单的Python应用程序&#xff0c;用于将PDF文件转换为旋转90度的PDF文件。主要用于csdn网站中导出的博客pdf是横向的&#xff0c;看起来不是很方便&#xff0c;才想到用python编制一个将pdf从横向转为纵向的功能。 功能 该PDF转换工具具有以下功能&#xff1a…...

微人事 登录问题完善

重启服务端的时候&#xff0c;发现前端页面会操作不了&#xff0c;这样后端session会失效&#xff0c;我们就需要让页面重新跳转到登录页 springsecurity配置类后端配置 前端拦截器进行拦截跳转...

【业务功能篇64】安装docker容器,在docker上安装mysql

docker教程&#xff1a; https://www.runoob.com/docker/docker-tutorial.html卸载docker 较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序&#xff0c;请卸载它们以及相关的依赖项。 yum remove docker docker-client docker-client-latest docker-co…...

MyBatis的基本概念和核心组件

MyBatis的基本概念 MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息&#xff0c;将接口和 Java 的 POJOs(Pla…...

sql update执行返回0,能否判断数据不存在

答案&#xff1a;不能。 update执行返回0的情况 1、没有找到需要更新的数据&#xff0c;就是这条记录不存在 例如&#xff1a;where后面的条件是id0&#xff0c;那这条记录肯定是不存在的&#xff0c;返回结果是0 2、更新时的数据和要更新的数据完全一致时 例如&#xff1a;更…...

数据分析 | 调用Optuna库实现基于TPE的贝叶斯优化 | 以随机森林回归为例

1. Optuna库的优势 对比bayes_opt和hyperoptOptuna不仅可以衔接到PyTorch等深度学习框架上&#xff0c;还可以与sklearn-optimize结合使用&#xff0c;这也是我最喜欢的地方&#xff0c;Optuna因此特性可以被使用于各种各样的优化场景。 2. 导入必要的库及加载数据 用的是sklea…...

stm32单片机开关输入控制蜂鸣器参考代码(附PROTEUS电路图)

说明&#xff1a;这个buzzer的额定电压需要改为3V&#xff0c;否则不会叫&#xff0c;源代码几乎是完全一样的 //gpio.c文件 /* USER CODE BEGIN Header */ /********************************************************************************* file gpio.c* brief Thi…...

打印X型的图案

int main() {int n0;int i0;int j0;scanf("%d",&n);for(i0;i<n;i){for(j0;j<n;j){if(ij){printf("*");}else if((ij)n-1){printf("*");}elseprintf(" ");}printf("\n");}return 0; }...

不含数字的webshell绕过

异或操作原理 1.首先我们得了解一下异或操作的原理 在php中&#xff0c;异或操作是两个二进制数相同时&#xff0c;异或(相同)为0&#xff0c;不同为1 举个例子 A的ASCII值是65&#xff0c;对应的二进制值是0100 0001 的ASCII值是96&#xff0c;对应的二进制值是 0110 000…...

Mac上传项目源代码到GitHub的修改更新

Mac上传项目源代码到GitHub的修改更新 最近在学习把代码上传到github&#xff0c;不得不说&#xff0c;真的还挺方便 这是一个关于怎样更新项目代码的教程。 首先&#xff0c;在本地终端命令行打开至项目文件下第一步&#xff1a;查看当前的git仓库状态&#xff0c;可以使用git…...

Android6:片段和导航

创建项目Secret Message strings.xml <resources><string name"app_name">Secret Message</string><string name"welcome_text">Welcome to the Secret Message app!Use this app to encrypt a secret message.Click on the Star…...

ClickHouse AST is too big 报错问题处理记录

ClickHouse AST is too big 报错问题处理记录 问题描述问题分析解决方案1、修改系统配置2、修改业务逻辑 问题描述 项目中统计报表的查询出现 AST is too big 问题&#xff0c;报错信息如下&#xff1a; 问题分析 报错信息显示 AST is too big。 AST 表示查询语法树中的最大…...

DPDK系列之二十七DIDO

一、DIDO介绍 随着计算机技术发展&#xff0c;特别是应用技术的快速发展。应用场景对计算机的处理速度几乎已经到了疯狂的地步。说句大白话&#xff0c;再快的CPU也嫌慢。没办法&#xff0c;CPU和IO等技术基本目前都处在了瓶颈之处&#xff0c;大幅度提高&#xff0c;短时间内…...

《游戏编程模式》学习笔记(七)状态模式 State Pattern

状态模式的定义 允许对象在当内部状态改变时改变其行为&#xff0c;就好像此对象改变了自己的类一样。 举个例子 在书的示例里要求你写一个人物控制器&#xff0c;实现跳跃功能 直觉上来说&#xff0c;我们代码会这么写&#xff1a; void Heroine::handleInput(Input input…...

博客系统之功能测试

博客系统共有&#xff1a;用户登录功能、发布博客功能、查看文章详情功能、查看文章列表功能、删除文章功能、退出功能 1.登录功能&#xff1a; 1.1测试对象&#xff1a;用户登录 1.2测试用例 方法&#xff1a;判定表 用例 编号 操作步骤预期结果实际结果截图1 1.用户名正确…...

CJS和 ES6 的语法区别

CommonJS 使用 module.exports 导出模块。ES6 使用 export 导出模块。 示例代码&#xff1a; CommonJS&#xff08;CJS&#xff09;模块的导出&#xff1a; // 导出模块 module.exports {foo: bar,baz: function() {return qux;} }; ES6 模块的导出&#xff1a; // 导出模…...

ArcGIS Pro如何制作不规则形状图例

在默认的情况下&#xff0c;ArcGIS Pro生成的图例是标准的点、直线和矩形的&#xff0c;对于湖泊等要素而言&#xff0c;这样的表示方式不够直观&#xff0c;我们可以将其优化一下&#xff0c;制作不规则的线和面来代替原有图例&#xff0c;这里为大家介绍一下制作方法&#xf…...

微软Win11 Dev预览版Build23526发布

近日&#xff0c;微软Win11 Dev预览版Build23526发布&#xff0c;修复了不少问题。牛比如斯Microsoft&#xff0c;也有这么多bug&#xff0c;所以你写再多bug也不作为奇啊。 主要更新问题 [开始菜单&#xff3d; 修复了在高对比度主题下&#xff0c;打开开始菜单中的“所有应…...

【NEW】视频云存储EasyCVR平台H.265转码配置增加分辨率设置

关于视频分析EasyCVR视频汇聚平台的转码功能&#xff0c;我们在此前的文章中也介绍过不少&#xff0c;感兴趣的用户可以翻阅往期的文章进行了解。 安防视频集中存储EasyCVR视频监控综合管理平台可以根据不同的场景需求&#xff0c;让平台在内网、专网、VPN、广域网、互联网等各…...

【数据结构】如何用队列实现栈?图文详解(LeetCode)

LeetCode链接&#xff1a;225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; 本文默认读者已经掌握栈与队列的基本知识 或者先看我的另一篇博客&#xff1a;【数据结构】栈与队列_字节连结的博客-CSDN博客 做题思路 由于我们使用的是C语言&#xff0c;不能直接使用队…...

Linux 虚拟机Ubuntu22.04版本通过远程连接连接不上,输入ifconfig只能看到127.0.0.1的解决办法

之前给虚拟机配置静态IP之后&#xff0c;可以直接通过主机Vscode远程连接。但是前一段时间把主机的TCP/IPV4静态IP设置了一下之后&#xff0c;再连接虚拟机就连不上了&#xff0c;于是参考解决虚拟机不能上网ifconfig只显示127.0.0.1的问题&#xff0c;又可以连接上了&#xff…...

C语言刷题训练DAY.9

1.线段图案 解题思路&#xff1a; 这里非常简单&#xff0c;我们只需要用一个循环控制打印即可。 解题代码&#xff1a; #include<stdio.h> int main() {int n 0;while ((scanf("%d", &n)) ! EOF){int i 0;for (i 0; i < n; i){printf("*&…...

CTFHub php://input

1.首先看代码&#xff1a; 这里其实就应该想到的是php://伪协议&#xff1a; php://filter、php://input、php://filter用于读取源码 php://input用于执行php代码 2.其次&#xff0c;判断使用php://input伪协议 而执行php://input伪协议条件是allow_url_include是On 可以先利用…...

React Native expo项目修改应用程序名称

https://expo.dev/accounts/xutongbao/projects npm install --global eas-cli && \eas init --id e32cf2c0-da5b-4a65-814a-4958d58f0ca7 eas init --id e32cf2c0-da5b-4a65-814a-4958d58f0ca7 app.config.js: export default {name: 学习,slug: learn-gpt,owner: x…...

unity 之Transform组件(汇总)

文章目录 理论指导结合例子 理论指导 当在Unity中处理3D场景中的游戏对象时&#xff0c;Transform 组件是至关重要的组件之一。它管理了游戏对象的位置、旋转和缩放&#xff0c;并提供了许多方法来操纵和操作这些属性。以下是关于Transform 组件的详细介绍&#xff1a; 位置&a…...

基于Opencv的虚拟拖拽项目

预备知识 勾股定理 跟随移动算法 手势识别图解 项目源代码 """ 演示一个简单的虚拟拖拽 步骤&#xff1a; 1、opencv 读取视频流 2、在视频图像上画一个方块 3、通过mediapipe库获取手指关节坐标 4、判断手指是否在方块上 5、是&#xff0c;方块跟着移动 6、…...

基于单片机DHT11温湿度NRF2401无线通信控制系统

一、系统方案 本设计采用STC89C5单片机作为主控制器&#xff0c;从机采用DHT11传感器采集温湿度、按键设置报警阀值&#xff0c;液晶1602显示&#xff0c;蜂鸣器报警&#xff0c;无线NRF2401模块。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统…...