Menu Close

Verilog中function在PRBS方面的应用

作者:图图,庄乾起,Yvonne

Verilog编程时,使用function可以将可被复用的组合逻辑功能提取出来,使代码易于参数化,也便于维护。因此在许多的代码复用设计中都采用了function 调用的方式实现,特别是有一定功能的函数发生器。下面以二进制伪随机序列生成器为例介绍function调用在参数化设计中的应用。

举例如下:
PRBS(Pseudo-random Binary Sequence)通过一个生成多项式产生伪随机数据,特别适合FPGA中通信加密处理。

一般来说,PRBS由LFSR(linear feedback shift register,线性反馈移位寄存器)生成。在生成过程中,数据进行移位及异或操作。

这里以16-bit数据为例。原始数据为data = 16’b1000_0111_0011_0101。

对第11,13,14和16位进行异或的操作,其对应的反馈多项式(模2)为fed_poly = x^{16}+x^{14}+x^{13}+x^{11}+1 。注意:反馈多项式里的’1′(或 x^{0})不表示相对应位的异或,表示异或结果对第一位的输入

其对应的反馈数为fed_poly = 17’b1011_0100_0000_0000_1,fed_poly[16:1] = 16’b1011_0100_0000_0000。那么将描述图1所示的过程可以表达为:

^ ( data & fed_poly[16:1] ) = ^(16’b1000_0111_0011_0101  &  16’b1011_0100_0000_0000)

如果是每次向左进行移一位操作的话,那么最终的表达式result为

result = { data[15:1],^ ( data & fed_poly[16 : 1] )};

如果是每次向右进行移一位操作的话,那么最终的表达式result为

result = { ^ ( data & fed_poly[16 :1] ),data[15:1]};

%title插图%num

图1 将原始多项式相应的位进行异或[1]

 

通过Verilog中function的巧妙运用,可并行实现参数化数据位宽的PRBS,模块化的设计可以被之后复用。

引用代码(部分代码有修改和注释)如下:

module prbs_gen
#(
parameter C_DWIDTH = 16 ,
parameter C_PRIMPOLY = 17’b1_0001_0000_0000_1011,   //反馈多项式
parameter C_POLY_WIDTH = 16
)
(
    input                                       I_clk ,
    input [C_POLY_WIDTH-1:0] I_init ,
    input                                       I_init_v ,
    input                                       I_prbs_en ,

    output reg [C_DWIDTH-1:0]                   O_prbs ,
    output reg                                  O_prbs_v
);

//————-generation polynomial—————-
//4: X^4+X^1+1
//5: X^5+X^2+1
//6: X^6+X^1+1
//7: X^7+X^3+1
//8: X^8+X^4+X^3+X^2+1
//9: X^9+X^4+1
//10: X^10+X^3+1
//11: X^11+X^2+1
//12: X^12+X^6+X^4+X^1+1
//13: X^13+X^4+X^3+X^1+1
//14: X^14+X^10+X^6+X^1+1
//15: X^15+X^1+1
//16: X^16+X^12+X^3+X^1+1
//———————————————-

//这里生成的16-bit随机数列,使用的是“16: X^16+X^12+X^3+X^1+1”,对应的反馈多项式C_PRIMPOLY = 17’b1_0001_0000_0000_1011
reg [C_POLY_WIDTH-1:0] S_prbs_reg;
wire [C_POLY_WIDTH-1:0] S_reg_sel;

assign S_reg_sel = I_init_v  ?  I_init : S_prbs_reg;

always @(posedge I_clk)
begin
    if(I_prbs_en)
    begin
        S_prbs_reg <= F_prbs_reg(S_reg_sel);          //调用函数
        O_prbs <= S_reg_sel;                          //输出生成的随机数
    end
    O_prbs_v <= I_prbs_en;
end

//这里是函数的定义
function [C_POLY_WIDTH-1:0] F_prbs_reg;
input [C_POLY_WIDTH-1:0] S_cal_init;
integer F_i;
begin
    F_prbs_reg = S_cal_init;         //传入初始值
    for( F_i = 0 ; F_i < C_DWIDTH ; F_i = F_i + 1 )
    F_prbs_reg = {^(F_prbs_reg & C_PRIMPOLY[C_POLY_WIDTH:1]),F_prbs_reg[C_POLY_WIDTH-1:1]};         
    //LFSR方法生成, 主要通过异或和移位
end
endfunction

endmodule

代码来源:Xilinx论坛 > 资源分享区,链接:https://forums.xilinx.com/t5/%E8%B5%84%E6%BA%90%E5%88%86%E4%BA%AB%E5%8C%BA/%E5%88%86%E4%BA%AB-verilog-function%E7%9A%84%E4%BD%BF%E7%94%A8/td-p/1230626

注:本文采纳IC知识库 论坛中 图图的文章

[1] “Linear-feedback shift register,” Wikiwand. [Online]. Available: https://www.wikiwand.com/en/Linear-feedback_shift_register. [Accessed: 13-Aug-2021].

Posted in FPGA, Verilog, Verilog, 开发语言, 教材与教案, 编程语言

2 Comments

  1. AntsUnderLeaf

    对初学者而言PRBS还需要百度一下,百度完也不能一下明白其中的所以然,这里直接对PRBS操作,感觉给代码加点注释会比较友好一点,而且还可以帮助我们了解PRBS。看起来会有点困难,,而且代码格式没有缩进,看起来会比较难受

发表评论

相关链接