简单串行CRC的verilog实现

简单串行CRC的verilog实现

CRC(Cyclic Redundancy Check,循环冗余校验)是数据传输中常用的一种差错控制编码方式,针对要发送的数据帧,使用一些特定的多项式可以计算出CRC校验结果,CRC校验结果和原始数据一起传输到接收端。

本例基于LSFR建立一个多项表达式为x8+x2+x+1的CRC算法,步骤如下:
a.计算CRC之前,CRC寄存器初始化为一个已知的值(初始值),接收端的CRC校验电路的初始值要使用和发送端相同的初始值。
b.当最后一个数据比特到达时,CRC内部存储的就是最后的校验结果
c.在最后一个数据比特发出后,储存在寄存器中的CRC校验结果逐比特输出,直至最后一个比特。校验结果紧跟在用户数据后面输出。

LSFR的多项表达式含义详解见https://blog.csdn.net/qq_44113393/article/details/89852994

CRC算法图如下:
简单串行CRC的verilog实现_第1张图片

其CRC寄存器代码如下,CRC的初始值设为8’hFF

module CRC8_CCITT
 (clk,reset,
 din,
 init_crc,
 calc_crc,
 crc_out);
input clk,reset;
input din;
input [7:0]init_crc;
input calc_crc;
output [7:0] crc_out;
parameter CRC_INIT_VALUE = 8'hFF;
reg [7:0]crcreg,crcreg_nxt;
wire [7:0] newcrc;
wire [7:0] crc_out;
assign newcrc[0] = crcreg[7]^din;
assign newcrc[1] = (crcreg[7]^din)^crcreg[0];
assign newcrc[2] = (crcreg[7]^din)^crcreg[1];
assign newcrc[3] = crcreg[2];
assign newcrc[4] = crcreg[3];
assign newcrc[5] = crcreg[4];
assign newcrc[6] = crcreg[5];
assign newcrc[7] = crcreg[6];
always @(*)begin
 if(init_crc)
 crcreg_nxt = CRC_INIT_VALUE;
 else if(calc_crc)
 crcreg_nxt = newcrc;
 else
 crcreg_nxt = crcreg;
end
always @(posedge clk or negedge reset)begin
 if(!reset)
 crcreg = CRC_INIT_VALUE;
 else
 crcreg = crcreg_nxt;
end
assign crc_out = crcreg;
endmodule

测试文件代码如下:

`timescale 1ns/1ns
module testbench_CRC8_CCITT;
reg clk_tb,reset_tb;
reg din_tb;
reg init_crc_tb,calc_crc_tb;
wire [7:0] crc_out_tb;
parameter CLK_HALF_PERIOD = 5;
parameter RST_DEASSERT_DLY = 100;
initial begin
 clk_tb = 1'b0;
 forever begin
  #CLK_HALF_PERIOD clk_tb = ~clk_tb;
 end
end
initial begin
 reset_tb = 1'b0;
 #RST_DEASSERT_DLY reset_tb = 1'b1;
end
initial begin
 din_tb = 0; 
 #RST_DEASSERT_DLY;
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 0;
 @(posedge clk_tb);
 #1 din_tb = 0;
 @(posedge clk_tb);
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 0;
 @(posedge clk_tb);
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 0;
end
initial begin
 init_crc_tb = 0;
 calc_crc_tb = 1;
end
CRC8_CCITT  test_CRC8_CCITT
 (.clk(clk_tb),.reset(reset_tb),
 .din(din_tb),
 .init_crc(init_crc_tb),
 .calc_crc(calc_crc_tb),
 .crc_out(crc_out_tb)
 );
endmodule

仿真结果如下:
简单串行CRC的verilog实现_第2张图片

结果分析,当最后一个数据到达完成后,crc_out开始一直往左移位循环,可以直接将crc_out[7]发送出去。

你可能感兴趣的:(简单串行CRC的verilog实现)