FPGA Xilinx维特比译码器实现卷积码译码

news2025/1/19 17:23:08

FPGA Xilinx维特比译码器实现卷积码译码

文章目录

  • FPGA Xilinx维特比译码器实现卷积码译码
    • 1 Xilinx维特比译码器实现
    • 2 完整代码
    • 3 仿真结果

MATLAB (n,k,m)卷积码原理及仿真代码(你值得拥有)_matlab仿真后代码-CSDN博客

MATLAB 仿真实现任意(n,k,m)卷积码译码_维特比译码matlab-CSDN博客

前面已经使用MATLAB实现了卷积码和译码,前段时间也在项目中实现了Xilinx中维特比译码器,这次就简单介绍一下这个译码器,从项目中把关于卷积码编译码的部分抽取出来 修改了一下,匆促实现了一下,还行。

1 Xilinx维特比译码器实现

在这里插入图片描述

首先找到Viterbi译码器 随便选一个

在这里插入图片描述

第一页 别管兄弟们 我也很多不懂什么意思,反正第一个就标准 Standard,第二个就回溯长度 ,兄弟们自己设置。

在这里插入图片描述

第二页 的第一个Best State 也不懂,用了之后会多几个看不懂的引脚 第二个Puncturing 好像那个是打孔的意思,我也没用到。第三个Coding是软硬编码的,我选择最简单的硬编码,直接输入0 1 就行了

在这里插入图片描述

第三页就是CC编码时的选项了,我编码使用的是1/2CC 然后对应的表达式分别为7 5,所以这里第一个就是2 代表两个输出码元,然后下面的代表的是表达式7 5

在这里插入图片描述

第四页第一个BER Options也没用到,用到了也会多几个引脚,没敢用

在这里插入图片描述

最后一页就是总结,大家注意上图中 左侧信息 “Implementation Details”

其中第一个DATA_IN_1(8:8) DATA_IN_1(0:0)意思是输入的比特第8位和第0位有效,到时候你只需要把输入的两比特放进这个变量里的第0位和第8位就行了。

DATA(0:0) 就代表每一次输出只有第0位是有效的,也就是一次输入一位 这一位就是第0位

2 完整代码

仿真文件

///
`timescale 1ns/1ps
module testbench_top();
	

//参数定义

`define CLK_PERIORD		10		//时钟周期设置为10ns(100MHz)	


//接口申明

reg 		clk;
reg 		rst_n;
reg         input_bit;
reg         input_valid;


wire [1:0]  output_bits;
wire        output_valid;



reg	enable;


wire out_data;
wire outdata_valid;
wire over;

reg o_data_end;
	
// 对被测试的设计进行例化
    // 实例化待测试的卷积编码模块

CC2 u_CC2(		//二分之一码率	多项式 = 7,5
    .clk		(clk),	
	.rst		(rst_n),
	.enable		(enable),		//使能信号 
	.sink_data	(input_bit),	//输入数据
	.sink_valid	(input_valid),	//数据有效信号
	
	.out_valid	(output_valid),	//输出数据有效信号
	.out_data	(output_bits)	//输出数据
);


CC2_Decoding u_CC2_Decoding(
	.clk			(clk),
	.rst			(rst_n),
	.in_data_valid	(output_valid),	//进来的全是有效数据  直接全部放进译码器中
	.in_data		(output_bits),
	.o_data_end		(o_data_end),
					
	.over			(over),	//结束解码
	.out_data		(out_data),
	.outdata_valid  (outdata_valid)
);



//复位和时钟产生

//时钟和复位初始化、复位产生
initial begin
	clk <= 0;
	rst_n <= 0;
	#1000;
	rst_n <= 1;
end
	
	//时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;	




integer file; // 文件句柄

//测试激励产生
initial begin
    // 打开文件,写入模式
    file = $fopen("D:\\out_data.txt", "w");
    // 确保文件成功打开
    if (file == 0) begin
        $display("Error opening file!");
        $finish;
    end

end

always @(posedge clk) begin
    if (outdata_valid) begin // 仅在数据有效时写入
        $fdisplay(file, "%d", out_data); // 将Ik写入文件
    end
end

initial begin
	 
	
	@(posedge rst_n);	//等待复位完成
	enable <= 1'b0;
	@(posedge clk);
	input_bit <= 1'b0;
	enable <= 1'b1;
	o_data_end <= 1'b0;
	@(posedge clk);
	repeat(8*16) begin		//连续输入8 * 16 *4个bit
	   @(posedge clk);		
		input_bit <= 1'b1;
		input_valid <= 1'b1;	//输入数据有效信号
	   @(posedge clk);	
		input_bit <= 1'b1;
	   @(posedge clk);	
		input_bit <= 1'b0;
	   @(posedge clk);	
		input_bit <= 1'b0;
	end
	input_valid <= 1'b0;	//输入数据有效信号
		
	repeat(3) begin
		@(posedge clk);
	end
	o_data_end <= 1'b1;  
	enable <= 1'b0;
	@(posedge clk);
	o_data_end <= 1'b0;
	#1000000;
	$fclose(file); // 关闭文件
	$stop;
end

endmodule


1/2CC卷积码编码

module CC2 (		//二分之一码率	多项弿 = 7,5
    input 	clk,	
	input 	rst,
	
	input	enable,		//使能信号 
	input 	sink_data,	//输入数据
	input 	sink_valid,	//数据有效信号
	
	output	reg out_valid,	//输出数据有效信号
	output	reg [1:0] 	out_data	//输出数据
);

// sink_data  shift_reg[1]  shift_reg[0]
// out_data[1] out_data[0]  7  5
reg [1:0] shift_reg;	//移位寄存噿

always @(posedge clk) begin
	
	if(!rst) begin
		shift_reg <= 2'b0;	//初始化为0
		out_valid <= 1'b0;	//数据输出无效
		out_data <= 2'b0;
	end else if(enable) begin
		if(sink_valid) begin	//检测到数据有效信号拉高
			out_data[0] <= sink_data + shift_reg[0];
			out_data[1] <= sink_data + shift_reg[1] + shift_reg[0];
			out_valid <= 1'b1;	//拉高数据输出有效信号
			shift_reg <= {sink_data,shift_reg[1]};	//移位
		end else begin
			out_data <= out_data;
			out_valid <= 1'b0;
			shift_reg <= shift_reg;
		end
	end else begin
		shift_reg <= 2'b0;	//将所有寄存器清零
		out_valid <= 1'b0;	//数据输出无效
		out_data <= 2'b0;	
	end
	
end

endmodule

1/2CC卷积码译码

module CC2_Decoding 
(
	input 	clk,
	input	rst,
	input	in_data_valid,	//进来的全是有效数据  直接全部放进译码器中
	input  [ 1:0] 	in_data,
	input 	o_data_end,
	
	output 	reg		over,	//结束解码
	output 			out_data,
	output 	        outdata_valid
);

parameter out_data_hop_amount = 8 * 16 * 4;	//	输出所有的有效比特数

wire [ 7:0] 	decoded_data;

reg [15:0] binary_data;
reg		   data_valid;

reg [ 10:0] out_data_hop_count;	//一跳的输出码元计数器

reg flag;

wire 	s_axis_data_tready;
wire    decoded_valid;

assign out_data = decoded_data[0];

Viterbi2CC_Ip u_Viterbi2CC_Ip(
	.aclk				   	(clk),
	.aresetn			   	(rst),		//低电平就是复位
	.binary_data			(binary_data),  // 输入的硬判决编码数据流(16比特宽度)
	.data_valid		 		(data_valid),          // 输入数据有效信号
							
	.s_axis_data_tready		(s_axis_data_tready),
	.decoded_data	   		(decoded_data),  // 解码后的输出数据
	.decoded_valid       	(decoded_valid)	 // 解码输出有效信号
);


assign  outdata_valid = (out_data_hop_count < out_data_hop_amount) ? decoded_valid : 0;

always @(posedge clk) begin
	if(!rst) begin
		data_valid <= 'b0;
		binary_data <= 'b0;
	end else if(in_data_valid && !flag) begin
		data_valid <= 1'b1;	//调高数据有效信号
		binary_data[8] <= in_data[0];
		binary_data[0] <= in_data[1];
	end else if(flag && s_axis_data_tready && out_data_hop_count <= out_data_hop_amount)begin
		data_valid <= 1'b1;
		binary_data <= 'b0;
	end else begin
		data_valid <= 1'b0;
		binary_data <= binary_data;
	end
end

//对输出的一跳卷积译码码元计数
always @(posedge clk) begin
	if(!rst) begin
		over <= 1'b0;
		out_data_hop_count <= 'b0;
	end else if(decoded_valid && out_data_hop_count <= out_data_hop_amount) begin
		//此时还在接收64个输出的有效比特数据
		over <= 1'b0;
		out_data_hop_count <= out_data_hop_count + 2'd1;
	end else if(out_data_hop_count <= out_data_hop_amount) begin
		over <= 1'b0;
		out_data_hop_count <= out_data_hop_count;
	end else begin
		over <= 1'b1;
		out_data_hop_count <= out_data_hop_count;
	end
end

always @(posedge clk) begin
	if(!rst) begin
		flag <= 'b0;
	end else if(o_data_end) begin	//数据送完了
		flag <= 1'b1;
	end else begin
		flag <= flag;
	end
end

endmodule

维特比译码器

module Viterbi2CC_Ip (
  input 	aclk,
  input 	aresetn,
  input 	[15:0] binary_data,  // 输入的硬判决编码数据流(16比特宽度)
  input 	data_valid,          // 输入数据有效信号
  
  output  	s_axis_data_tready,
  output reg [7:0] decoded_data,  // 解码后的输出数据
  output reg decoded_valid        // 解码输出有效信号
);

reg [15:0] 	s_axis_data_tdata;
reg 		s_axis_data_tvalid;

wire [7:0] 	m_axis_data_tdata;
wire 		m_axis_data_tvalid;
reg 		m_axis_data_tready;

viterbi2CC your_instance_name (
  .aclk(aclk),                              // input wire aclk
  .aresetn(aresetn),                        // input wire aresetn
  .s_axis_data_tdata(s_axis_data_tdata),    // input wire [15 : 0] s_axis_data_tdata
  .s_axis_data_tvalid(s_axis_data_tvalid),  // input wire s_axis_data_tvalid
  .s_axis_data_tready(s_axis_data_tready),  // output wire s_axis_data_tready
  .m_axis_data_tdata(m_axis_data_tdata),    // output wire [7 : 0] m_axis_data_tdata
  .m_axis_data_tvalid(m_axis_data_tvalid),  // output wire m_axis_data_tvalid
  .m_axis_data_tready(m_axis_data_tready)  // input wire m_axis_data_tready
);

always @(posedge aclk) begin
  if (!aresetn) begin
    // 复位信号处理
    s_axis_data_tvalid <= 'b0;
    m_axis_data_tready <= 'b0;
    decoded_valid <= 'b0;
	decoded_data <= 'b0;
  end else begin
    if (data_valid && s_axis_data_tready) begin
      // 输入有效时,将二进制编码数据发送给解码器
      s_axis_data_tdata <= binary_data;  // 输入16比特的编码数据
      s_axis_data_tvalid <= 1'd1;           // 表示输入数据有效
    end else begin
      s_axis_data_tvalid <= 1'd0;
    end

    // 解码器输出处理
    if (m_axis_data_tvalid) begin
      decoded_data <= m_axis_data_tdata;  // 获取解码后的数据
      decoded_valid <= 1'd1;                 // 标记解码输出有效
    end else begin
      decoded_valid <= 1'd0;
    end

    m_axis_data_tready <= 1'd1;  // 准备接收更多解码数据
  end
end

endmodule

3 仿真结果

在这里插入图片描述

这是multisim中的仿真结果,不好看,直接在MATTAB中看解调出来的数据

在这里插入图片描述

最后MATLAB中的数据和仿真输入的数据几乎一模一样,只有后四位不一样,这主要是因为卷积码译码回溯的问题,导致最后几位译码会出现问题。不过问题不大

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

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

相关文章

java+ssm+mysql水产品商城

项目介绍&#xff1a; 使用javassmmysql开发的水产品商城&#xff0c;系统包含管理员、用户角色&#xff0c;功能如下&#xff1a; 管理员&#xff1a;用户管理&#xff1b;种类管理&#xff1b;商品管理&#xff1b;订单管理&#xff1b;评论管理&#xff1b;新闻管理&#…

【传感器技术】第5章 电容式传感器,变极距式电容传感器,变面积式电容传感器,变介质式电容传感器

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…

二叉树前序遍历

什么是前序遍历&#xff1f; 一个二叉树的前序遍历就是对于树中的每一个节点而言&#xff0c;都是先遍历自己&#xff0c;再遍历左右。 如&#xff1a; 递归实现前序遍历 题目链接&#xff1a;144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 实现步骤&…

RAG系统分类、评估方法与未来方向

分享一篇RAG综述&#xff1a;Retrieval-Augmented Generation for Large Language Models: A Survey&#xff0c;主要想了解一下RAG的评估方法&#xff0c;分享给大家。 文章目录 一、RAG分类二、评估方法三、未来方向 一、RAG分类 RAG分类&#xff1a;Navie RAG、Advanced RA…

【软件安全】软件安全设计规范,软件系统安全设计制度(Word原件)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 软件全面文档清单涵盖以下核心内容&a…

约克约克VRF中央空调,清凉舒适从此不再是梦

生活总是少不了空调的陪伴。但是&#xff0c;你是否还在为传统空调的高能耗、低效率而烦恼&#xff1f;别担心&#xff0c;约克VRF中央空调来帮你解决这一切难题&#xff01;      节能省电&#xff0c;我懂你~      现代生活讲究的是高效和环保&#xff0c;而约克VRF中…

DMA简介

DMA是一个数据转运小助手, 它主要是用来协助CPU,完成数据转运的工作 第一个程序: 在这个程序里&#xff0c;我们将使用DMA&#xff0c;进行存储器到存储器的数据转运, 也就是把一个数组里面的数据&#xff0c; 复制到另一个数组里 DMA简介 DMA外设&#xff0c; 是可以直接访…

liunx docker 部署 nacos seata sentinel

部署nacos 1.按要求创建好数据库 2.创建docker 容器 docker run -d --name nacos-server -p 8848:8848 -p 9848:9848 -p 9849:9849 -e MODEstandalone -e SPRING_DATASOURCE_PLATFORMmysql -e MYSQL_SERVICE_HOST172.17.251.166 -e MYSQL_SERVICE_DB_NAMEry-config -e MYSQL…

计算机视觉与各个学科融合:探索新方向

目录 引言计算机视觉与其他学科的结合 与医学的结合与机械工程的结合与土木工程的结合与艺术与人文的结合发文的好处博雅知航的辅导服务 引言 计算机视觉作为人工智能领域的重要分支&#xff0c;正迅速发展并渗透到多个学科。通过与其他领域的结合&#xff0c;计算机视觉不仅…

电阻计RM3544、RM3545的使用

目录&#xff1a; 一、电阻计与PC通讯 1、硬件连接 2、RmLogger.exe的使用 二、RM3545测量35uΩ电阻 一、电阻计与PC通讯 1、硬件连接 可以设置USB或COM口(串口)连接PC&#xff0c;也可以设置为“打印”输出。 1&#xff09;使用USB连接PC 2&#xff09;使用串口连接PC …

【JVM】JVM基础教程(一)

目录 初识JVM JVM是什么&#xff1f; JVM的功能 解释、即时编译和运行 内存管理 常见的JVM JVM虚拟机规范 HotSpot的发展历程 JVM的组成 字节码文件详解 应用场景 以正确姿势打开字节码文件 ​编辑字节码文件的组成 基本信息 Magic魔数 主副版本号 常量池 接口…

Mybaits的优点缺点?

大家好&#xff0c;我是锋哥。今天分享关于【Mybaits的优点&缺点?】面试题。希望对大家有帮助&#xff1b; Mybaits的优点&缺点? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MyBatis 是一个优秀的持久层框架&#xff0c;通常用于 Java 应用程序中&…

gulp应该怎么用,前端批量自动化替换文件

背景 最近公司准备把所有项目中用到的国际化相关的key规范化&#xff0c;原因是: 一直以来公司的app和web端 在针对相同的需求以及相同的国际化语言&#xff0c;需要设置不同的两份国际化文件&#xff0c;难以维护旧版的国际化文件中&#xff0c;存在的大量值重复&#xff0c…

POI遍历行所有单元格的两种方式,getPhysicalNumberOfCells方式有问题,勿用

今天看POI源码的时候&#xff0c;发现HSSFWorkbook类型的工作簿&#xff0c;行数据是用TreeMap<Integer, HSSFRow>存储的&#xff0c;列数据是用HSSFCell[]数组来存的&#xff1b;XSSFWorkbook类型的工作簿&#xff0c;行数据是用SortedMap<Integer, XSSFRow>存储的…

NUMA-非统一内存访问架构

NUMA&#xff08;Non-Uniform Memory Access&#xff09; 是一种计算机内存架构&#xff0c;主要用于多处理器系统。NUMA架构中的每个处理器都连接到自己的本地内存&#xff0c;并且可以访问其他处理器的内存&#xff0c;但访问其他处理器的内存速度较慢。 内核通过调度优化进…

WPF+LibVLC开发播放器-LibVLC在C#中的使用

LibVLC在C#中的使用 安装包Nuget使用控件使用播放器初始化加载视频文件 视频教程&#xff1a; 使用WPFLibVLC快速开发一个播放器 安装包Nuget 安装下面两个包,必须安装两个 一个是相关框架对应的包&#xff0c;Winform就安装LibVLCSharp.Winform;WPF就安装LibVLCSharp.WPF&am…

用GPT零负担学单片机之点亮一颗cpu 第3节 训练or特征匹配?用GPT开发嵌入式

用GPT零负担学单片机之点亮一颗cpu 第3节 训练or特征匹配&#xff1f;AI写代码 大家好,我是小杰学长 如果你是大学生 遇到电子技术 学习 成长 入行难题 我曾经通过大学比赛赚钱 从事嵌入式AI 航天军工 用特别的学习和求职方法线下半年带50学弟学妹入行开发 主页佳喔威信&…

基于Java Springboot在线招聘APP且微信小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 微信…

动力商城-05 阿里云短信服务

1.添加依赖 <dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifactId><version>2.0.24</version></dependency>2.控制层 Api(tags "短信业务接口管理") RequestMapping("p/sms&…

深入解析 HTML Input 元素:构建交互性表单的核心

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…