作者:Jacky Gao,AMD开发者;来源:AMD开发者社区
本文通过用RTL实现Fibonacci LSFR,对DDR实现误码率测试。并在RTL中实现注入错误码元的功能,模拟误码的情况。此功能可以推广至GT等高速数据总线的BERT测试。
简介
线性反馈移位寄存器(Linear feedback shift register,LFSR)是指给定前一状态的输出,将该输出的线性函数再用作输入的移位寄存器。最常见的运算是异或,即对寄存器的某些位进行异或操作后作为输入,然后进行整体移位。
线性反馈移位寄存器的运算是确定性的,所生成的数据流完全决定于寄存器当时或者之前的状态。其输出的状态是有限的,最终一定会循环。然而,通过本原多项式,线性反馈移位寄存器可以生成看起来是随机的且循环周期非常长的序列。
Fibonacci LFSRs
首先介绍三个重要的概念,
LFSR,线性反馈移位寄存器,通过移位操作用来在生成数据流。
Tap,即抽头,一般指定进行逻辑运算的寄存器数据位。
Seed,即种子,指的是在进行生成PRBS码时的初始值。
LFSR最右端的比特为输出比特。抽头依次与输出比特进行异或运算,然后反馈回最左端的位。最右端位置所生成的序列被称为输出流,赋给寄存器的初始值叫做“种子 “,影响下一个状态的比特位叫做抽头。
例如在下图中,抽头序列为[9,5],分别在第9,5个比特位,则相应的特征多项式为。
BERT
误码率测试仪(Bit Error Rate Tester,BERT),常用于高速数字通信链路的仿真和测试,用来模拟真实的数据流。
RTL实现
下面我们用RTL实现PRBS和BERT,并在PRBS中加入注入error的功能,模拟传输过程中误码的的情景。
prbs的实现
除了实现LFSR序列,我们还在端口中加入errror信号 ,在有效时我们会在发生序列中加入一位误码。实现的代码如下:
if (ENA_i === 1'b 1 && READY_i === 1'b 1) begin shift_data = shift_reg; for (i = 0; i <= DW - 1; i = i + 1) begin feedback = shift_data[LENGTH - 1]; for (j = 0; j <= LENGTH - 2; j = j + 1) begin if (TAPS[j] === 1'b 1) feedback = feedback ^ shift_data[j]; end shift_data = {shift_data[30:0], feedback}; if (i === 0 & error === 1'b 1) begin DATA_o[DW - 1 - i] <= ~shift_data[LENGTH - 1]; error <= 1'b 0; end else DATA_o[DW - 1 - i] <= shift_data[LENGTH - 1]; end shift_reg <= shift_data; end
bert的实现
BERT模块以当前的输入数据作为种子,通过抽头计算LSFR序列,并与后面的数据按位比较。
我们通过ERROR_COUNT和WORD_COUNT分别输出检测到的误码和总共的码元数,这样顶层的模块可以计算出实际的误码率。
if(VALID_i === 1'b 1) begin shift_data = shift_reg; errors = 6'b 0; for (i = 0; i <= DW - 1; i = i + 1) begin feedback = shift_data[LENGTH-1]; for (j = 0; j <= LENGTH - 2; j = j + 1) if (TAPS[j] == 1'b 1) feedback = feedback ^ shift_data[j]; shift_data = {shift_data[30:0], feedback}; if (data_reg[DW-1-i] != shift_data[LENGTH-1]) errors = errors + 1; end shift_reg <= shift_data; if (error_count[32] == 1'b 0) begin error_count <= error_count + errors; ERROR_COUNT_o <= error_count[31:0]; end else ERROR_COUNT_o <= {32{1'b 1}}; if (word_count[32] == 1'b 0) begin word_count <= word_count + 1; WORD_COUNT_o <= word_count[31:0]; end else WORD_COUNT_o <= {32{1'b 1}}; end
测试结果
我们以MIG为例,在Vivado中创建MIG的参考工程,然后修改顶层example_top模块,添加prbs和bert的实例,并在固定的时间注入误码。
通过下面的仿真结果可以看到,bert正确检测到了两次注入的误码,并把误码累加器递增。
完整的测试工程请参考附件。所有的代码都是可以综合的,可以实际上板测试。