文章目录
提示:本文仅供个人学习,未经授权严禁转载。
前言
本文主要分享一个CRC小模块,该模块通过parameter配置可以实现任意的CRC算法。
目的:通过简单的配置parameter来实现任意想要的CRC算法,避免每次在需要不同CRC算法时,从头研究CRC算法的实现,主要为了省事。
意义:通过该模块,可以深刻理解各种CRC算法具体的计算步骤。这个模块也可以作为设计的基础库,在需要使用到CRC算法的地方,调用该模块并配置几个parameter即可。
1. 模块接口和参数说明
1.1 parameter参数
name | description |
---|---|
X | CRC码的位宽。如CRC-16/XMODEM算法,X即16。 |
D | 一个clock cycle计算的数据位宽。 |
POLY | CRC多项式。 |
IV | CRC初值 |
REFIN | 1:输入数据按字节反转。0:不反转。 |
REFOUT | 整个数据是否按位反转。 |
XOROUT | 将REFOUT后的结果和该参数异或后输出。 |
PIPEOUT | 1:将CRC结果打一拍再输出。0:不打拍。 |
1.2 模块接口
name | direction | width | description |
---|---|---|---|
clk | input | 1 | 时钟。 |
rst_n | input | 1 | 复位。 |
init | input | 1 | 在en==1时用IV作为初值计算CRC。 |
en | input | 1 | 使能计算。 |
din | input | D | 输入数据。 |
crcx | output | X | CRC结果。 |
2. 模块使用例程
2.1 CRC-16/XMODEM算法
(1)CRC工具计算
(2)Verilog代码参数配置
parameter X = 16
;parameter D = 32
;parameter POLY = 'h1021
;parameter REFIN = 0
;parameter REFOUT = 0
;parameter IV = 'h0
;parameter XOROUT = 'h0
;parameter PIPEOUT = 1
;
(3)VCS仿真结果
I. 参数D配置为32
II. 参数D配置为16
2.2 CRC-32/MPEG-2算法
(1)CRC工具计算
(2)Verilog代码参数设置
parameter X = 32
;parameter D = 32
;parameter POLY = 'h04C11DB7
;parameter REFIN = 0
;parameter REFOUT = 0
;parameter IV = 'hFFFF_FFFF
;parameter XOROUT = 'h0
;parameter PIPEOUT = 1
;
(3)VCS仿真结果
2.3 自定义CRC算法
(1)CRC工具计算
(2)Verilog代码参数设置
parameter X = 23
;parameter D = 32
;parameter POLY = 'h7A1035
;parameter REFIN = 1
;parameter REFOUT = 1
;parameter IV = 'h5A5A5A
;parameter XOROUT = 'h050505
;parameter PIPEOUT = 1
;
(3)VCS仿真结果
3. CRC IP Verilog代码
(1) crcx_d1.v
module crcx_d1 #(
parameter X = 16 , // 8, 16, 32 correspond to crc8, crc16, crc32;
parameter poly = 16'h1021 // crc polynomial
)(
input serial_in ,
input [X-1:0] crc_pre ,
output [X-1:0] crc
);
generate if (X==8) begin : gen_crc8_d1
wire new_lsb = crc_pre[7] ^ serial_in;
assign crc[0] = new_lsb;
assign crc[1] = crc_pre[0] ^ (poly[1] & new_lsb);
assign crc[2] = crc_pre[1] ^ (poly[2] & new_lsb);
assign crc[3] = crc_pre[2] ^ (poly[3] & new_lsb);
assign crc[4] = crc_pre[3] ^ (poly[4] & new_lsb);
assign crc[5] = crc_pre[4] ^ (poly[5] & new_lsb);
assign crc[6] = crc_pre[5] ^ (poly[6] & new_lsb);
assign crc[7] = crc_pre[6] ^ (poly[7] & new_lsb);
end
else if (X==16) begin : gen_crc16_d1
wire new_lsb = crc_pre[15] ^ serial_in;
assign crc[0] = new_lsb;
assign crc[1] = crc_pre[0