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 / 1psmodule 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 endendmoduleprbs_tb.sv
`timescale 1ns / 1psmodule 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; endendmoduleprbs_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 endmoduleprbs_wide_tb.sv
`timescale 1ns / 1psmodule 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; endendmodule1 Answer1
I get compile errors on 2 different simulators (Cadence and Synopsys) from these 2 lines in the testbench:
logic prbs = '0;logic prbs_n = '0;Since you connect those signals to the module instance output ports, you should not set them to any value in the declaration lines. Your code has multiple drivers of the signals:
- The module instance output port.
- The continuous driver of your
logicdeclaration.
Just declare the signals without an assignment:
logic prbs ;logic prbs_n;Aside from that, I do not see any other functional problems with your code. The layout follows good coding practices, and you make good use of parameters.
In the testbench, you could take advantage of 2-state signal types. This could lead to better simulation performance, and it also better conveys the intent of your code. Since there is no need to drivex orz for your instance inputs, you can usebit instead oflogic:
bit clk;bit s_rst_n;bit en;Since all 2-state types default to 0, there is no need to explicitly initialize them to 0 in the declaration or elsewhere. This is purely a matter of convenience and preference. The situation is similar for your testbench counter:
int tick;You could simplify your clock using a single line of code:
always #( CLOCK_PERIOD / 2 ) clk = !clk;In your design, you could simplify the combinational logic as follows. Change:
always_comb begin o_prbs = lfsr[PN - 1]; o_prbs_n = ~lfsr[PN - 1];endto the equivalent:
assign o_prbs = lfsr[PN - 1];assign o_prbs_n = ~o_prbs;This avoids repeating thelfsr expression.
- \$\begingroup\$Thanks for your comments, I really appreciate it. Based on the comments , the code has been fixed. I commit the code to a new question. Once again thank you!\$\endgroup\$Drakonof– Drakonof2021-12-06 07:34:38 +00:00CommentedDec 6, 2021 at 7:34
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.

