FPGA教程系列-CRC硬件加速原理深度解析
CRC硬件加速原理
依然开头放上原文,https://mp.weixin.qq.com/s/NGQEtskEjkjMzhiwMcY7Sw
表驱动
应该跟查找表差不多,从表中读出数据。
位到字节的转换,简单的想就是把一位看成一个字节,虽然是个类比的办法,还是不太容易理解,需要反复的琢磨。
重点是:
- 新的最高位只跟当前最高字节的前两位有关系
- 再下一个最高位只跟当前最高字节的前三位有关系
- 总之,第 k 次循环的最高位,只取决于当前最高字节的前 k 位
换一句话说,如果以前8位一个字节来输入的话,进行8次"长除法"的运算结果,只跟这8位有关,那么,根据这8位做出一个查找表,包含了所有的情况,也就是256个结果,可以根据这8位是什么快速的查找结果,然后进行异或,相当于速度提升了8倍。
当然,上述情况成立的前提是XOR 可以提前合并。
不要在那傻傻地循环8次了。因为最高那个字节已经包含了接下来8步所有的操作指令。我们直接看着这个字节,一步到位,把这一连串的XOR变换一次性加上去。
verilog
原始状态:
+----------+------------------------+
| Top Byte | Remaining 24 bits |
+----+-----+-----------+------------+
| |
| 1. Top Byte | 2. 剩下的字节左移
| 只用来 | 空出右边位置
| 查索引 |
v v
+----------+ +------------------------+----------+
| TABLE | | Remaining 24 bits | New Data | <-- 新进来的字节
+----+-----+ +-----------+------------+-----+----+
| | ^
| 查出 "超级修正值" | |
+------------------------+ |
| |
v (进行 XOR) |
+------------------------------------------+
| FINAL REGISTER RESULT |
+------------------------------------------+
CRC硬件算法优化
1、结尾 :零字节本身异或进寄存器(X ^ 0 = X)不会改变值,它们唯一的作用是提供"移位次数",把真实数据的最后几位"推"到最高字节去查表。
2、开头 :开头几个字节主要是为了把初始数据装进寄存器。如果寄存器本来为零,就是简单的移入;如果寄存器非零,初始值会在装入过程中"混合"(异或)一下这些字节,但核心动作还是装入。
数学上的优化:
verilog
r = ((r << 8) | *p++) ^ t[(r >> 24) & 0xFF];
可以转换为:
r = (r << 8) ^ (*p++) ^ t[(r >> 24) & 0xFF]; //本质上就是全异或操作
最终转换为
r=0; while (len--) r = (r<<8) ^ t[(r >> 24) ^ *p++];
既然数据最终都要异或到最高位才能决定查表索引,不如提前把当前输入的数据字节(*p)与寄存器的最高字节(r >> 24)进行异或
文章里说两个表,应该是在时间维度上的不一样,真实物理世界上应该是一个表。
-
旧算法(Augmented) :数据D从最右边(第 0 字节)进入。
- 它要经过 4 次移位才能到达最左边(第 3 字节)去触发计算。
- 旧表处理的是"位于最左边"的情况。
-
新算法(Direct) :数据D刚进来,还没移位呢,我们就想直接查表算它的最终影响。
- 如果你想建立一个表,由"位于最右边的数据D"直接查出"它在 4 次移位后对寄存器的贡献"。
- 那么这个表的内容,确实应该等于 Standard_Table[D] 再经过某种反向推导或者预移位。
- 在这个理论视角下,表是不一样的。
原来的算法是"人(数据)走到了门口(最高位)才查票(查表)";现在的算法是"人还在最后排队,但我把他的票直接传送到门口,和正在出门的人的票混在一起查"。检票处的数据库(表)没变,只是送票的方式变了。
CRC的硬件特性
总体来说,没有太多的疑问。
反射,是为了为了迁就硬件,软件实现通常不选择"把每个输入字节都翻转一遍"(效率太低),而是选择"翻转整个世界"。
-
初始值(Init Value) :
- 通常设为 0xFFFFFFFF 而不是 0。
- 原因:如果初始值为 0,那么消息开头的一连串 0 字节不会让寄存器发生变化(因为 0 ^ 0 = 0)。设置非零初始值可以消除这个"盲区",让开头的 0 也能被检测到。
-
最终异或(Final XOR Value) :
- 在计算结束后,将结果再异或一个常数(如 0xFFFFFFFF)。
- 原因:历史遗留的标准约定,或者是为了取反结果。
Rocksoft™ 模型
| 参数 | 含义 | 示例 (CRC-32 标准) |
|---|---|---|
| WIDTH | 位宽 | 32 |
| POLY | 生成多项式 (省略最高位) | 04C11DB7 |
| INIT | 寄存器初始值 | FFFFFFFF |
| REFIN | 输入字节是否反射 | True (适配硬件) |
| REFOUT | 输出结果是否反射 | True |
| XOROUT | 结果最终异或值 | FFFFFFFF |
| CHECK | 校验值 (输入"123456789"的结果) | CBF43926 |
具体还是以原文为主,这里主要是对原文的一些个人理解,也许有失偏颇,但暂时也只能理解到这里了。