这是时序逻辑,转换成组合逻辑就是当前寄存器的值等于之前寄存器的值和当前输入做运算,用变量init来表示寄存器初始值,然后做8次迭代,
crc[0] = init[3] ^ data ;
crc[1] = init[0] ^ init[3] ^ data;
crc[2] = init[1];
crc[3] = init[2];
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
为了方便,在crc后面用迭代次数-1表示,那么第1次迭代:输入数据的最高位data[7]和上一轮的LFSR寄存器值(因为才开始,所以是初始值)做异或运算。
data[7]:
crc7[0] = init[3] ^ data[7] ;
crc7[1] = init[0] ^ init[3] ^ data[7];
crc7[2] = init[1];
crc7[3] = init[2];
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
同理,有第2次迭代:输入数据的次高位data[6]和上一轮的LFSR寄存器值(即crc7变量)做异或运算。
data[6]:
crc6[0] = crc7[3] ^ data[6] = init[2] ^ data[6];
crc6[1] = crc7[0] ^ crc7[3] ^ data[6] = init[3] ^ data[7] ^ init[2] ^ data[6];
crc6[2] = crc7[1] = init[0] ^ init[3] ^ data[7];
crc6[3] = crc7[2] = init[1];
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
直到第8次迭代,输入最后一个数据:
data[5]:
crc5[0] = crc6[3] ^ data[5] = init[1] ^ data[5];
crc5[1] = crc6[0] ^ crc6[3] ^ data[5] = init[2] ^ data[6] ^ init[1] ^ data[5];
crc5[2] = crc6[1] = init[3] ^ data[7] ^ init[2] ^ data[6];
crc5[3] = crc6[2] = init[0] ^ init[3] ^ data[7];
data[4]:
crc4[0] = crc5[3] ^ data[4] = init[0] ^ init[3] ^ data[7] ^ data[4]
crc4[1] = crc5[0] ^ crc5[3] ^ data[4] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4];
crc4[2] = crc5[1] = init[2] ^ data[6] ^ init[1] ^ data[5];
crc4[3] = crc5[2] = init[3] ^ data[7] ^ init[2] ^ data[6];
data[3]:
crc3[0] = crc4[3] ^ data[3] = init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3]
crc3[1] = crc4[0] ^ crc4[3] ^ data[3] = init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3]
crc3[2] = crc4[1] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4];
crc3[3] = crc4[2] = init[2] ^ data[6] ^ init[1] ^ data[5];
data[2]:
crc2[0] = crc3[3] ^ data[2] = init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2]
crc2[1] = crc3[0] ^ crc3[3] ^ data[2] = init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2]
crc2[2] = crc3[1] = init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3]
crc2[3] = crc3[2] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4]
data[1]:
crc1[0] = crc2[3] ^ data[1] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ data[1]
crc1[1] = crc2[0] ^ crc2[3] ^ data[1] = init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2] ^ init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ data[1]
crc1[2] = crc2[1] = init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2]
crc1[3] = crc2[2] = init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3]
data[0]:
crc0[0] = crc1[3] ^ data[0] = init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ data[0]
= init[0] ^ data[4] ^ init[2] ^ data[6] ^ data[3] ^ data[0]
crc0[1] = crc1[0] ^ crc1[3] ^ data[0] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ data[1] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ data[0]
= init[1] ^ data[5]^ init[3] ^ data[4] ^ data[1]^ data[7] ^ data[4] ^ init[2] ^ data[6] ^ data[3] ^ data[0]
crc0[2] = crc1[1] = init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2] ^ init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ data[1]
crc0[3] = crc1[2] = init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2]
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
把crc0的表达式整理一下:
crc0[0] = data[6] ^ data[4] ^ data[3] ^ data[0] ^ init[0] ^ init[2];
crc0[1] = data[7] ^ data[6] ^ data[5] ^ data[1] ^ data[3] ^ data[0] ^ init[1] ^ init[2] ^ init[3];
crc0[2] = data[7] ^ data[6] ^ data[4] ^ data[2] ^ data[1] ^ init[0] ^ init[2] ^ init[3];
crc0[3] = data[7] ^ data[5] ^ data[3] ^ data[2] ^ init[1] ^ init[3];
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
和这个网站http://crctool.easics.be/用工具生成的代码(核心部分)做对比,二者结果一致。
newcrc[0] = data[6] ^ data[4] ^ data[3] ^ data[0] ^ crc[0] ^ crc[2];
newcrc[1] = data[7] ^ data[6] ^ data[5] ^ data[3] ^ data[1] ^ data[0] ^ crc[1] ^ crc[2] ^ crc[3];
newcrc[2] = data[7] ^ data[6] ^ data[4] ^ data[2] ^ data[1] ^ crc[0] ^ crc[2] ^ crc[3];
newcrc[3] = data[7] ^ data[5] ^ data[3] ^ data[2] ^ crc[1] ^ crc[3];
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
接着编写并行CRC-8的代码:
//并行CRC-8:宽度8,多项式0x07(x^8+x^2+x+1),初始值00,XOROUT00,REFIN/REFOUT均为FALSE
module test(
input clk, //时钟
input rst, //异步复位
input [7:0] pal_in, //并行8位输入数据
input pal_in_val, //并行输入数据有效
output [7:0] crc_data, //CRC校验数据
output crc_data_val //CRC校验数据有效
);
//定义寄存器变量
reg [7:0] crc; //CRC校验数据
reg data_val; //CRC校验数据输出有效信号
localparam CRC_INIT = 8'd0; //LFSR寄存器初始值
//连接端口
assign crc_data = crc;
assign crc_data_val = data_val;
//并行电路使用函数来构造
function [7:0] CRC8;
input [7:0] data; //被校验数据
input [7:0] crc_init; //寄存器初值
begin
CRC8[0] = data[7] ^ data[6] ^ data[0] ^ crc_init[0] ^ crc_init[6] ^ crc_init[7];
CRC8[1] = data[6] ^ data[1] ^ data[0] ^ crc_init[0] ^ crc_init[1] ^ crc_init[6];
CRC8[2] = data[6] ^ data[2] ^ data[1] ^ data[0] ^ crc_init[0] ^ crc_init[1] ^ crc_init[2] ^ crc_init[6];
CRC8[3] = data[7] ^ data[3] ^ data[2] ^ data[1] ^ crc_init[1] ^ crc_init[2] ^ crc_init[3] ^ crc_init[7];
CRC8[4] = data[4] ^ data[3] ^ data[2] ^ crc_init[2] ^ crc_init[3] ^ crc_init[4];
CRC8[5] = data[5] ^ data[4] ^ data[3] ^ crc_init[3] ^ crc_init[4] ^ crc_init[5];
CRC8[6] = data[6] ^ data[5] ^ data[4] ^ crc_init[4] ^ crc_init[5] ^ crc_init[6];
CRC8[7] = data[7] ^ data[6] ^ data[5] ^ crc_init[5] ^ crc_init[6] ^ crc_init[7];
end
endfunction
//当输入有效时进行CRC校验
always @(posedge clk or posedge rst)begin
if(rst)
crc <= 8'd0;
else if(pal_in_val) //输入有效时
crc <= CRC8(pal_in,CRC_INIT); //校验结果落后一拍
end
//在输入数据有效的下一个周期输出有效
always @(posedge clk or posedge rst)begin
if(rst)
data_val <= 0;
else if(pal_in_val)
data_val <= 1;
else
data_val <= 0; //其他时间均为低电平
end
endmodule
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
测试逻辑和上面的串行CRC一样:依次输入0~255这256个数据,观察CRC校验结果:
`timescale 1ns/1ns
module tb_test();
//信号声明
reg clk;
reg rst;
reg [7:0] pal_in;
reg pal_in_val;
wire[7:0] crc_data;
wire crc_data_val;
//被测模块实例化
test inst_test(
.clk (clk ), //时钟信号
.rst (rst ), //时钟信号
.pal_in (pal_in ), //串行输入数据
.pal_in_val (pal_in_val ), //串行输入数据有效信号
.crc_data (crc_data ),
.crc_data_val (crc_data_val)
);
//生成时钟信号
initial begin
clk = 1'b0;
forever #5 clk = ~clk;
end
//生成复位信号
initial begin
rst = 1'b1; //复位
#40 rst = 1'b0; //取消复位
end
//生成输入数据与时钟使能信号
always @(posedge clk or posedge rst)begin
if(rst)begin
pal_in <= 255;
pal_in_val <= 0;
end
else begin
pal_in <= pal_in + 1;
pal_in_val <= 1;
end
end
//仿真过程
initial begin
#1000 $stop; //关闭仿真
end
endmodule
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
仿真结果如下,CRC校验结果依次输出00-07-0e-09······,与正确结果对比后,发现仿真无误。

initial begin
rst = 1'b1; //复位
#40 rst = 1'b0; //取消复位
end
//生成输入数据与时钟使能信号
always @(posedge clk or posedge rst)begin
if(rst)begin
pal_in <= 255;
pal_in_val <= 0;
end
else begin
pal_in <= pal_in + 1;
pal_in_val <= 1;
end
end
//仿真过程
initial begin
#1000 $stop; //关闭仿真
end
endmodule
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
仿真结果如下,CRC校验结果依次输出00-07-0e-09······,与正确结果对比后,发现仿真无误。

- 📣您有任何问题,都可以在评论区和我交流📃!
- 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
- 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!
data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://wuzhikai.blog.csdn.net/article/details/136441181","extend1":"pc","ab":"new"}">>
评论记录:
回复评论: