简单并行CRC(verilog)(转)

这么久真是囧的几周, 天天在囧一个相关的问题. 一直没有囧出来= =.. 偏偏网上资料少得可怜… 本来没有想到弄CRC 检验的, 但是由于前个星期在囧状态机的时候无意描述了一个LFSR 也就是线性移位寄存器, 然后不知道除了做模2 还可以干嘛, 于是查到了CRC 可以用那块实现. 也就是串行校验… 并且相当有趣的算法. 可是囧了一个星期, 逻辑图画了一次又一次, 换了N 总方式来描述,DA TA 都出来相当囧异的x… 刚才突然醒悟过来,MS 忘记了给reg 初值了.. 嗯, 等下再试试!!!
呵呵, 归正传, 由于用串行实现CRC 暂时搁下, 于是临时写了个并行检验 CRC 当作对CRC 实现的笔记, 然后可以安心地去复习信号和模电以及膜拜马克思老先生了….
嗯, 怎么解释这个方法呢. 就是如果发送1110001, 我们可以用多项式t(x)=x^7+x^6+x^5+1 表示, 然后选择一个k 次幂的生成多项式g(x), 当然生成多项式是现成的, 有国际标准的. 比如CRC-4 标准中,g(x)=x^4+x+1,( 对应序列就是10011).
实现步骤
1)        设选择的生成多项式为g(x), 最高次幂为k;
2)        将发送的数据序列左移k 位;( 设为t1(x))
3)        设r(x) 序列余数, 注意这里的除法求余运算事实上二进制模2 运算, 即( 加不进位) 减不借位, 相当于k 除数和被除数的高k 位进行一次异或( 这下明白为啥可以用lfsr 来实现了吧). 则r(x) 等于按模2 算法t1(x) 除以g(x) 的余数序列.
4)        用r(x) 加t1(x) 则构成带校验码的新序列( 设为t2(x)). 如果数据在传送过程中没有出差错, 则接收到的t2(x) 再与g(x) 进行模2 运算, 则余数为0, 否传送则数据出错.
如果对模2 运算不清晰的话
参考
http://zhidao.baidu.com/question/90071684.html?si=1
因为没有调之前没有调成功用线形移位寄存器实现模2 运算, 所以才用并行数据发送并监测. 也就是说, 又有点回到了” 编程序” 的感觉. 在这里, 整个模2 运算的过程类似于手工除法步骤, 建议自己动手再画一画过程= =|| 判断是否需要和g(x) 进行异或操作参照竖式处罚, 只是加减运算采用异或(^) 运算来代替. 当运算完成将也余数和送入数据拼接得到最终的CRC 码.
方法如此一目了然, 所以直接给程序了= =|||( 由于网上资料少, 所以懂哥不能保证正确性还有臃肿性….)
生成CRC 模块
module CRC_G(clk,
             res_n,
             da ta_in,//7 bit parallel da ta in
             da ta_crc);//11 bit parallel da ta out(origin +crc co de)
     input clk,res_n;
     input [6:0]da ta_in;
     output [10:0]da ta_crc;
     reg [10:0]da ta_crc;//origin+crc
     reg [10:0]temp;//regist da ta_in when division begin
     parameter polynomial=5'b10011;//g(x)=x^4+x+1
     always@(posedge clk or negedge res_n)
     begin
         if(!res_n)
         begin
             da ta_crc<=0;
             temp<=0;
         end
         else
             temp<={da ta_in,4'b0};
     end
     always@(temp)//generate crc_output  
         begin  
             if(temp[10])temp[10:6]=temp[10:6]^polynomial; 
             if(temp[9])temp[9:5]=temp[9:5]^polynomial; 
             if(temp[8])temp[8:4]=temp[8:4]^polynomial; 
             if(temp[7])temp[7:3]=temp[7:3]^polynomial; 
             if(temp[6])temp[6:2]=temp[6:2]^polynomial; 
             if(temp[5])temp[5:1]=temp[5:1]^polynomial; 
             if(temp[4])temp[4:0]=temp[4:0]^polynomial; 
             da ta_crc={da ta_in,temp[3:0]};  
         end  

endmodule
附一个当时写的检查这一块testbench( 好像有很大问题…)
`timescale 10ns/10ns
module t_crc;
     reg clk;
     reg res_n;
     reg [6:0]da ta;
     wire [6:0]da ta_in;
     wire [10:0]da ta_crc;
CRC_G t(.clk(clk),.res_n(res_n),.da ta_in(da ta_in),.da ta_crc(da ta_crc));
always #10 clk=~clk;
initial 
begin
     clk=0;
     #10 res_n=1;
     #10 res_n=0;
     #10 res_n=1;
   / /da ta=7'b1110111;
     #1000 $stop;
end
assign da ta_in=da ta;
always@(posedge clk)
     da ta={$random}%2;
endmodule
但是这一块出来的结果还算正确= =, 但是总觉得心里不太踏实..
CRC 码检查模块
module CRC_C(clk,
             res_n,
             da ta_crc,//get from module CRC_G
             da ta_out);//output the checked da ta
input clk,res_n;
input [10:0]da ta_crc;//11 bit CRCcode
output [6:0]da ta_out;//7 da ta out
reg [10:0]datacrc_c;//11 bit regist CRCcode
reg [6:0]da ta_out;
parameter polynomial=5'b10011;//g(x)=x^4+x+1
CRC_G m(.clk(clk),.res_n(res_n),.da ta_crc(da ta_crc));
always@(posedge clk or negedge res_n)
     begin
         if(!res_n)
         begin
             da ta_out<=0;
             datacrc_c<=0;
         end
         else
             datacrc_c<=da ta_crc;
     end
always@(datacrc_c)//check crc
     begin
             if(datacrc_c[10])datacrc_c[10:6]=datacrc_c[10:6]^polynomial;
             if(datacrc_c[9])datacrc_c[9:5]=datacrc_c[9:5]^polynomial;
             if(datacrc_c[8])datacrc_c[8:4]=datacrc_c[8:4]^polynomial;
             if(datacrc_c[7])datacrc_c[7:3]=datacrc_c[7:3]^polynomial;
             if(datacrc_c[6])datacrc_c[6:2]=datacrc_c[6:2]^polynomial;
             if(datacrc_c[5])datacrc_c[5:1]=datacrc_c[5:1]^polynomial;
             if(datacrc_c[4])datacrc_c[4:0]=datacrc_c[4:0]^polynomial;
             if(datacrc_c[3:0]==0)
                 da ta_out=da ta_crc[10:4];
             else
                 da ta_out=0;
     end
endmodule

测试模块和刚才那个差不多,但是由于文章字数限制所以没有贴上来. 
但是请注意那囧异的波形确实不知道哪里有问题了…
MS生成CRC校验码出来都是对的..但是..但是为何最后就没反应了呢..请有兴趣的高手帮忙看一下= =


简单并行CRC(verilog)(转)_第1张图片


然后懂哥郁闷的发现,怎么仿真让数据在传送中出错被检测到呢?= =||又这是一个问题


总结:Verilog应该是一种描述语言,先有电路再有描述,不知道这么认为对不对.可惜…思路转换真麻烦啊…这次就是像写程序一样实现的,感觉有点惭愧…
提一下,下图是g(x)=x^4+x+1模2的图;


简单并行CRC(verilog)(转)_第2张图片

就是困扰懂哥N久的想要改造成生成CRC码LFSR,先放在这里了,现在找到问题了,应该好办了吧.不过这两周要加课且要考好几门课了,不贝多芬不行啊= =,
对了,就在这篇里面水两句,民航总局局长来我们学校蹭饭,为期一周,天啦,我们又面对每天穿制服的囧样,一个星期啊…又要穿那个火锅妹一样的制服!!!于是懂哥相信局长来我校会有深陷”制服门”的感觉.嗯,今天笔记整理到这里.

你可能感兴趣的:(FPGA)