FPGA:卷积编码及维特比译码仿真

FPGA:卷积编码及维特比译码仿真

本篇记录一下在FPGA中完成卷积编码和维特比译码的过程,通过代码解释编码的过程和译码的过程,便于理解,同时也方便移植到其他工程中。

1. 准备工作

  • 卷积编译码IP核—convolutionIP核和viterbiIP核
  • 卷积编码原理知识—网上有很多关于原理性的解释
  • 卷积编码对照仿真过程—可以对照之前的MATLAB仿真程序便于更好的理解编译码的过程,但是有一点不同,在FPGA仿真代码中利用自然数编码,最后译码回自然数,方便对照正确性。

2. 编码过程

首先添加convolutionIP核,可以看到首先有如下的需要配置的参数。

卷积核设置

按照上图的设置方式为2,1,7形式的卷积编码器,这个没有什么需要注意的,按照常规设置就可以了。

然后添加viterbiIP核,打开之后可以看到如下的设置参数。

卷积核设置

在第一个Viterbi Type栏中可以可以选择Standard,然后约束长度和编码过程的设置一致,回溯深度可以利用公式计算5*(约束长度-1),这个是最小的设置的值,回溯深度至少要大于这个值。

卷积核设置

在第二个配置页中,按照如下的参数进行设置,这个可以参考MATLAB仿真。

卷积核设置

这个页面配置的传入的bit数据,因为编码设置的是2,1,7所以这个设置为2,

3. 仿真过程

整个仿真过程利用0-15的自然数循环,对其进行卷积编码,然后通过viterbi译码还原出原来的自然数。

程序的设置流程思路:

  • 为了方便移植到其他的工程中,同时为了转换数据速率,在自然数信源和卷积编码中间添加了一个fifo
  • 同样的操作,在译码结束之后添加了一个fifo,与前一个fifo对称。
  • 在利用译码的过程中,有一点注意事项:编码之后的2bit数据输入到viterbi译码的IP核中时,需要在第0位和第8位填充,构成两bit。这个技术手册中有说明。

手册

下面给出两个fifo的参数设置,自然数位宽为[0:3],首先是信源和编码之间的fifo。

fifo_en
然后是译码之后的fifo。

fifo_de

4. 完整代码

`timescale 1ns / 1psmodule conv_encoder(input clk,          //时钟input rst_n         // 复位  高电平复位);parameter K = 1;   //  对应MATLAB仿真中的k和n的值,这个在IP核设置中已经有体现
parameter N = 2;   //
parameter L = 7;  // 编码之后的数据长度reg [5:0] datain_num; // 每一组编码的原始数据个数
reg [3:0] datain;
//reg [5:0] dataout_num;  //输出编码数据的个数// 定义viterbi IP核需要用到的信号
wire vit_datain_valid;   // 当vit ip的ready信号有效同时 conv的输出有效的时候,这个信号有效
wire vit_datain_ready;   //
wire vit_dataout_valid;
wire vit_dataout_ready;
wire vit_data_out;  // 译码结果输出// 信源处fifo的相关信号线,该fifo是用来把多位数转为比特流传入到卷积编码中。
wire fifo_encode_empty;
wire fifo_encode_full;
wire fifo_encode_out;
wire fifo_decode_empty;
wire fifo_decode_full;
wire [3:0] fifo_decode_out;wire rd_en; //第一个fifo的读写控制信号
wire wr_en;
reg wren;always@(posedge clk)beginif(~rst_n)beginwren <= 1'b0;endelse beginif(fifo_encode_full==1'b1)beginwren <= 1'b0;endelse beginwren <= 1'b1;endend
end
assign wr_en = wren & (!fifo_encode_full);  // fifo没有满就往fifo中写数据 
wire rd_en2; // 第二个fifo的读写控制信号
wire wr_en2;assign rd_en2 = !fifo_decode_empty;  // 最后一个fifo 非空就可以读数据
assign wr_en2 = (!fifo_decode_full) & vit_dataout_valid;
assign vit_dataout_ready = 1'b1;  // 最后直接进fifo了,这里不做特殊控制了,直接常为1,就可以仅看vit_dataout_valid信号了// 编码信号的控制型号 valid 和 ready
wire conv_datain_ready;
reg conv_datain_valid;
wire [1:0] conv_dataout;
wire conv_dataout_valid;
wire conv_dataout_ready;// 设计输入数据 这里面需要对输入的数据转化弄成位的形式,
// 这个和卷积编码的参数设置有关,2,1,7,接受一个输入bit生成两个bitalways@(posedge clk)beginif(~rst_n)begindatain <= 4'b0;datain_num <= 6'b0;endelse beginif(wr_en == 1'b1)begin // 数据只在wr_en有效的情况下才逐渐累加,这个是为了通过连续的数值检验译码正确性datain <= datain + 4'b1;datain_num <= datain_num + 6'b1;endelse begindatain <= datain;datain_num <= datain_num;endend
end// 在这里添加转换bit 可以用fifo实现,同时能够控制速率 assign rd_en = conv_datain_ready;
fifo_encode u1 (.clk(clk),      // input wire clk.srst(~rst_n),    // input wire srst.din(datain),      // input wire [3 : 0] din.wr_en(wr_en),  // input wire wr_en.rd_en(rd_en),  // input wire rd_en.dout(fifo_encode_out),    // output wire [0 : 0] dout.full(fifo_encode_full),    // output wire full.empty(fifo_encode_empty)
);always@(posedge clk)beginif(~rst_n)beginconv_datain_valid <= 1'b0;endelse beginconv_datain_valid <= rd_en;end
endassign conv_dataout_ready = 1'b1;convolution_0 conv (.aclk(clk),                              // input wire aclk.aresetn(rst_n),                        // input wire aresetn.s_axis_data_tdata(fifo_encode_out),    // input wire [7 : 0] s_axis_data_tdata  注意这个只能接受1bit有效数据.s_axis_data_tvalid(conv_datain_valid),  // input wire s_axis_data_tvalid.s_axis_data_tready(conv_datain_ready),  // output wire s_axis_data_tready.m_axis_data_tdata(conv_dataout),    // output wire [7 : 0] m_axis_data_tdata.m_axis_data_tvalid(conv_dataout_valid),  // output wire m_axis_data_tvalid.m_axis_data_tready(conv_dataout_ready)  // input wire m_axis_data_tready
);assign vit_datain_valid = conv_dataout_valid & conv_dataout_ready;// 编码完成后进行译码过程
viterbi_0 viterbi (.aclk(clk),                                // input wire aclk.aresetn(rst_n),                          // input wire aresetn.s_axis_data_tdata({7'b0,conv_dataout[1],7'b0,conv_dataout[0]}),      // input wire [15 : 0] s_axis_data_tdata 这个经过编码之后的数据需要按照此种方式输入。.s_axis_data_tvalid(vit_datain_valid),    // input wire s_axis_data_tvalid.s_axis_data_tready(vit_datain_ready),    // output wire s_axis_data_tready.m_axis_data_tdata(vit_data_out),      // output wire [7 : 0] m_axis_data_tdata.m_axis_data_tvalid(vit_dataout_valid),    // output wire m_axis_data_tvalid.m_axis_data_tready(vit_dataout_ready)   // input wire m_axis_data_tready
);// 添加一个把数据恢复成自然数的fifo
fifo_decode u2 (.clk(clk),      // input wire clk.srst(~rst_n),    // input wire srst.din(vit_data_out),      // input wire [3 : 0] din.wr_en(wr_en2),  // input wire wr_en.rd_en(rd_en2),  // input wire rd_en.dout(fifo_decode_out),    // output wire [0 : 0] dout.full(fifo_decode_full),    // output wire full.empty(fifo_decode_empty)  // output wire empty
);endmodule

下面为tb文件:

`timescale 1ns / 1psmodule conv_tb();reg l_clk;
reg rst_n;conv_encoder conv_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 beginrst_n <= 0;#40;rst_n <= 1;#320;//#50000000;#320;
//    $stop;
end
endmodule

5. 结果分析

以下为仿真结果图:

结果

最下面的红色线是译码之后经过fifo速率转换之后的结果,可以看到是从0依次递增的自然数,一直到15,然后循环下去。这个有效是和rd_en2这个信号保持一致的,但是看这组红线,译码的结果是两个0,这是因为fifo读数据的时候是有一个clk的时钟延时的,这也是为什么在给出fifo参数设置的时候把latency=1用红线框起来。所以把rd_en2延迟一个系统时钟对照fifo_decode_out看数据就正确了。在使用的时候看接下来数据处理的过程需求,采用合适的操作,这里只做简单的仿真验证。

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

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

相关文章

工作流 Flowable 的使用

一、BPMN 业务流程建模与标注 通过 Status&#xff08;状态&#xff09; 字段维护流程状态&#xff0c;流程负责的审批人可能也是 Hard Code&#xff08;硬编码&#xff09;会出现以下问题&#xff1a; 1.流程健壮性差&#xff0c;但凡出现人员变动&#xff0c;或者组织结构调…

Linux部署项目

本文以人人权限管理系统为例&#xff0c;使用finalshell工具连接服务器。服务器使用的是腾讯云服务器。用自己虚拟机也可以完成项目部署。 后端代码renren-security: 采用SpringBoot2、MyBatis-Plus、Shiro框架&#xff0c;开发的一套权限系统&#xff0c;极低门槛&#xff0c…

【RocketMQ】(五)消息的消费

消费者从Broker拉取到消息之后&#xff0c;会将消息提交到线程池中进行消费&#xff0c;RocketMQ消息消费是批量进行的&#xff0c;如果一批消息的个数小于预先设置的批量消费大小&#xff0c;直接构建消费请求ConsumeRequest将消费请求提交到线程池处理&#xff0c;否则需要分…

OpenMesh 网格平滑

文章目录 一、简介二、相关参数二、实现代码三、实现效果参考资料一、简介 由于物理采样过程固有的局限性,三维扫描仪获得的网格通常是有噪声的。为了消除这种噪声,所谓的平滑算法被开发出来。这类方法有很多,OpenMesh主要为我们提供了两种平滑算法,一种是较为经典的Laplac…

火山引擎 ByteHouse:ClickHouse 如何保证海量数据一致性

背景 ClickHouse是一个开源的OLAP引擎&#xff0c;不仅被全球开发者广泛使用&#xff0c;在字节各个应用场景中也可以看到它的身影。基于高性能、分布式特点&#xff0c;ClickHouse可以满足大规模数据的分析和查询需求&#xff0c;因此字节研发团队以开源ClickHouse为基础&…

【【萌新的FPGA学习之实战流水灯】】

萌新的FPGA学习之实战流水灯 实验任务 本节的实验任务是使用领航者底板上的两个 PL LED 灯顺序点亮并熄灭&#xff0c;循环往复产生流水灯的效 果&#xff0c;流水间隔时间为 0.5s。 1MHz&#xff1d;1000000Hz 10的6次方 1ns&#xff1d;10的-9次方秒 开发板晶振50Mhz 计算得…

NIO简单介绍

一、什么是NIO 1、Java NIO全称java non-blocking IO&#xff0c; 是指JDK提供的新API。从JDK1.4开始&#xff0c;Java提供了一系列改进的输入/输出的新特性&#xff0c;被统称为NIO(即New IO)&#xff0c;是同步非阻塞的 2、NIO有三大核心部分: Channel(通道)&#xff0c; Buf…

Goland设置头注释

package ${GO_PACKAGE_NAME} * Author: 坐公交也用券 * HomePage: https://liumou.site * File: ${NAME}.go * Date: ${DATE} ${TIME} * Des: 文件作用

点分治维护dp+连通块上新型dp思路+乘积方面进行根号dp:0922T4

首先连通块&#xff0c;所以点分治肯定是 Trick1 钦定选根的连通块dp 对于钦定选根的连通块dp&#xff0c;有一种常见思路 先对原树求其dfn序&#xff0c;按dfn序倒序求解 具体的&#xff0c;对于当前点 i i i&#xff08;注意这里都是指dfn序&#xff09;&#xff0c;我们…

企业电子招标采购系统源码之从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

【智慧工地源码】智慧工地助力数字建造、智慧建造、安全建造、绿色建造

智慧工地围绕建设过程管理&#xff0c;建设项目与智能生产、科学管理建设项目信息生态系统集成在一起&#xff0c;该数据在虚拟现实环境中&#xff0c;将物联网收集的工程信息用于数据挖掘和分析&#xff0c;提供过程趋势预测和专家计划&#xff0c;实现工程建设的智能化管理&a…

[Linux]线程概念

[Linux]线程概念 文章目录 [Linux]线程概念什么是线程Linux系统下的线程实现线程是CPU调度的基本单位进程是系统分配资源的基本实体二级页表 线程的优点线程的缺点线程异常线程用途线程资源 什么是线程 线程是进程内部的一个执行分支&#xff0c;执行粒度比进程更细&#xff0…

【Java 基础篇】Java网络编程:下载进度监控实现详解

文件下载是许多应用程序的重要功能&#xff0c;而下载进度监控是提高用户体验的关键。在本文中&#xff0c;我们将详细介绍如何使用Java实现文件下载进度监控&#xff0c;以便用户可以实时了解文件下载的进度。 什么是下载进度监控 下载进度监控是一种用户界面元素或功能&…

113双周赛

题目列表 2855. 使数组成为递增数组的最少右移次数 2856. 删除数对后的最小数组长度 2857. 统计距离为 k 的点对 2858. 可以到达每一个节点的最少边反转次数 一、使数组成为递增数组的最少右移次数 这题可以直接暴力求解&#xff0c;枚举出每种右移后的数组&#xff0c;将…

什么是UWB定位技术?UWB定位的应用场景及功能介绍

说到定位我们并不陌生&#xff0c;定位技术一直与我们的生活密不可分&#xff0c;比如最常见的车辆导航。 根据使用场景&#xff0c;定位技术分为室内定位和室外定位。 室外定位主要依靠GPS&#xff0c;北斗&#xff0c;GLONASS&#xff0c;伽利略等全球卫星定位导航系统。室内…

2023年“羊城杯”网络安全大赛 决赛 AWDP [Break+Fix] Web方向题解wp 全

终于迎来了我的第一百篇文章。 这次决赛赛制是AWDP。BreakFix&#xff0c;其实就是CTFFix&#xff0c;Fix规则有点难崩。Break和Fix题目是一样的。 总结一下&#xff1a;败北&#xff0c;还是太菜了得继续修炼一下。 一、Break ezSSTI 看到是SSTI&#xff0c;焚靖直接一把梭…

AI人体行为分析:玩手机/打电话/摔倒/攀爬/扭打检测及TSINGSEE场景解决方案

一、AI人体行为分析技术概述及场景 人体姿态分析/行为分析/动作识别AI算法&#xff0c;是一种利用人工智能技术对人体行为进行检测、跟踪和分析的方法。通过计算机视觉、深度学习和模式识别等技术&#xff0c;可以实现对人体姿态、动作和行为的自动化识别与分析。 在场景应用…

005-第一代光电小工具(一)

第一代光电小工具(一) 文章目录 第一代光电小工具(一)项目介绍大致原理描述核心控件QCustomPlot关于QCustomPlot 播放音频软件截图 关键字&#xff1a; Qt、 Qml、 QCustomPlot、 曲线、 SQLite 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&…

解决因为修改SELINUX配置文件出错导致Faild to load SELinux poilcy无法进入CentOS7系统的问题

一、问题 最近学习Kubernetes&#xff0c;需要设置永久关闭SELINUX,结果修改错了一个SELINUX配置参数&#xff0c;关机重新启动后导致无法进入CentOS7系统&#xff0c;卡在启动进度条界面。 二、解决 多次重启后&#xff0c;在启动日志中发现 Faild to load SELinux poilcy…

VirtualBox解决VERR_SUPDRV_COMPONENT_NOT_FOUND错误

简述 最近使用VirtualBox时发现其增强功能不能用了&#xff0c;也就是不能双向拖拉文件&#xff0c;整了很久不知所以&#xff1b;看到有网友说跟新其VBoxGuestAdditions.ios文件&#xff0c;所以直接把我的VirtualBox从6.x升级到了7.x&#xff0c;然后就发生了眼前的一幕&…