汉明码的编解码在fpga上的实现Word格式.docx
《汉明码的编解码在fpga上的实现Word格式.docx》由会员分享,可在线阅读,更多相关《汉明码的编解码在fpga上的实现Word格式.docx(32页珍藏版)》请在冰豆网上搜索。
1.创建工程
选择filenewproject,出现如图1-1所示的对话框。
输入projectname和希望的路径;
输入libraryname,缺省是work。
图1-1
2.添加Verilog代码
这一步的目的是将verilog文件添加到创建好的工程中。
要添加的文件可以是先前已经创建好的,也可以现在输入。
3.编译工程
编译所有功能模块和测试模块,选择Compile中的CompileAll,如下图所示
图1-2
4.仿真。
首先是调用设计,选择Simulate>
Simulate,出现图1-2的对话框,选择该工程的testbench文件,单击右键,选择将所有信号(或你希望观察的信号)添加到wave窗口中。
第二章Verilog的基础知识
2.1verilog的主要功能
作为一种硬件描述语言,VerilogHDL可以直接描述硬件结构,也可以通过描述系统行为实现建模。
VerilogHDL的主要特点和功能有:
(1)描述基本逻辑门,如and、or和nand等基本逻辑门都内置在语言中,可以直接调用。
(2)描述基本开关模型,如nmos、pmos和coms等基本开关都可以直接调用。
(3)允许用户定义基元(UDP),这种方式灵活有效,用户定义的基元既可以是组合逻辑也可以是时序逻辑。
(4)VerilogHDL中两种数据类型,线网数据类型和寄存器数据类型。
线网类型表示构件间的物理连线,而寄存器类型表示抽象的数据存储元件。
(5)能够描述层次设计,可使用模块实例结构描述任何层次。
(6)设计的规模可以是任意的,语言不对设计的规模(大小)施加任何限制。
(7)VerilogHDL语言的描述能力可以通过使用编程接口(PLI)进一步扩展。
PLI是允许外部函数访问VerilogHDL模块内信息,允许设计者与模拟器交互的例程集合。
(8)设计能够在多个层次上加以描述,从开关级、门级、寄存器传送级(RTL)到算法级,报括进程和队列级。
(9)能够使用内置开关级原语在开关级对设计完整建模。
(10)同一语言可用于生成模拟激励和指定测试的验证约束条件。
(11)VerilogHDL不仅能够在RTL上进行设计描述,而且能够在体系结构级和算法级行为上进行设计描述。
(12)能够使用门和模块实例化语句在结构级进行结构描述。
(13)VerilogHDL具有混合方式建模能力,即设计中每个模块均可以在不同设计层次上建模。
、
(14)VerilogHDL具有内置逻辑函数,例如&
(按位与)和|(按位或)。
2.2verilog基本语法
2.2.1wire型和reg型
(1)wire型
wire型数据常用来表示以assign关键字指定的组合逻辑信号。
Verilog程序模块中输入、输出信号类型默认时自定义为wire型。
wire型信号可以用做方程式的输入,也可以用做“assign”语句或实例元件的输出。
wire型信号的定义格式如下:
wire[n-1:
0]数据名1,数据名2,….,数据名N;
(2)reg型
reg是寄存器数据类型的关键字。
寄存器是数据储存单元的抽象。
通过赋值语句可以改变寄存器的值,其作用相当于改变触发器存储器的值。
reg型数据常用来表示always模块内的指定信号,常代表触发器。
reg型信号的定义格式如下:
reg[n-1:
0]数据名1,数据名2,---,数据名N;
reg数据类型的缺省值是未知的。
reg型数据可以为正值或负值,但当一个reg型数据时一个表达式中的操作数,它的值被当做无符号值,即正值。
reg型和wire型的区别在于:
reg型保持最后一次的赋值,而wire型则需要持续地驱动。
2.2.2initial模块和always模块
(1)initial模块
在进行仿真时,一个initial模块从模拟0时刻开始执行,且在仿真的过程中指执行一次,在执行完一次后,该initial就被挂起,不在执行。
Initial模块的格式为:
Initial
Begin/fork
块内变量说明
时序控制1行为语句1;
时序控制n行为语句n;
End/join
(2)always模块
always模块是一直重复执行的且可综合,always过程块由always过程语句和语句块组成,其格式为:
always@(敏感事件列表)
begin/fork
块内变量说明
时序控制1行为语句1;
----------
时序控制n行为语句;
end/join
2.2.3边沿和电平触发事件
事件控制分为两种:
边沿触发事件和电平触发控制事件。
边沿触发事件是指指定信号的边沿信号跳变时发生指定的行为,分为信号的上升沿和下降沿。
上升沿用posedge关键字描述,下降沿用negedge关键字描述。
电平触发事件是指指定信号的电平发生变化时发生指定的行为。
2.2.4条件语句
(1)if_else
If语句是用来判断所给定的条件是否满足,根据判定的结果(真或假)决定给出的两种操作之一。
If语句的语法如下:
If(state_1)
procedural_condition_1
{elseif(state_2)
procedural_condition_2}
{else
procedural_condition_3}
如果对state_1求值的结果为某个非零值,那么procedural_condition_1被执行,如果state_1的值为0、x、或z,那么procedural_condition_1不执行。
如果存在一个else分支,那么这个分支被执行。
在if_else语句的使用过程经常出现if语句的嵌套,因此应注意if和else的匹配问题。
(2)case语句
case语句的语法形式:
case(case_expr)
case_item_expr{case_item_expr}:
statement
…
[default:
statement]
endcase
case括号内的表达式称为控制表达式,case_item_expr括号内的表达式为分支表达式。
控制表达式通常表示为控制信号的某些位,分支表达式则用这些控制信号的具体状态值表示,因此,分支表达式又可以称为常量表达式。
case语句首先将控制表达式case_expr的值计算出来,然后依次与各个分支语句case_item_expr的值进行比较。
若匹配则执行该分支的语句,如果所有的分支表达式的值都没有与表达式的值相匹配,就执行default后面的语句。
default项可有可无,一个case语句中只能有一个default项。
2.2.5阻塞和非阻塞赋值
在硬件中,过程赋值语句表示用赋值语句右端表达式所推导的逻辑来驱动该赋值语句左边表达式的变量。
过程赋值语句只能出现在always语句和initial语句。
有两种过程赋值语句:
(1)阻塞赋值(blockingassignments)
阻塞赋值用符号“=”来完成,“阻塞赋值”由其赋值操作行为而得名“阻塞”即时说在当前的赋值完成前阻塞其他类型的赋值任务,但是如果右端表达式中含有延时语句,则在延时没结束前不会阻塞其他赋值任务。
(2)非阻塞赋值(nonblockingassignments)
非阻塞赋值有“<
=”来完成,“非阻塞赋值”也有其赋值操作行为而得名:
在一个时间步(timestep)的开始估计右端表达式的值,并在这个时间结束时用等式右边的值更新取代左端表达式。
在估算右端表达式和更新左端表达式的中间时间段,其他的对左端表达式的非阻塞赋值可以被执行,即“非阻塞赋值”从估计右端开始并不阻碍其他的赋值任务。
通过实践表明,遵循以下的编码风格可以大大减少设计中的错误和提高设计效率:
(1)对组合逻辑建模采用阻塞赋值。
(2)对时序逻辑建模采用非阻塞赋值。
(3)用多个always块分别对组合和时序逻辑建模。
(4)尽量不要在同一个always块里面混合使用“阻塞赋值”和“非阻塞赋值”:
如果在同一个always块里面既组合逻辑又为时序逻辑建模,则应使用“非阻塞赋值”。
2.2.6组合逻辑电路
(1)组合逻辑电路的特点:
任何时刻的输出仅决定于当时的输入信号,这是组合逻辑电路在功能上的共同特点。
(2)组合逻辑电路的设计方法:
第一步,逻辑抽象。
第二步,写逻辑表达式。
第三步,绘逻辑图。
第四步,HDL编程。
第五步,设计输入。
第六步,设计仿真。
第七步,编程下载。
2.2.7时序逻辑电路
(1)时序电路的特点:
任一时刻的输出信号不仅取决于当时的输入信号,而且还取决于电路的原来状态。
(2)时序电路的设计方法:
第一步,从给定的逻辑图中写出电路的输出方程和触发器的驱动方程,然后将驱动方程代入触发器的特征方程,得到状态方程。
第二步,将输入变量和触发器的各种取值组合,代入状态方程和输出方程,计算得到状态转换表。
第三步,将状态转换表的状态变化规律用状态转换图或时序图表示出来。
第四步,根据状态转换图或时序图说明电路的逻辑功能。
第三章汉明码的编译码设计
3.1汉明码的原理
3.1.1基本概念
线性分组码是一类重要的纠错码,应用很广泛。
在(n,k)分组码中,若
督元是按线性关系相加而得到的,则称其为线性分组码。
现在以(7,4)分组码为例来说明线性分组码的特点。
设其码字为
,其中前4位是信息元,后3位是监督元,可用下列线性方程组来描述该分组码,产生监督元:
(3.1.1)
监督位计算结果
序
号
码
字
信息码元
监督元
0
0
0
8
1
0
1
1
1
9
2
10
3
11
4
12
5
13
6
14
7
15
表3-1-1
由表3-1-1不难看出,上述(7,4)码的最小码距d0=3,它能纠1个错或检2个错。
汉明码是能够纠正单个错误的线性分组码,其特点是:
最小码距d0=3,码长n与监督位满足n=2r-1的关系,上述的(7,4)线性分组码就是一个汉明码。
3.1.2监督矩阵H
式(3.1.1)所示(7,4)汉明码的3个监督方程改写后可用矩阵形式表示为
=
并记为
H称为监督矩阵,一旦H给定,信息位和监督位之间的关系也就确定了。
H矩阵可以分成2部分
,可以用来作为判断接收码字A是否出错的依据。
3.1.3生成矩阵G
=
A=
·
G
G称为生成矩阵,由G和信息组就可以产生全部码字。
生成矩阵也可以分成2部分,即
其中
3.1.4伴随式(校正子)S
设发送码组
在传输过程中可能发生误码。
接收码组
收发码组之差定义为错码行矩阵E,即
B=A+E
其中
因此,若
表示该接收码元无错;
若
则表示该接收码元有错。
令
,成为伴随式。
下表是(7,4)汉明码的S与E的对应关系
错误
码位
E
S
e6
e5
e4
e3
e2
e1
e0
s2
s1
s0
/
b0
b1
b2
b3
b4
b5
b6
表3-1-1
3.2汉明码的编码器设计
3.2.1编码器的设计流程图
N
Y
图3-2-1
3.2.2代码设计
首先输入4位并行的信息码in[3:
0],输出加了帧头1010和奇偶校验位的12位串行码out。
帧头1010是在程序中直接给的。
代码如下:
ham[11:
8]<
=4'
b1010;
监督码ham[3],ham[2],ham[1]是根据生成矩阵
通过异或信息位得到的。
ham[3]<
=in[3]^in[2]^in[1];
ham[2]<
=in[3]^in[2]^in[0];
ham[1]<
=in[3]^in[1]^in[0];
奇偶校验位是把得到的7位(7,4)汉明码异或得到的。
ham[0]<
=in[3]^in[2]^in[1]^in[0]^(in[3]^in[2]^in[1])^(in[3]^in[2]^in[0])^(in[3]^in[1]^in[0]);
把得到的12位并行数据转换为12位串行数据我们加了一个计数器。
elseif(count==4'
d11)
begin
count<
=count+4'
d1;
ready<
=1;
out<
=ham[0];
end
else
=ham[4'
d11-count];
d1
3.2.3仿真波行及其分析
图3-2-2
先对波形中的信号作一个说明:
rst:
复位信号,高电平表示复位。
in_en:
使能信号,高电平时允许工作。
clk:
时钟信号,上升沿时表示事件发生。
clkcnt:
计数器,用来控制何时输入数据。
in:
输入信号,这里输入4位并行数据。
ready:
准备输出信号,高电平时表示输出的信号有效。
out:
输出信号,这里输出的是12位串行信号。
分析:
从图中可以看出此时复位信号为低电平,使能端为高电平,此时编码器处于工作状态,我们从图中可以看出输入两组四位并行数据1101和1110。
我们先分析1101,首先我们通过关系式算出ham[3]<
得出ham[3]=1^1^0=0。
由ham[2]<
=in[3]^in[2]^in[0];
得出ham[2]=1^1^1=1。
由ham[1]<
得出ham[1]=1^0^1=0。
因为4个1,所以奇偶校验位ham[0]=0,故ham[11:
0]=101011010100从图中可以看出ham存的12位并行数据的确为101011010100,。
从图中可以看出当ready=1,out会依次输出1,0,1,0,1,1,0,1,0,1,0,0十二位串行数据。
同理也可以验证输入1110,输出是1,0,1,0,1,1,1,0,1,0,0,0的十二位串行数据。
3.3汉明码解码器的设计
3.3.1解码器的设计流程图
图3-3-1
3.3.2代码设计
输入信号是串行信号in,输出是并行的信号。
先设置一个4位移位寄存器,当寄存器里的值时1010时,便提取后面的七位数据位。
temp[3:
1]<
=temp[2:
0];
temp[0]<
=in;
算出校正子S(是一个三位寄存器)的值。
代码的实现:
ham[0]=in;
S[2]=ham[6]^ham[5]^ham[4]^ham[2];
S[1]=ham[6]^ham[5]^ham[3]^ham[1];
S[0]=ham[6]^ham[4]^ham[3]^in;
判断奇偶校验位是否正确。
if(ham[0]^ham[1]^ham[2]^ham[3]^ham[4]^ham[5]^ham[6]!
=in)
纠错功能
代码的实现case(S)
3'
b011:
out<
=ham[6:
3]^4'
b0001;
b101:
b0010;
b110:
b0100;
b111:
b1000;
3.3.3仿真波形及其分析
图3-3-2
先对波形的信号作一个说明:
。
temp:
数据寄存器,当检测到1010时便提取后面的数据。
分析:
输入是:
101011111111101011010100-----
当temp里面的数是1010便提取后面的7位数,在判断奇偶校验位没有错后,便成功的输出是四位信息位,按理论将输出1111和1101四位并行的数,从图中可以看出输出的是1111和1101,从而实现汉明码的译码。
3.4汉明码的编码器和译码器的连接
直接使用Verilog的模块调用语句将模块实体化,调用时填入你要连接的Wire名就可以实现连接。
比如下列语句中,将模块Module1的out端口和Module2的in端口连接起来。
wireA;
Module1(.out(A));
Module2(.in(A));
这样即可。
图3-4-1
从波形中可以看出编码器的输入的四位并行数据分别是1110,1111,1001,在ready高电平时解码器输出四位并行数据分别是1110,1111,1001。
从而验证了编码和解码的过程是完全正确的。
结束语
这个课题用的是verilog语言写的,由于我以前没学过。
所以在选的课题后我找了本verilo