循环冗余校验编码CRC.docx
- 文档编号:12342294
- 上传时间:2023-04-18
- 格式:DOCX
- 页数:15
- 大小:213.84KB
循环冗余校验编码CRC.docx
《循环冗余校验编码CRC.docx》由会员分享,可在线阅读,更多相关《循环冗余校验编码CRC.docx(15页珍藏版)》请在冰豆网上搜索。
循环冗余校验编码CRC
EDA专用周实训报告
课题:
循环冗余校验编码(CRC)
组员:
指导老师:
前言
EDA(电子设计自动化)技术是现代电子工程领域的一门新技术,它提供了基于计算机和信息技术的电路系统设计方法。
EDA技术的发展和推广应用极大地推动了电子工业的发展。
随着EDA技术的发展,硬件电子电路的设计几乎可以完全依靠计算机来完成,这样就大大缩短了硬件电子电路设计的周期,从而使制造商可以快速开发出品种多、批量小的产品,以满足市场的需求。
EDA教学和产业界的技术推广时当今世界的一个技术热点,EDA技术是现代电子行
业中不可缺少的一项技术。
CRC(CyclicRedundancyCheck)循环冗余校验码是常用的校验码,在早期的通信中运用广泛,因为早期的通信技术不够可靠(不可靠性的来源是通信技术决定的,比如电磁波通信时受雷电等因素的影响),不可靠的通信就会带来‘确认信息’的困惑,对通信的可靠性检查就需要‘校验’,校验是从数据本身进行检查,它依靠某种数学上约定的形式进行检查,校验的结果是可靠或不可靠,如果可靠就对数据进行处理,如果不可靠,就丢弃重发或者进行修复。
目录
一:
实验目的4
二:
实验内容4
三:
实验步骤4
四:
实验原理5
1.CRC校验码介绍5
2.硬件电路的实现方法6
五:
程序设计………………………………………………………7
六:
专用周总结12
一:
实验目的
1:
学习CRC编码基本流程,学会调试循环冗余校验码编码程序。
2:
掌握CRC校验码的编码原理,重点掌握按字节(Byte)编码方法。
3:
学习用FPGA设计一个数据通信中常用的数据检测模块——循环冗余校验CRC模块,熟悉理解CRC的检测原理。
二:
实验内容
本实验的内容是设计循环冗余校验CRC模块。
利用Quartus2完成设计、仿真等工作,最后在SmartSOPC实验箱上进行硬件测试和分析。
通过KEY1~KEY3输入信息,并显示于数码管1~3,接收到的数据显示于数码管4~6,CRC校验码显示于数码管7/8。
按KEY4加载要发送的信息,由LED2指示其状态;KEY5为复位键,由LED1指示,数据接收状态由LED3(完成)和LED4(出错)指示,数据的输入、输出显示等操作由本实验提供的一个测试模块(crc5_test)完成,用户可以自行分析该测试模块。
这里主要介绍CRC模块的设计。
三:
实验步骤
1:
启动Quartus2建立一个空白工程,然后命名为crc5.pqf。
2:
建立VerilogHDL源程序文件crc5.v.,写出程序代码并保存(完整的VerilogHDL程序参考清单),进行综合编译。
若在编译过程中发现错误,则找出并更正错误,直至编译成功为止。
3:
建立波形仿真文件并进行仿真验证,分析其运行最高时钟频率。
4:
将光盘中EDA_Component目录下的crc5_test.bsf、crc5_test.v拷贝到工程目录。
5:
自行设计按键及数码管显示程序然后编译直至没有发现错误。
6:
选择目标器件并对相应的引脚进行锁定。
7:
将crc5_top.bdf设置为顶层实体,对该工程文件进行全程编译处理。
8:
硬件连接,下载程序。
9:
通过KEY1~KEY5进行操作,观察数码管和发光二极管的状态,取几个数计算验证。
四:
实验原理
1.CRC校验码介绍
CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。
在接收端,则根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。
16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(乘以216)后,再除以一个多项式,最后所得到的余数既是CRC码。
求CRC码所采用模2加减运算法则,既是不带进位和借位的按位加减,这种加减运算实际上就是逻辑上的异或运算,加法和减法等价,乘法和除法运算与普通代数式的乘除法运算是一样,符合同样的规律。
接收方将接收到的二进制序列数(包括信息码和CRC码)除以多项式,如果余数为0,则说明传输中无错误发生,否则说明传输有误。
2、实现方法:
CRC码是由两部分组成,前部分是信息码,就是需要校验的信息,后部分是校验码,如果CRC码共长n个bit,信息码长k个bit,就称为(n,k)码。
它的编码规则是:
1)、首先将原信息码(kbit)左移r位(k+r=n)
2)、运用一个生成多项式g(x)(也可看成二进制数)用模2除上面的式子,得到的余数就是校验码
生成CRC码的基本原理:
任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。
例如:
代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。
3硬件电路的实现方法
多项式除法,可用除法电路来实现。
除法电路的主体由一组移位寄存器和模2加法器(异或单元)组成。
以CRC-ITU为例,它由16级移位寄存器和3个加法器组成,见下图(编码/解码共用)。
编码、解码前将各寄存器初始化为"1",信息位随着时钟移入。
当信息位全部输入后,从寄存器组输出CRC结果。
五:
程序设计
modulezyz(clock,key,led,seg,dig);
inputclock;
input[4:
0]key;
output[3:
0]led;
output[7:
0]seg;
output[7:
0]dig;
wire[11:
0]sdata;
wire[11:
0]rdata;
wire[4:
0]crc;//crc冗余码输入
wiredload;
wirerst_n;
regled2_r;
regled3_r;
reg[11:
0]sdata_r;
reg[11:
0]rdata_r;
reg[7:
0]seg_r;
reg[7:
0]dig_r;
regdload_r;
reg[16:
0]count;
reg[4:
0]dout1,dout2,dout3;
reg[4:
0]buff;
reg[2:
0]cnt3;
reg[3:
0]disp_dat;
regdiv_clk;
wire[4:
0]key_edge;
wire[16:
0]datacrco;
wirehsend;
reg[16:
0]datacrci;
reghrecv;
reg[16:
0]datacrco_r;
reghsend_r;
reg[16:
0]dtemp;
reg[11:
0]sdtemp;
reg[16:
0]rdtemp;
reg[16:
0]rdatacrc;
/*信号输出*/
assigncrc[4:
0]=datacrco_r[4:
0];
assignled[2]=led2_r;
assignled[3]=led3_r;
assignseg=seg_r;
assigndig=dig_r;
assignsdata=sdata_r;
assigndload=dload_r;
assignled[1:
0]={~dload_r,rst_n};
parameterpolynomial=6'b110101;
assigndatacrco=datacrco_r;
assignhsend=hsend_r;
assignrdata=rdata_r;
/*时钟分频部分*/
always@(posedgeclock)
begin
if(count<17'd120000)
begin
count<=count+1'b1;
div_clk<=1'b0;
end
else
begin
count<=17'd0;
div_clk<=1'b1;
end
end
/*按键消抖部分*/
always@(posedgeclock)
begin
if(div_clk)
begin
dout1<=key;
dout2<=dout1;
dout3<=dout2;
end
end
/*按键边沿检测部分*/
always@(posedgeclock)
begin
buff<=dout1|dout2|dout3;
end
/*下降沿检测*/
assignkey_edge=~(dout1|dout2|dout3)&buff;
/*3位16进制数输出部分*/
always@(posedgeclock)//按键1
begin
if(key_edge[0])//下降沿检测
sdata_r[11:
8]<=sdata_r[11:
8]+1'b1;
end
always@(posedgeclock)//按键2
begin
if(key_edge[1])//下降沿检测
sdata_r[7:
4]<=sdata_r[7:
4]+1'b1;
end
always@(posedgeclock)//按键3
begin
if(key_edge[2])//下降沿检测
sdata_r[3:
0]<=sdata_r[3:
0]+1'b1;
end
always@(posedgeclock)//按键4
begin
if(key_edge[3])
//下降沿检测
dload_r<=~dload_r;
end
assignrst_n=buff[4];//按键5
always@(posedgeclockornegedgerst_n)
begin
if(!
rst_n)
begin
hsend_r=1'b0;
datacrco_r=17'd0;
end
elseif(dload==1'b1)
begin
dtemp={sdata,5'b00000};
sdtemp=sdata;
if(dtemp[16])dtemp[16:
11]=dtemp[16:
11]^polynomial;
if(dtemp[15])dtemp[15:
10]=dtemp[15:
10]^polynomial;
if(dtemp[14])dtemp[14:
9]=dtemp[14:
9]^polynomial;
if(dtemp[13])dtemp[13:
8]=dtemp[13:
8]^polynomial;
if(dtemp[12])dtemp[12:
7]=dtemp[12:
7]^polynomial;
if(dtemp[11])dtemp[11:
6]=dtemp[11:
6]^polynomial;
if(dtemp[10])dtemp[10:
5]=dtemp[10:
5]^polynomial;
if(dtemp[9])dtemp[9:
4]=dtemp[9:
4]^polynomial;
if(dtemp[8])dtemp[8:
3]=dtemp[8:
3]^polynomial;
if(dtemp[7])dtemp[7:
2]=dtemp[7:
2]^polynomial;
if(dtemp[6])dtemp[6:
1]=dtemp[6:
1]^polynomial;
if(dtemp[5])dtemp[5:
0]=dtemp[5:
0]^polynomial;
datacrco_r={sdtemp,dtemp[4:
0]};
hsend_r=1'b1;
end
else
hsend_r=1'b0;
end
always@(posedgeclockornegedgerst_n)
begin
if(!
rst_n)
begin
rdata_r=12'd0;
led2_r=1'b1;
led3_r=1'b1;
end
elseif(hsend==1'b1)
begin
rdatacrc=datacrco_r;
rdtemp=datacrco_r;
if(rdtemp[16])rdtemp[16:
11]=rdtemp[16:
11]^polynomial;
if(rdtemp[15])rdtemp[15:
10]=rdtemp[15:
10]^polynomial;
if(rdtemp[14])rdtemp[14:
9]=rdtemp[14:
9]^polynomial;
if(rdtemp[13])rdtemp[13:
8]=rdtemp[13:
8]^polynomial;
if(rdtemp[12])rdtemp[12:
7]=rdtemp[12:
7]^polynomial;
if(rdtemp[11])rdtemp[11:
6]=rdtemp[11:
6]^polynomial;
if(rdtemp[10])rdtemp[10:
5]=rdtemp[10:
5]^polynomial;
if(rdtemp[9])rdtemp[9:
4]=rdtemp[9:
4]^polynomial;
if(rdtemp[8])rdtemp[8:
3]=rdtemp[8:
3]^polynomial;
if(rdtemp[7])rdtemp[7:
2]=rdtemp[7:
2]^polynomial;
if(rdtemp[6])rdtemp[6:
1]=rdtemp[6:
1]^polynomial;
if(~(rdtemp[5:
0]^polynomial))
begin
rdata_r=rdatacrc[16:
5];
led2_r=4'b0;
end
else
begin
rdata_r=12'd0;
led3_r=1'b0;
end
end
else
led2_r=1'b1;
end
/*数码管扫描显示部分*/
always@(posedgeclock)//定义上升沿触发进程
begin
if(div_clk)
cnt3<=cnt3+1'b1;
end
always@(posedgeclock)
begin
if(div_clk)
begin
case(cnt3)//选择扫描显示数据
3'd0:
disp_dat=sdata_r[11:
8];//第一个数码管
3'd1:
disp_dat=sdata_r[7:
4];//第二个数码管
3'd2:
disp_dat=sdata_r[3:
0];//第三个数码管
3'd3:
disp_dat=rdata_r[11:
8];//第四个数码管
3'd4:
disp_dat=rdata_r[7:
4];//第五个数码管
3'd5:
disp_dat=rdata_r[3:
0];//第六个数码管
3'd6:
disp_dat={3'b0,crc[4]};//第七个数码管
3'd7:
disp_dat=crc[3:
0];//第八个数码管
endcase
case(cnt3)//选择数码管显示位
3'd0:
dig_r=8'b01111111;//选择第一个数码管显示
3'd1:
dig_r=8'b10111111;//选择第二个数码管显示
3'd2:
dig_r=8'b11011111;//选择第三个数码管显示
3'd3:
dig_r=8'b11101111;//选择第四个数码管显示
3'd4:
dig_r=8'b11110111;//选择第五个数码管显示
3'd5:
dig_r=8'b11111011;//选择第六个数码管显示
3'd6:
dig_r=8'b11111101;//选择第七个数码管显示
3'd7:
dig_r=8'b11111110;//选择第八个数码管显示
endcase
end
end
always@(disp_dat)
begin
case(disp_dat)//七段译码
4'h0:
seg_r=8'hc0;//显示0
4'h1:
seg_r=8'hf9;//显示1
4'h2:
seg_r=8'ha4;//显示2
4'h3:
seg_r=8'hb0;//显示3
4'h4:
seg_r=8'h99;//显示4
4'h5:
seg_r=8'h92;//显示5
4'h6:
seg_r=8'h82;//显示6
4'h7:
seg_r=8'hf8;//显示7
4'h8:
seg_r=8'h80;//显示8
4'h9:
seg_r=8'h90;//显示9
4'ha:
seg_r=8'h88;//显示a
4'hb:
seg_r=8'h83;//显示b
4'hc:
seg_r=8'hc6;//显示c
4'hd:
seg_r=8'ha1;//显示d
4'he:
seg_r=8'h86;//显示e
4'hf:
seg_r=8'h8e;//显示f
endcase
end
Endmodule
六:
专用周总结
/*************************************************************************************\
主要供工程学院的学弟学妹们参考。
程序还是自己在看看哦!
希望你们能学好这门课
通信技术
2011.3
/*************************************************************************************\
七、参考资料
1、王金明,数字系统设计与VerilogHDL,北京:
电子工业出版,2010.7
2、周立功,EDA实验与实践,北京:
北京航空航天大学出版社,2007.93、网
4、程序源码搜索引擎
5、中国电子网
6、全球最大中文IT技术社区
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 循环 冗余 校验 编码 CRC