FPGA: RS译码仿真过程

news/2024/5/9 18:35:47/文章来源:https://blog.csdn.net/qudunan6468/article/details/132327494

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判断是不是第一个周期。

在这里插入图片描述

至此完成了译码的过程。

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

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

相关文章

安卓纯代码布局开发游戏二:Android Studio开发环境搭建

1.Android Studio下载&#xff1a; Download Android Studio & App Tools - Android Developers 2.安装 安装过程非常简单&#xff0c;找到下载包&#xff0c;一直点Next即可。 3.下载Android SDK 第一次进入Android Studio默认会先下载Android SDK,笔者下载的Android SDK存…

后端返回图片资源错误404,前端使用默认图片

后端返回的图片资源可能会因为各种原因&#xff08;后台误删&#xff0c;地址更改未及时更新&#xff0c;损毁&#xff09;出现无法展示的情况&#xff0c;比如这种报错 就会导致图片资源错误&#xff0c;页面出现这种情况 用户体验很不好&#xff0c;为了改善这种情况&#xf…

服务器数据恢复-HP EVA存储常见故障的数据恢复流程

EVA存储原理&#xff1a; EVA系列存储是以虚拟化存储为实现目的的中高端存储设备&#xff0c;内部的结构组成完全不同于其他的存储设备&#xff0c;RAID在EVA内部称之为VRAID。 EVA会在每个物理磁盘&#xff08;PV&#xff09;的0扇区写入签名&#xff0c;签名后PV会被分配到不…

Spring Boot 知识集锦之actuator监控端点详解

文章目录 0.前言1.参考文档2.基础介绍默认支持的端点 3.步骤3.1. 引入依赖3.2. 配置文件3.3. 核心源码 4.示例项目5.总结 0.前言 背景&#xff1a; 一直零散的使用着Spring Boot 的各种组件和特性&#xff0c;从未系统性的学习和总结&#xff0c;本次借着这个机会搞一波。共同学…

javaScript:数组方法(增删/提取类/截取/操作方法等)

目录 一.数组的增删方法 1.push()数组末尾添加元素 解释 代码 运行截图 2.unshift()向数组的头部添加数组 解释 代码 运行截图 3.pop()数组的尾部删除一个元素 解释 代码 运行截图 4.shift()数组的头部删除一个元素 解释 代码 运行截图 5. splice()任意位…

Android-网络访问技术Retrofit浅析

Retrofit是一种基于注解的网络请求库&#xff0c;专门用于在Android应用中进行网络访问。它使用简洁的方式定义了网络请求的接口&#xff0c;并自动将请求结果解析为Java对象。Retrofit的核心原理是利用了Java的动态代理技术&#xff0c;将网络请求接口的注解信息转化为具体的网…

如何配置Apple推送证书 push证书

如何配置Apple推送证书 push证书 转载&#xff1a;如何配置Apple推送证书 push证书 想要制作push证书&#xff0c;就需要使用快捷工具appuploader工具制 作证书&#xff0c;然后使用Apple的推送功能配置push证书&#xff0c;就可以得到了。PS&#xff1a;push没有描述文件&a…

如何借助数字化为企业管理赋能?

数字化可以利用技术简化流程、增强决策并提高整体效率&#xff0c;从而显着增强企业管理能力。以下是有关如何使用数字化赋能企业管理的分步指南&#xff1a; 1.评估当前流程和需求&#xff1a; 了解您当前的业务流程、痛点以及可以从数字化中受益的领域。确定您想要解决的具体…

Android Studio Giraffe控制台乱码

这几天在使用Android Studio Giraffe进行一个App的开发&#xff0c;在项目构建的时候&#xff0c;控制台输出中文都是乱码&#xff0c;看着很不爽&#xff0c;进行了两项配置&#xff0c;中文就可以正常输出了&#xff0c;看起来就爽多了。 第一个配置&#xff1a;点击Help菜单…

Datawhale Django入门组队学习Task02

Task02 首先启动虚拟环境&#xff08;复习一下之前的&#xff09; 先退出conda的&#xff0c; conda deactivate然后cd到我的venv下面 &#xff0c;然后cd 到 scripts&#xff0c;再 activate &#xff08;powershell里面&#xff09; 创建admin管理员 首先cd到项目路径下&a…

用于弥散加权MRI的关节各向异性维纳滤光片研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

无涯教程-Perl - symlink函数

描述 此函数在OLDFILE和NEWFILE之间创建符号链接。在不支持符号链接的系统上,会导致致命错误。 语法 以下是此函数的简单语法- symlink ( OLDFILE, NEWFILE )返回值 如果失败,此函数返回0,如果成功,则返回1。 例 以下是显示其基本用法的示例代码,首先在/tmp目录中创建一…

亿赛通电子文档安全管理系统任意文件上传漏洞复现

0x01 产品简介 亿赛通电子文档安全管理系统&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资产&…

系统架构设计师-信息安全技术(1)

目录 一、信息安全基础 1、信息安全五要素 2、网络安全漏洞 3、网络安全威胁 4、安全措施的目标 二、信息加解密技术 1、对称加密 2、非对称加密 3、加密算法对比 三、密钥管理技术 1、数字证书 2、PKI公钥体系 四、访问控制技术 1、访问控制基本模型 2、访问控制的实现技术…

近 2000 台 Citrix NetScaler 服务器遭到破坏

Bleeping Computer 网站披露在某次大规模网络攻击活动中&#xff0c;一名攻击者利用被追踪为 CVE-2023-3519 的高危远程代码执行漏洞&#xff0c;入侵了近 2000 台 Citrix NetScaler 服务器。 研究人员表示在管理员安装漏洞补丁之前已经有 1200 多台服务器被设置了后门&#x…

flutter 常见的状态管理器

flutter 常见的状态管理器 前言一、Provider二、Bloc三、Redux四、GetX总结 前言 当我们构建复杂的移动应用时&#xff0c;有效的状态管理是至关重要的&#xff0c;因为应用的不同部分可能需要共享数据、相应用户交互并保持一致的状态。Flutter 中有多种状态管理解决方案&#…

Web和云开发,Rust会起飞?

Web和云开发&#xff0c;Rust会起飞&#xff1f; 一、前言 二、大厂偏爱&#xff0c;Rust的未来 三、Rust做Web的雄心 四、有必要换Rust做Web&#xff1f; 1.效率和性能 2.可靠性和可维护性 五、Rust先苦后甜 六、用Rust前的几个问题 七、开发界的强者 一、前言 去年…

Leetcode-每日一题【剑指 Offer 32 - II. 从上到下打印二叉树 II】

题目 从上到下按层打印二叉树&#xff0c;同一层的节点按从左到右的顺序打印&#xff0c;每一层打印到一行。 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回其层次遍历结果&#xff1a; [ [3], [9,20], [15,7] ] 提示&#xff…

《安富莱嵌入式周报》第320期:键盘敲击声解码, 军工级boot设计,开源CNC运动控制器,C语言设计笔记,开源GPS车辆跟踪器,一键生成RTOS任务链表

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; https://www.bilibili.com/video/BV1Cr4y1d7Mp/ 《安富莱嵌入式周报》第320期&#xff1a;键盘敲击…

炫酷UI前端效果的CSS生成工具

提升设计人员和前端开发人员的工作 推荐炫酷UI前端效果的CSS生成工具1.Neumorphism2.带有渐变的图标3.Interactions4.大型数据库5.动画6.Mask7.动画按钮8. 自定义形状分隔线9.背景图案10. SVG波浪推荐炫酷UI前端效果的CSS生成工具 1.Neumorphism 地址:https://neumorphism.i…