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

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

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

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

相关文章

识别医疗设备制造中的变异性的三个步骤

质量控制是医疗设备制造的关键支柱。毕竟&#xff0c;如果产品不符合最高的安全和功能标准&#xff0c;人们可能会被误诊、受伤甚至死亡。每个设备都必须符合精确的规格和法规&#xff0c;即使是微小的偏差也可能产生重大影响。 我们将以优化磁共振成像&#xff08;MRI&#xf…

数据结构---链表(2)---双向链表

链表(1)中讲过了在OJ题中出现很多并且能作为一些复杂数据结构子结构的不带头单向不循环链表&#xff0c;下面讲解应用很广很实用的带头双向循环链表。 三、双向链表---DoublyLinkedList 演示带头双向循环链表(实用)。 带头--->不需要对空链表继续单独判断&#xff1b;循环…

JAVA |日常开发中读写TXT文本详解

JAVA &#xff5c;日常开发中读写TXT文本详解 前言一、读取 TXT 文本1.1 使用BufferedReader读取1.2 使用Scanner读取 二、写入 TXT 文本2.1 使用BufferedWriter写入2.2 使用PrintWriter写入2.3 字节流写入&#xff08;FileOutputStream&#xff09;后转换为字符流&#xff08;…

clion解决默认编译器乱码问题

解决乱码问题 如图所示当我们在clion下开发时如果输入中文&#xff0c;会有乱码出现。 问题的产生 clion默认的C/C编译器&#xff08;MinGW&#xff09;对中文的解析有问题出现乱码。 解决方案 修改文件的编码方式 进入clion的Settings(设置)–>Editor(编辑) —>Fil…

pset2 substitution.c

1.extension&#xff1a;To Do Tasks 推荐一个vscode里面一个很好用的插件&#xff01;&#xff01;&#xff01;写出解决的步骤&#xff0c;不但理清楚思路。还可以提高效率&#xff01;特别是针对一些文本比较长的pset&#xff0c;要求多且零碎&#xff0c;反复切换页面&…

程序员需要具备哪些知识?

程序员需要掌握的知识广泛而深厚&#xff0c;这主要取决于具体从事的领域和技术方向。不过&#xff0c;有些核心知识是共通的&#xff0c;就像建房子的地基一样&#xff0c;下面来讲讲这些关键领域&#xff1a; 1. 编程语言&#xff1a; 无论你是搞前端、后端、移动开发还是嵌…

解密时序数据库的未来:TDengine Open Day技术沙龙精彩回顾

在数字化时代&#xff0c;开源已成为推动技术创新和知识共享的核心力量&#xff0c;尤其在数据领域&#xff0c;开源技术的涌现不仅促进了行业的快速发展&#xff0c;也让更多的开发者和技术爱好者得以参与其中。随着物联网、工业互联网等技术的广泛应用&#xff0c;时序数据库…

云计算vsphere 服务器上添加主机配置

这里是esxi 主机 先把主机打开 然后 先开启dns 再开启 vcenter 把每台设备桌面再vmware workstation 上显示 同上也是一样 &#xff0c;因为在esxi 主机的界面可能有些东西不好操作 我们选择主机和集群 左边显示172.16.100.200

Kotlin报错:lateinit property xxx has not been initialized

Kotlin报错&#xff1a;lateinit property xxx has not been initialized 发生在定义了一个名为xxx的lateinit变量。 解决&#xff0c;在调用前&#xff0c;可以先判断一层该xxx变量是否已经初始化&#xff1a; if (this::xxx.isInitialized) {//正常使用该变量} kotlin.Unini…

【ArcGIS微课1000例】0134:ArcGIS Earth实现二维建筑物的三维完美显示

文章目录 一、加载数据二、三维显示三、三维符号化一、加载数据 加载配套实验数据(0134.rar中的建筑物,2d或3d都可以),方法如下:点击添加按钮。 点击【Add Files】,在弹出的Open对话框中,选择建筑物,点击确定,完成添加。 默认二维显示: 二、三维显示 右键建筑物图层…

【Linux系统编程】——理解冯诺依曼体系结构

文章目录 冯诺依曼体系结构硬件当代计算机是性价比的产物冯诺依曼的存储冯诺依曼的数据流动步骤冯诺依曼结构总结 冯诺依曼体系结构硬件 下面是整个冯诺依曼体系结构 冯诺依曼结构&#xff08;Von Neumann Architecture&#xff09;是现代计算机的基本结构之一&#xff0c;由数…

H3C OSPF实验

实验拓扑 实验需求 按照图示配置 IP 地址按照图示分区域配置 OSPF &#xff0c;实现全网互通为了路由结构稳定&#xff0c;要求路由器使用环回口作为 Router-id&#xff0c;ABR 的环回口宣告进骨干区域 实验解法 一、配置IP地址 [R1]int l0 [R1-LoopBack0]ip add 1.1.1.1 32 […

【工具变量】上市公司企业所在地城市等级直辖市、副省级城市、省会城市 计划单列市(2005-2022年)

一、包含指标&#xff1a; 股票代码 股票代码 股票简称 年份 所属城市 直辖市&#xff1a;企业所在地是否属于直辖市。1是&#xff0c;0否。 副省级城市&#xff1a;企业所在地是否属于副省级城市。1是&#xff0c;0否。 省会城市&a…

Android Studio历史版本下载

Android Studio 下载文件归档 | Android Developers 一定要选择英文环境&#xff0c; 拉到最后&#xff0c;同意

纯粹直播 1.7.7 |手机版和TV版,聚合六大直播平台,原画播放

纯粹直播是一款开源的应用程序&#xff0c;支持兴趣化主题的游戏直播、户外直播和才艺直播节目。目前可以观看斗鱼、B站、虎牙和抖音等六大直播平台的内容。该应用适配了安卓手机和电视盒子平台使用&#xff0c;并且软件无广告&#xff0c;提供原画质播放体验。 大小&#xff…

【Docker】针对开发环境、测试环境、生产环境如何编排?

目录 一、引言 二、Docker Compose 文件基础 三、针对不同环境的 Docker 编排 开发环境 测试环境 生产环境 四、配置文件全局变量的编写 五、总结 一、引言 在软件开发和部署的过程中&#xff0c;不同的环境有着不同的需求和配置。Docker 作为一种强大的容器化技术&…

rabbitmq 安装延时队列插件rabbitmq_delayer_message_exchange(linux centOS 7)

1.插件版本 插件地址&#xff1a;Community Plugins | RabbitMQ rabbitmq插件需要对应的版本&#xff0c;根据插件地址找到插件 rabbitmq_delayer_message_exchange 点击Releases 因为我rabbitmq客户端显示的版本是&#xff1a; 所以我选择插件版本是&#xff1a; 下载 .ez文…

同道猎聘Q3营收降利润增,AI或成估值重塑关键词

2024年&#xff0c;经济向好的趋势没有改变&#xff0c;挑战却仍然存在。企业纷纷进行结构性变革优化或业务方向调整。这一点反映到人才市场&#xff0c;绝大多数企业对招聘扩张持保守态度&#xff0c;降本增效的主题仍在延续。 作为人才市场水温变化的“温度计”&#xff0c;…

UPLOAD LABS | PASS 10 - 黑名单绕过(Windows . 绕过 - 变体)

关注这个靶场的其它相关笔记&#xff1a;UPLOAD LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;过关流程 本关的目标是上传一个 WebShell 到目标服务器上&#xff0c;并成功访问&#xff1a; 通过查看源码&#xff0c;可以发现&#xff0c;本关在之前所有关卡的基础上做了…

【iOS】多线程基础

【iOS】多线程基础 文章目录 【iOS】多线程基础前言进程与线程进程进程的状态进程的一个控制结构进程的上下文切换 线程为什么要用线程什么是线程线程和进程的关系线程的上下文切换 线程和进程的优缺点 小结 前言 笔者由于对于GCD不是很了解&#xff0c;导致了项目中网络请求哪…