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 / 1ps

module 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)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;
        if(fifo_full==1'b1)begin
            rs_encode_input_tvalid_reg <= 1'b0;
        end
        else begin
            rs_encode_input_tvalid_reg <= 1'b1;
        end
        
        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

// 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)begin
    if(~rst_n)begin
        fifo_flag <= 1'b0;
    end
    else begin
        if(fifo_rd_en==1'b1)begin
            fifo_flag <= 1'b1;
        end
    end
end

always@(posedge clk)begin
    if(~rst_n)begin
        rs_decode_data_s_valid_reg <= 1'b0;
    end
    else begin
        rs_decode_data_s_valid_reg <= fifo_rd_en;
    end
end

fifo_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)begin
    if(~rst_n)begin
        decode_num = 6'b1;
    end
    else begin
        if(rs_decode_data_s_valid==1'b1)begin
            decode_num <= decode_num + 6'b1;
            if(decode_num >= 6'd14)begin
                decode_num <= 6'b0;
            end
        end
    end
end
// 控制tlast信号
always@(posedge clk)begin
    if(~rst_n)begin
        rs_decode_data_s_tlast_reg <= 1'b0;
    end
    else begin //当解码输入进入的数据为一组时,拉高tlast信号;
        if(decode_num >= 6'd14)begin
            rs_decode_data_s_tlast_reg <= 1'b1;
        end
        else begin
            rs_decode_data_s_tlast_reg <= 1'b0;
        end
    end
end

rs_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 begin
    rst_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.mfbz.cn/a/77080.html

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

相关文章

微信小程序|自定义弹窗组件

目录 引言小程序的流行和重要性自定义弹出组件作为提升用户体验和界面交互的有效方式什么是自定义弹出组件自定义弹出组件的概念弹出层组件在小程序中的作用和优势为什么需要自定义弹出组件现有的标准弹窗组件的局限性自定义弹出组件在解决这些问题上的优势最佳实践和注意事

日常BUG——Java使用Bigdecimal类型报错

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;日常BUG、BUG、问题分析☀️每日 一言 &#xff1a;存在错误说明你在进步&#xff01; 一、问题描述 直接上代码&#xff1a; Test public void test22() throws ParseException {System.out.p…

Linux怎样处理网络请求——彻底理解IO多路复用

常见的网络IO模型 网络 IO 模型分为四种&#xff1a;同步阻塞 IO、同步非阻塞IO、IO 多路复用、异步非阻塞 IO(Async IO, AIO)&#xff0c;其中AIO为异步IO&#xff0c;其他都是同步IO 同步阻塞IO 同步阻塞IO&#xff1a;在线程处理过程中&#xff0c;如果涉及到IO操作&…

这场大学生竞赛中,上百支队伍与合合信息用AI共克难题

目录 0 校企联合共克难题1 北京林业大学&#xff1a;文档格式转换2 浙江中医药大学&#xff1a;个性化题库3 中南林业科技大学&#xff1a;交互场景挖掘4 重庆邮电大学&#xff1a;大模型赋能智能文档5 总结 0 校企联合共克难题 近日&#xff0c;中国大学生服务外包创新创业大…

web前端开发基础入门html5+css3+js学习笔记(一)

目录 1.第一个前端程序2.前端工具的选择与安装3.VSCode开发者工具快捷键4.HTML5简介与基础骨架4.1 HTML5的DOCTYPE声明4.2 HTML5基本骨架4.2.1 html标签4.2.2 head标签4.2.3 body标签4.2.4 title标签4.2.5 meta标签 5.标签之标题5.1 快捷键5.1 标题标签位置摆放 6.标签之段落、…

GDP药品供应管理规范确保冷链运输合规性

药品运输面临许多挑战&#xff0c;包括产品可能因暴露在不利条件下导致降解。药品供应管理规范 (GDP) 运输指南在确保整个运输链的冷链合规性方面发挥着关键作用。 药品的分销与生产和制造生产线一样精细和敏感。自全球物流公司成立以来&#xff0c;配送过程中对受控环境的需求…

AI Chat 设计模式:14. 适配器模式

本文是该系列的第十四篇&#xff0c;采用问答式的方式展开&#xff0c;问题由我提出&#xff0c;答案由 Chat AI 作出&#xff0c;灰色背景的文字则主要是我的一些思考和补充。 问题列表 Q.1 关于适配器模式&#xff0c;如果由浅入深的来考察&#xff0c;你会依次提出什么问题…

【腾讯云 Cloud Studio 实战训练营】Hexo 框架 Butterfly 主题搭建个人博客

什么是Cloud Studio Cloud Studio 是基于浏览器的集成式开发环境&#xff08;IDE&#xff09;&#xff0c;为开发者提供了一个永不间断的云端工作站。用户在使用 Cloud Studio 时无需安装&#xff0c;随时随地打开浏览器就能在线编程。 ​ Hexo 博客成品展示 本人博客如下&…

根据一棵树的两种遍历构造二叉树

题目 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,null,…

sql server安装报错 合成活动模板库(ATL) 失败

错误 “合成活动模板库(ATL) 规则失败“ 解决办法&#xff1a; 进入SQL Server 2008R2安装包目录找到文件&#xff1a;sqlsupport_msi&#xff0c;安装此文件之后&#xff0c;再安装SQL Server&#xff0c;便可解决该问题。C:\SQL Server 2008R2\new\SQL Server 2008R2\2052_CH…

uniapp开发微信小程序使用painter将页面转换为图片并保存到本地相册

引言 我使用到painter的原因是&#xff0c;在uniapp开发微信小程序时&#xff0c;需要将一个页面的内容转换成图片保存到本地相册。 起初在网上找到很多都是在uniapp中使用 html2canvas 将网页转换成图片再jspdf将图片转换为pdf&#xff0c;但是这种方式在小程序环境不支持&am…

【数据结构】二叉树链式结构的实现及其常见操作

目录 1.手搓二叉树 2.二叉树的遍历 2.1前序、中序以及后序遍历 2.2二叉树的层序遍历 3.二叉树的常见操作 3.1求二叉树节点数量 3.2求二叉树叶子节点数量 3.3求二叉树第k层节点个数 3.3求二叉树的深度 3.4二叉树查找值为x的节点 4.二叉树的销毁 1.手搓二叉树 在学习…

[数据集][目标检测]钢材表面缺陷目标检测数据集VOC格式2279张10类别

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;2279 标注数量(xml文件个数)&#xff1a;2279 标注类别数&#xff1a;10 标注类别名称:["yueyawan",&…

ceph数据分布

ceph的存储是无主结构&#xff0c;数据分布依赖client来计算&#xff0c;有两个条主要路径。 1、数据到PG 2、PG 到OSD 有两个假设&#xff1a; 第一&#xff0c;pg的数量稳定&#xff0c;可以认为保持不变&#xff1b; 第二&#xff0c; OSD的数量可以增减&#xff0c;OSD的…

【TI-CCS笔记】工程编译配置 bin文件的编译和生成 各种架构的Post-build配置汇总

【TI-CCS笔记】工程编译配置 bin文件的编译和生成 各种架构的Post-build配置汇总 TI编译器分类 在CCS按照目录下 有个名为${CG_TOOL_ROOT}的目录 其下就是当前工程的编译器 存放目录为&#xff1a; C:\ti\ccs1240\ccs\tools\compiler按类型分为五种&#xff1a; ti-cgt-arm…

Appium Desktop安装

【提示&#xff1a;官方已不再维护&#xff0c;建议命令行方式安装&#xff0c;但可以学习了解一下】 Appium Desktop是一款适用于Mac、Windows和Linux的应用程序&#xff0c;它以漂亮灵活的UI为您提供Appium自动化服务器的强大功能。它基本上是Appium Server的图形界面。您可…

【嵌入式环境下linux内核及驱动学习笔记-(19)LCD驱动框架2-FrameBuffer】

目录 1、 Frmebuffer(帧缓冲&#xff09;操作介绍1.1 显示设备的抽象1.2 内存映像1.3 输出画面数据1.4 用户态下操作屏显1.4.1 用文件I / O 操作屏显1.4.2 mmap() 函数1.4.3 ioctl()函数1.4.5 用命令操作屏1.4.6 测试程序 2、Framebuffer总体框架2.1 框架要点2.2 fbmem.c分析2.…

算法通关村第三关【黄金】| 数组元素出现次数问题

1.数字出现的次数超过数组长度的一半 方法一、使用Map键值对来记录每个元素出现的次数&#xff0c;返回次数大于一半的 class Solution {public int majorityElement(int[] nums) {Map<Integer,Integer> map new HashMap<>();for(int i 0;i<nums.length;i){m…

深度学习入门-3-计算机视觉-图像分类

1.概述 图像分类是根据图像的语义信息对不同类别图像进行区分&#xff0c;是计算机视觉的核心&#xff0c;是物体检测、图像分割、物体跟踪、行为分析、人脸识别等其他高层次视觉任务的基础。图像分类在许多领域都有着广泛的应用&#xff0c;如&#xff1a;安防领域的人脸识别…

开源低代码平台Openblocks

网友 HankMeng 想看低代码工具&#xff0c;正好手上有一个&#xff1b; 什么是 Openblocks &#xff1f; Openblocks 是一个开发人员友好的开源低代码平台&#xff0c;可在几分钟内构建内部应用程序。 传统上&#xff0c;构建内部应用程序需要复杂的前端和后端交互&#xff0c;…
最新文章