这么久真是囧的几周,
天天在囧一个相关的问题.
一直没有囧出来= =..
偏偏网上资料少得可怜…
本来没有想到弄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
呵呵,
嗯,
实现步骤
1)
2)
3)
4)
如果对模2
参考
http://zhidao.baidu.com/question/90071684.html?si=1
因为没有调之前没有调成功用线形移位寄存器实现模2
方法如此一目了然,
生成CRC
module CRC_G(clk,
res_n,
da
da
input clk,res_n;
input [6:0]da
output [10:0]da
reg [10:0]da
reg [10:0]temp;//regist da
parameter polynomial=5'b10011;//g(x)=x^4+x+1
always@(posedge clk or negedge res_n)
begin
if(!res_n)
begin
da
temp<=0;
end
else
temp<={da
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
end
endmodule
附一个当时写的检查这一块testbench(
`timescale 10ns/10ns
module t_crc;
reg clk;
reg res_n;
reg [6:0]da
wire [6:0]da
wire [10:0]da
CRC_G t(.clk(clk),.res_n(res_n),.da
always #10 clk=~clk;
initial
begin
clk=0;
#10 res_n=1;
#10 res_n=0;
#10 res_n=1;
/ /da
#1000 $stop;
end
assign da
always@(posedge clk)
da
endmodule
但是这一块出来的结果还算正确= =,
CRC
module CRC_C(clk,
res_n,
da
da
input clk,res_n;
input [10:0]da
output [6:0]da
reg [10:0]datacrc_c;//11 bit regist CRCcode
reg [6:0]da
parameter polynomial=5'b10011;//g(x)=x^4+x+1
CRC_G m(.clk(clk),.res_n(res_n),.da
always@(posedge clk or negedge res_n)
begin
if(!res_n)
begin
da
datacrc_c<=0;
end
else
datacrc_c<=da
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
else
da
end
endmodule
测试模块和刚才那个差不多,
但是请注意那囧异的波形确实不知道哪里有问题了…
MS
然后懂哥郁闷的发现,
总结:Verilog
提一下,
就是困扰懂哥N
对了,
八卦也丢这里了: