Quartus 曼彻斯特码 CRC校验

2024-02-24 06:40

本文主要是介绍Quartus 曼彻斯特码 CRC校验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

VHDL 曼彻斯特编解码

曼彻斯特码

曼彻斯特码,即曼彻斯特编码(Manchester Encoding),也叫做相位编码(PE),是一个同步时钟编码技术,被物理层使用来编码一个同步位流的时钟和数据。在曼彻斯特编码中,每一位的中间有一跳变,位中间的跳变既作时钟信号,又作数据信号;从低到高跳变表示“1”,从高到低跳变表示“0”。

说明

最近完成了一个串行通信的项目,采用光纤作为物理层材料,FPGA为控制器。协议方面以4个高电平作为起始位,数据宽度28位数无停止位,通过修改程序使原8个时钟周期判断一位数据变为2位时钟判断一位数据,加快了解码的速度,降低了解码时钟所需频率。

曼彻斯特编码

编码部分较为简单,流程为加同步头、串并转换。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use work.PCK_CRC8_D1.ALL;entity coding isgeneric (dat_wide		: integer := 21;head_wide	: integer := 4);Port ( Clk 			: in  STD_LOGIC;Clk_div_2    : in  STD_LOGIC;Pid_data 		: in  STD_LOGIC_VECTOR (dat_wide-1 downto 0);--输入并行码Pod_manch 	: out STD_LOGIC);
end coding;architecture Behavioral of coding issignal Sbd_manch		:	std_logic := '0';--曼切斯特码内部信号signal Sbd_NRZ			:	std_logic := '0';--串行码元signal Sbd_NRZ_reg	:	std_logic_vector(2 downto 0) := (others => '0');--串行码元(经3个时钟延时)signal Sbd_cnt			:	integer range 0 to head_wide + dat_wide +10 := 0;signal Sbd_data		:	std_logic_vector( dat_wide + 7 downto 0) := ( others => '0' );signal Sbd_crc_1		:	std_logic_vector( 7 downto 0 ) := ( others => '0' );begin
----------------------------------------------------------------------------------
--组合运算
----------------------------------------------------------------------------------	Pod_manch	<=	Sbd_manch;Sbd_data		<= Pid_data & Sbd_crc_1;
----------------------------------------------------------------------------------
--NRZ串行码延时两个时钟进程,通过两个D触发器实现
----------------------------------------------------------------------------------	
Pr_d	:	process(Clk)beginif rising_edge(Clk) thenif Clk_div_2 = '1' thenSbd_NRZ_reg(0) <= Sbd_NRZ;Sbd_NRZ_reg(1) <= Sbd_NRZ_reg(0);Sbd_NRZ_reg(2) <= Sbd_NRZ_reg(1);elsenull;end if;end if;end process;----------------------------------------------------------------------------------
--时钟计数进程,计数值Sbd_cnt用于对并转串和编码进程进行控制
----------------------------------------------------------------------------------		
Pr_count	:	process(Clk)	begin	if rising_edge(Clk) then		if Clk_div_2 = '1' thenif Sbd_cnt < (head_wide + dat_wide +10) then--4+21+8+2=35Sbd_cnt <= Sbd_cnt + 1;elseSbd_cnt <= 0;end if;elsenull;end if;end if;end process;
----------------------------------------------------------------------------------
--并转串进程,通过计数移位的方式实现,并行输入:Pid_data,串行输出:Sbd_NRZ
----------------------------------------------------------------------------------
Pr_1	:	process(CLK)beginif rising_edge(CLK) thenif Clk_div_2 = '1' thencase Sbd_cnt iswhen 0	=>	Sbd_crc_1 <= ( others => '0' );when 1	=>Sbd_crc_1 <= nextCRC8_D1( Sbd_data( 28 ), Sbd_crc_1);when 2 to dat_wide	=>Sbd_NRZ 		<= Sbd_data( (dat_wide + 7) - conv_integer( Sbd_cnt - 2 ) );--并转串Sbd_crc_1 	<= nextCRC8_D1( Sbd_data( (dat_wide + 7) - conv_integer( Sbd_cnt - 1 ) ), Sbd_crc_1);when dat_wide + 1 to dat_wide + 9	=>Sbd_NRZ <= Sbd_data( (dat_wide + 7) - conv_integer( Sbd_cnt - 2 ) );--并转串when others	=>Sbd_NRZ <= '0';end case;elsenull;end if;end if;end process;----------------------------------------------------------------------------------
--曼切斯特编码进程,加入3个时钟的高电平同步头,编码完成输出标志位Poc_flag
----------------------------------------------------------------------------------Pr_2	:	process(Clk)beginif rising_edge(Clk) thencase Sbd_cnt iswhen 0 to 1		=>	Sbd_manch <= '0'; when 2 to head_wide + 1	=>Sbd_manch <= '1';when head_wide + 2 to 34	=>if Sbd_NRZ_reg(2) = '1' thenSbd_manch <= not Clk_div_2;elseSbd_manch <= Clk_div_2;end if;when others		=>Sbd_manch <= '0'; end case;end if;end process;
end Behavioral;

曼彻斯特解码

解码采用状态机实现,分为三个状态:idle(空闲),decod(编码),error(错误)。解码流程如下:1、判断同步头,连续接收到4个高电平即可认为是同步头。2、判断是接收的一位数据是0还是1,详情见下图示意。3、接收到指定长度的数据后串转并输出。
判断数据
判断接收的数据,在 计数器为01的时刻判断,如果此时接收的电平为高电平就判断为1,反之为0。上述通过01时刻就可以判断出数据为0或1,增加10时刻判断是因为01时刻此时的寄存器还没更新数据,从寄存器读到的数据是旧的数据,而10时刻寄存器已更新。


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use work.PCK_CRC8_D1.ALL;entity decoding isgeneric (dat_wide		: integer := 21);Port ( 	CLK								: in  STD_LOGIC;DECODE_EN						: in  STD_LOGIC;MANCHESTER_WITHOUT_HEADER	: in  STD_LOGIC;	--输入的曼切斯特码DECODE_ERROR					: out	STD_LOGIC;DECODE_OUT						: out std_logic_vector( (dat_wide-1) downto 0)	--解码后的串行编码);
end decoding;architecture Behavioral of decoding is
----------------------------------------------------------------------------------signal crc8_data_reg 		:	std_logic_vector( 7 downto 0 ) := (others => '0');signal crc8_data				:	std_logic_vector( 7 downto 0 ) := (others => '0');signal manchester_data		:  std_logic_vector( dat_wide + 8 downto 0) := (others => '0');signal decode_reg1			:	std_logic := '0';signal decode_reg2			:	std_logic := '0';signal decode_coder			:	std_logic := '0';--输出串行码元内部信号signal coder_cnt				:	std_logic_vector( 1 downto 0 ) := (others => '0');--时钟计数--signal coder_fall_cnt		:	std_logic_vector( 1 downto 0 ) := (others => '0');--时钟计数,用于判断码的‘0’‘1’状态signal manchester_cnt		:	std_logic_vector( 4 downto 0 ) := (others => '0');--signal decoder_end			:	std_logic := '0';signal decoder_end_reg		:	std_logic := '0';signal decod_end_reg_cnt1	:	std_logic_vector(10 downto 0) := (others => '0');begin
----------------------------------------------------------------------------------
--组合运算 
----------------------------------------------------------------------------------
--	DECODE_OUT	<= manchester_data(28 downto 8);
--	Pod_crc 		<= crc8_data;
----------------------------------------------------------------------------------
--曼切斯特码解码
----------------------------------------------------------------------------------Pr_rising_cnt_CLK	:	process(CLK)beginif falling_edge(CLK) thenif DECODE_EN = '0' thencoder_cnt <= (others => '0');								elseif coder_cnt < "10" then--3coder_cnt <= coder_cnt + 1; elsecoder_cnt <= "01";end if;end if;end if;end process;----------------------------------------------------------------------------------
--判断电平
----------------------------------------------------------------------------------				Pr_just	:	process(CLK)beginif rising_edge(CLK) thenif DECODE_EN = '0' thendecode_reg1 <= '0';decode_reg2 <= '0';elseif (coder_cnt = "01") thenif MANCHESTER_WITHOUT_HEADER = '0' thendecode_reg1 <= '0';decode_reg2 <= '1';elsedecode_reg1 <= '1';decode_reg2 <= '0';end if;elsenull;end if;end if;end if;end process;Pr_decode	:	process(CLK)beginif rising_edge(CLK) thenif DECODE_EN = '0' thenDECODE_ERROR <= '0';decode_coder <= '0';elseif coder_cnt = "10" thenif decode_reg1 = '0' and decode_reg2 = '1' thendecode_coder <= '0';DECODE_ERROR <= '0';elsif decode_reg1 = '1' and decode_reg2 = '0' thendecode_coder <= '1';DECODE_ERROR <= '0';elseDECODE_ERROR <= '1';end if;elseDECODE_ERROR <= '0';end if;end if;end if;end process;									----------------------------------------------------------------------------------	
--串转并处理和CRC8校验
----------------------------------------------------------------------------------				Pr_tran	:	process(CLK)beginif rising_edge(CLK) thenif DECODE_EN = '0' thenmanchester_cnt <= (others => '0');crc8_data_reg <= (others => '0');decoder_end <= '0';elseif coder_cnt < "10" then--7manchester_cnt <= manchester_cnt;elsemanchester_cnt <= manchester_cnt + 1;manchester_data ( (dat_wide + 8) - conv_integer( manchester_cnt ) ) <= decode_coder;--以串行码开头作为高位if manchester_cnt < dat_wide+1 then--21decoder_end <= '0';crc8_data_reg <= nextCRC8_D1( decode_coder, crc8_data_reg);elsif manchester_cnt < (dat_wide + 8) then--29decoder_end <= '0';elsedecoder_end <= '1';
--						DECODE_OUT	<= manchester_data(28 downto 8);crc8_data <= crc8_data_reg;end if;end if;end if;end if;end process;
----------------------------------------------------------------------------------
--输出标志位
----------------------------------------------------------------------------------Pr_d	:	process(CLK)beginif rising_edge(CLK) thendecod_end_reg_cnt1(0) 				<= decoder_end;decod_end_reg_cnt1(10 downto 1) 	<= decod_end_reg_cnt1(9 downto 0);decoder_end_reg 						<= decod_end_reg_cnt1(10);end if;end process;Pr_mark	:	process(CLK)beginif rising_edge(CLK) thenif ( crc8_data = manchester_data(7 downto 0) )and ( decoder_end_reg = '1' ) thenDECODE_OUT	<= manchester_data((dat_wide + 7) downto 8);elsenull;end if;end if;end process;
end Behavioral; 

这篇关于Quartus 曼彻斯特码 CRC校验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/741259

相关文章

SpringBoot3.4配置校验新特性的用法详解

《SpringBoot3.4配置校验新特性的用法详解》SpringBoot3.4对配置校验支持进行了全面升级,这篇文章为大家详细介绍了一下它们的具体使用,文中的示例代码讲解详细,感兴趣的小伙伴可以参考... 目录基本用法示例定义配置类配置 application.yml注入使用嵌套对象与集合元素深度校验开发

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

SpringValidation数据校验之约束注解与分组校验方式

《SpringValidation数据校验之约束注解与分组校验方式》本文将深入探讨SpringValidation的核心功能,帮助开发者掌握约束注解的使用技巧和分组校验的高级应用,从而构建更加健壮和可... 目录引言一、Spring Validation基础架构1.1 jsR-380标准与Spring整合1

SpringBoot利用@Validated注解优雅实现参数校验

《SpringBoot利用@Validated注解优雅实现参数校验》在开发Web应用时,用户输入的合法性校验是保障系统稳定性的基础,​SpringBoot的@Validated注解提供了一种更优雅的解... 目录​一、为什么需要参数校验二、Validated 的核心用法​1. 基础校验2. php分组校验3

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java中使用注解校验手机号格式的详细指南

《Java中使用注解校验手机号格式的详细指南》在现代的Web应用开发中,数据校验是一个非常重要的环节,本文将详细介绍如何在Java中使用注解对手机号格式进行校验,感兴趣的小伙伴可以了解下... 目录1. 引言2. 数据校验的重要性3. Java中的数据校验框架4. 使用注解校验手机号格式4.1 @NotBl

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

spring 参数校验Validation示例详解

《spring参数校验Validation示例详解》Spring提供了Validation工具类来实现对客户端传来的请求参数的有效校验,本文给大家介绍spring参数校验Validation示例详... 目录前言一、Validation常见的校验注解二、Validation的简单应用三、分组校验四、自定义校

校验码:奇偶校验,CRC循环冗余校验,海明校验码

文章目录 奇偶校验码CRC循环冗余校验码海明校验码 奇偶校验码 码距:任何一种编码都由许多码字构成,任意两个码字之间最少变化的二进制位数就称为数据检验码的码距。 奇偶校验码的编码方法是:由若干位有效信息(如一个字节),再加上一个二进制位(校验位)组成校验码。 奇校验:整个校验码中1的个数为奇数 偶校验:整个校验码中1的个数为偶数 奇偶校验,可检测1位(奇数位)的错误,不可纠错。

web登录校验

基础登录功能 LoginController @PostMapping("/login")Result login(@RequestBody Emp emp) {log.info("前端,发送了一个登录请求");Emp e = empService.login(emp);return e!=null?Result.success():Result.error("用户" +"名或密码错误");