CRC校验原理和verilog实现方法(三)

时间:2022-07-16 04:33:57

1 代码生成

verilog实现CRC校验,可以充分发挥FPGA的硬件特性,即并行运算的能力。

具体实现方式,可以参考我上一篇博客,关键是用线性反馈移位寄存器表示出多项式,另外注意校验数据高位在先。然后根据电路结构推导出逻辑表达式,再转换成verilog就行了。

更高效的方法是利用现成的代码生成工具,例如附件的链接1,就是一种在线的CRC校验代码生成工具。

2 修改移植

我这里用代码生成工具生成多项式为x^4 + x^1 + 1,即CRC-4/ITU校验模型,校验输入数据位宽为4bit的CRC代码,并分享一下修改移植时的心得。

生成的代码如下,这个多项式和我上一篇博客举例所用多项式一样,所以生成的代码之前推导的逻辑表达式也是相同的。

function [3:0] nextCRC4_D4;

input [3:0] Data;
input [3:0] crc;
reg [3:0] d;
reg [3:0] c;
reg [3:0] newcrc;
begin
d = Data;
c = crc;

newcrc[0] = d[3] ^ d[0] ^ c[0] ^ c[3];
newcrc[1] = d[3] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[3];
newcrc[2] = d[2] ^ d[1] ^ c[1] ^ c[2];
newcrc[3] = d[3] ^ d[2] ^ c[2] ^ c[3];
nextCRC4_D4 = newcrc;
end
endfunction

其实这段代码有用的只是中间那四行行为级赋值语句,可以直接拷贝到工程里使用。其中d是4位的校验数据,c是CRC寄存器。

用这段代码做CRC校验时,有几点需要明确:

1)数据位宽。

2)输入输出是否高低位反转。

3)c的初值。

4)输出是否按位取反。

其中第1点取决于通信时一帧数据的长度,第2、3点一般在常用的CRC校验模型中规定好了。这里用的CRC-4/ITU校验模型规定c的初值为0,输出不需要取反,输入输出高低位需要反转。

如果被校验数据data只有4bit,那么直接令data高低位反转后赋值d,c=0,组合逻辑输出的就是4位newcrc做高低位反转,最后得到的就是CRC校验码;

假如被校验的数据位数大于4bit,需要按字节来进行“叠加”校验。

比如数据data[15:0]=1577h,那么安照这样的校验流程:高字节低4bit(5h)反转后给d——newcrc作为下次校验的c的值——高字节高4bit(1h)反转后给d——newcrc作为下次校验的c的值——低字节低4bit(7h)反转后给d——newcrc作为下次校验的c的值——低字节高4bit(7h)反转后给d——newcrc反转后作为CRC校验码

c的更新可以用寄存器实现。如下所示:

reg [3:0] c;
wire [3:0] d; //参与校验数据

assign d = {data_r[0], data_r[1], data_r[2], data_r[3]};//翻转数据位

assign newcrc[0] = crc_en & (d[3] ^ d[0] ^ c[0] ^ c[3]);
assign newcrc[1] = crc_en & (d[3] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[3]);
assign newcrc[2] = crc_en & (d[2] ^ d[1] ^ c[1] ^ c[2]);
assign newcrc[3] = crc_en & (d[3] ^ d[2] ^ c[2] ^ c[3]);

always @(posedge clk or negedge rstn) begin
  if(!rstn)
    c <= 4'h0;//初始0
  else begin
    if(start_pos)
      c <= 4'h0;
    else if(crc_en)
      c <= newcrc;
  end
end

3 功能验证

为了验证上面修改的代码功能,编写了测试代码,对16bit的数据求校验码。这里分别验证了data[15:0]=1577h和data[15:0]=4511h两个数据的CRC校验。

1)data[15:0]=1577h

在开发板上运行测试代码,用signalTAP观察结果(电脑上没有装Modelsim),其中data_in为待校验数据,经过4次计算,得到校验码为crc_out=0x2。

CRC校验原理和verilog实现方法(三)

利用在线CRC计算工具(链接见我之前的博客),计算1577h的校验码,与测试结果一致:

CRC校验原理和verilog实现方法(三)

2)data[15:0]=4511h

得到校验码为crc_out=0xF。

CRC校验原理和verilog实现方法(三)

利用在线CRC计算工具(链接见我之前的博客),计算4511h的校验码,与测试结果一致:

CRC校验原理和verilog实现方法(三)

这就说明,本文的“叠加”校验,可以实现对多字节数据的“分段”校验。多字节数据可以是4字节、16字节等,CRC校验代码中的输入数据d可以是1bit、2bit、4bit、8bit等。

不过据我的经验,要实现这种“叠加”校验,必须设置输入输出数据高低位反转,不然结果不对。也就是说如果你选的校验模型不需要数据位反转,那么只能做一次性的校验了。具体原因咱也研究不清楚,不知道有没有大神解答。

在线CRC代码生成链接:

1、https://www.easics.com/crctool/