首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >伪随机二进制序列

伪随机二进制序列
EN

Code Review用户
提问于 2021-11-26 12:59:20
回答 1查看 1K关注 0票数 2

给出了产生伪随机比特序列的FPGA模块.第一个模块产生一个位序列。第三模块通过将总线传输到例如由更快的设备控制的复用器来加速生成。因此,这个总线被序列化为一个位序列。

prbs.sv

代码语言:javascript
复制
`timescale 1ns / 1ps

module prbs #
(
       parameter integer PN = 7 //3, 4, 5, 6, 7, 9, 11, 15, 17, 23, 31, 32, 36, 41
)
(
    input  logic i_clk,
    input  logic i_s_rst_n,
    input  logic i_en,

    output logic o_prbs,
    output logic o_prbs_n
);
    localparam integer TAP_1 = (PN == 3) ? 2 :
                               (PN == 4) ? 3 :
                               (PN == 5) ? 4 :
                               (PN == 6) ? 5 :
                               (PN == 7) ? 6 :
                               (PN == 9) ? 7 :
                               (PN == 11) ? 10 :
                               (PN == 15) ? 14 :
                               (PN == 17) ? 16 :
                               (PN == 23) ? 22 :
                               (PN == 31) ? 30 :
                               (PN == 32) ? 31 :
                               (PN == 36) ? 35 :
                               (PN == 41) ? 40 : 0;

    localparam integer TAP_0 = (PN == 3) ? 0 :
                               (PN == 4) ? 2 :
                               (PN == 5) ? 2 :
                               (PN == 6) ? 4 :
                               (PN == 7) ? 0 :
                               (PN == 9) ? 4 :
                               (PN == 11) ? 8 :
                               (PN == 15) ? 0 :
                               (PN == 17) ? 2 :
                               (PN == 23) ? 17 :
                               (PN == 31) ? 27 :
                               (PN == 32) ? 21 :
                               (PN == 36) ? 24 :
                               (PN == 41) ? 37 : 0;

    logic [PN - 1 : 0] lfsr; 

    always_comb begin
        o_prbs   = lfsr[PN - 1];
        o_prbs_n = ~lfsr[PN - 1];
    end                       

    always_ff @ (posedge i_clk) begin
        if (i_s_rst_n == 1'h0) begin
            lfsr <= '1;
        end
        else if (i_en == 1'h1) begin
            lfsr <= {lfsr[PN - 2 : 0], lfsr[TAP_1] ^ lfsr[TAP_0]};
        end
    end
endmodule

prbs_tb.sv

代码语言:javascript
复制
`timescale 1ns / 1ps

module prbs_tb; 
    localparam integer PN             = 7; //3, 4, 5, 6, 7, 9, 11, 15, 17, 23, 31, 32, 36, 41
    localparam integer PERIOD         = 2 ** PN;

    localparam integer CLOCK_PERIOD   = 100;

    localparam integer TEST_ITERATION = 1000;
    localparam integer CHANGE_EN_VAL  = 100;

    logic clk     = '0;
    logic s_rst_n = '0;
    logic en      = '0;
    logic prbs    = '0;
    logic prbs_n  = '0;

    integer tick = 0;

    prbs #
    (
        .PN (PN)
    )
    prbs_dut
    (
        .i_clk     (clk    ),
        .i_s_rst_n (s_rst_n),
        .i_en      (en     ),

        .o_prbs    (prbs   ),
        .o_prbs_n  (prbs_n )
    );

    initial begin
        forever begin
            #( CLOCK_PERIOD / 2 ) clk = !clk;
        end 
    end

    initial begin
        s_rst_n <= '0;
        @(posedge clk);

        s_rst_n <= '1;
        en      <= '1;
        @(posedge clk);

        for(int i = 0; i < TEST_ITERATION; i++) begin
            if ((i % PERIOD) == (PERIOD - 1)) begin
                en   <= ~en;
                tick = 0;
            end
            else begin
                tick++;
            end

            @(posedge clk);
        end

        $finish;
    end
endmodule

prbs_wide.sv

代码语言:javascript
复制
    `timescale 1ns / 1ps
    
    module prbs_wide #
    (
        parameter integer PN = 7, //3, 4, 5, 6, 7, 9, 11, 15, 17, 23, 31, 32, 36, 41
        parameter integer WIDTH = 16
    )
    (
        input  logic                 i_clk,
        input  logic                 i_s_rst_n,
        input  logic                 i_en,
    
        output logic [WIDTH - 1 : 0] o_prbs,
        output logic [WIDTH - 1 : 0] o_prbs_n
    );
        localparam integer TAP_1 = (PN == 3) ? 2 :
                                   (PN == 4) ? 3 :
                                   (PN == 5) ? 4 :
                                   (PN == 6) ? 5 :
                                   (PN == 7) ? 6 :
                                   (PN == 9) ? 7 :
                                   (PN == 11) ? 10 :
                                   (PN == 15) ? 14 :
                                   (PN == 17) ? 16 :
                                   (PN == 23) ? 22 :
                                   (PN == 31) ? 30 :
                                   (PN == 32) ? 31 :
                                   (PN == 36) ? 35 :
                                   (PN == 41) ? 40 : 0;
    
        localparam integer TAP_0 = (PN == 3) ? 0 :
                                   (PN == 4) ? 2 :
                                   (PN == 5) ? 2 :
                                   (PN == 6) ? 4 :
                                   (PN == 7) ? 0 :
                                   (PN == 9) ? 4 :
                                   (PN == 11) ? 8 :
                                   (PN == 15) ? 0 :
                                   (PN == 17) ? 2 :
                                   (PN == 23) ? 17 :
                                   (PN == 31) ? 27 :
                                   (PN == 32) ? 21 :
                                   (PN == 36) ? 24 :
                                   (PN == 41) ? 37 : 0;
    
        logic [PN - 1 : 0] lfsr;
        logic [PN - 1 : 0] r_lfsr;  
        logic [WIDTH - 1 : 0] tmp;  
        
        always_comb begin
            lfsr = r_lfsr;
    
            for (int i = WIDTH - 1; i >= 0; i = i - 1) begin
                lfsr   = {lfsr[PN - 2 : 0], lfsr[TAP_1] ^ lfsr[TAP_0]};
                tmp[i] = lfsr[TAP_1] ^ lfsr[TAP_0];
            end
        end                 
    
        always_ff @ (posedge i_clk) begin
            if (i_s_rst_n == 1'h0) begin
                r_lfsr   <= '1;
    
                o_prbs   <= '0;
                o_prbs_n <= '1;
            end
            else if (i_en == 1'h1) begin
                r_lfsr <= lfsr;
    
                o_prbs   <= tmp;
                o_prbs_n <= ~tmp;
            end
        end
    endmodule

prbs_wide_tb.sv

代码语言:javascript
复制
`timescale 1ns / 1ps

module prbs_wide_tb;
    localparam integer PN             = 7;
    localparam integer PERIOD         = 2 ** PN - 1;
    localparam integer WIDTH          = 128;

    localparam integer CLOCK_PERIOD   = 100;

    localparam integer TEST_ITERATION = 1000;
    localparam integer CHANGE_EN_VAL  = 100;

    logic                 clk     = '0;
    logic                 s_rst_n = '0;
    logic                 en      = '0;

    logic [WIDTH - 1 : 0] prbs    = '0;
    logic [WIDTH - 1 : 0] prbs_n  = '0;

    prbs_wide #
    (
        .PN    (PN   ),
        .WIDTH (WIDTH)
    )
    prbs_wide_dut
    (
        .i_clk     (clk    ),
        .i_s_rst_n (s_rst_n),
        .i_en      (en     ),

        .o_prbs    (prbs   ),
        .o_prbs_n  (prbs_n )
    );

    initial begin
        forever begin
            #( CLOCK_PERIOD / 2 ) clk = !clk;
        end 
    end

    initial begin
        s_rst_n <= '0;
        @(posedge clk);

        s_rst_n <= '1;
        en      <= '1;
        @(posedge clk);

        for(int i = 0; i < TEST_ITERATION; i++) begin        
            if ((i % PERIOD) == PERIOD - 1) begin
                en <= ~en;
            end
            @(posedge clk);
        end

        $finish;
    end
endmodule
EN

回答 1

Code Review用户

回答已采纳

发布于 2021-11-27 13:03:31

我在两个不同的模拟器(Cadence和Synopsys)上从testbench中的这两行获得编译错误:

代码语言:javascript
复制
logic prbs    = '0;
logic prbs_n  = '0;

由于将这些信号连接到模块实例输出端口,因此不应将它们设置为声明行中的任何值。您的代码有多个信号驱动程序:

  1. 模块实例输出端口。
  2. logic声明的连续驱动程序。

只需在没有赋值的情况下声明信号:

代码语言:javascript
复制
logic prbs  ;
logic prbs_n;

除此之外,我不认为您的代码有任何其他功能问题。布局遵循良好的编码实践,您可以很好地利用参数。

在测试平台中,您可以利用2状态信号类型。这可能会带来更好的模拟性能,也能更好地传达代码的意图。由于不需要为实例输入驱动xz,所以可以使用bit而不是logic

代码语言:javascript
复制
bit clk;
bit s_rst_n;
bit en;

由于所有的2状态类型默认为0,因此不需要在声明或其他地方显式地将它们初始化为0。这纯粹是一个方便和偏爱的问题。对于testbench计数器,情况类似:

代码语言:javascript
复制
int tick;

您可以使用一行代码简化您的时钟:

代码语言:javascript
复制
always #( CLOCK_PERIOD / 2 ) clk = !clk;

在您的设计中,您可以简化组合逻辑如下。更改:

代码语言:javascript
复制
always_comb begin
    o_prbs   = lfsr[PN - 1];
    o_prbs_n = ~lfsr[PN - 1];
end                       

相当于:

代码语言:javascript
复制
assign o_prbs   = lfsr[PN - 1];
assign o_prbs_n = ~o_prbs;

这避免了重复lfsr表达式。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/270417

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档