PRBS生成电路:LFSR结构、多项式选择、初始种子设置
做高速串行测试这么多年,我越来越觉得PRBS这个东西,就像是数字世界的“噪声发生器”,听起来简单,但选不对多项式、设不对种子,后面测出来的误码率全是虚假的。这一章咱们把它的“心脏”——LFSR,彻底拆开看看。
LFSR:说白了就是一个带反馈的移位寄存器
线性反馈移位寄存器,名字听着唬人,其实核心就三部分:
- 移位寄存器链:一串D触发器手拉手排好队
- 反馈抽头:从特定级把信号引出来
- 异或门:把抽头信号异或后喂回输入端
为什么叫“线性”?因为反馈网络只用了异或运算。异或是线性运算,没有与门、或门。这个特性决定了PRBS序列的数学性质很干净,好分析,也好生成。
我习惯把LFSR分成两类:斐波那契型(外部反馈)和伽罗瓦型(内部反馈)。后者速度更快,因为异或门嵌在寄存器之间,没有很长的组合逻辑路径。
| 对比项 | 斐波那契型 | 伽罗瓦型 |
|---|---|---|
| 反馈结构 | 所有抽头异或后送到第一级 | 抽头位置就地异或后传下一级 |
| 关键路径 | 异或门数量多,路径长 | 每个时钟只有一级异或 |
| 适用场景 | 低速,容易理解 | 高速,我的首选 |
我的小习惯:做25Gbps以上速率时,我一定用伽罗瓦型。你想想看,斐波那契型那个大异或树,稍微一不留神就卡时序了。
多项式选择——不是随便找个多项式就能用
LFSR能产生的序列长度由本原多项式决定。本原多项式是啥?说白了就是能让LFSR走遍除全零外所有状态的“素数级”多项式。
以PRBS7为例,它的生成多项式是 x⁷ + x⁶ + 1。7表示用7级寄存器,生成的序列长度是 2⁷ – 1 = 127 bit。多出的那1bit去哪了?全零状态被跳过了,因为LFSR进了全零就出不来了。
工程上常用的几个多项式我列在下面:
| 名称 | 生成多项式 | 序列长度 | 典型用途 |
|---|---|---|---|
| PRBS7 | x⁷ + x⁶ + 1 | 127 bit | SATA, PCIe 1.0 |
| PRBS15 | x¹⁵ + x¹⁴ + 1 | 32767 bit | 10G以太网 |
| PRBS23 | x²³ + x¹⁸ + 1 | 8388607 bit | FC (光纤通道) |
| PRBS31 | x³¹ + x²⁸ + 1 | 2.15×10⁹ bit | PCIe 3.0/4.0, 25G/50G |
我曾经吃过亏:在某个12.5Gbps项目中,随手选了个非本原多项式,结果序列长度缩了30%。误码率测出来异常高,折腾了两天才发现是多项式没选对。所以记住了:只选本原多项式,别自己瞎编。
你做测试码型发生器时怎么选?我的经验是:先看标准文档。IEEE 802.3、OIF-CEI、PCI-SIG都有明确的PRBS阶数和多项式定义。别自己发明,跟着标准走最省心。
初始种子设置——这个坑很多人跳过
种子,就是LFSR一开始寄存器的值。它不影响序列的结构,但决定序列的“相位”。
有一个铁律:种子不能是全零。为什么?你想,全零状态下异或结果永远是0,反馈回去还是0,LFSR就“原地踏步”了。
工程上常用的种子:
// PRBS7 常用种子:0x01 (二进制 0000001)
// PRBS31 常用种子:0x7FFFFFFF
// Verilog 示例
reg [30:0] lfsr = 31'h7FFFFFFF; // 所有位为1,也常用
reg [6:0] lfsr = 7'b0000001; // 最低位为1,其余为0
种子的关键作用:在测试场景中,发送端和接收端必须用同一个种子。否则接收端生成的本地PRBS序列跟收到的序列对不上号,误码率计算全是错的。
还有个进阶玩法:种子对齐。有时候为了方便调试,我会给多通道分别设不同种子,这样通过观察各通道的锁定时间差,就能判断接收端是否工作正常。
这张图展示的是PRBS7的伽罗瓦型结构。看箭头:D6输出同时分两路,一路直接输出作为PRBS序列,一路向下跟D5的抽头做异或后反馈回去。这就是“内部反馈”的精髓。