Modules for FPGAs for generating a pseudo-random bit sequence are presented. The first module generates a bit sequence. The third module speeds up the generation by transferring the bus to, for example, a multiplexer which is controlled by a faster device. Hence this bus is serialized into a bit sequence.
prbs.sv
`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
`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
`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
`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