mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
Added PRBS test sequence generator and chekker
This commit is contained in:
parent
8fa82449ed
commit
c189b88688
96
prbs_gen_chk.sv
Normal file
96
prbs_gen_chk.sv
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// prbs_gen_chk.sv
|
||||||
|
// Konstantin Pavlov, pavlovconst@gmail.com
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// INFO ------------------------------------------------------------------------
|
||||||
|
// This module generates or checks a PRBS pattern
|
||||||
|
// See "xapp884" appnote for more info
|
||||||
|
|
||||||
|
// Set paramaters for compliance to ITU-T Recommendation O.150 Section 5
|
||||||
|
//--------------------------------- ------------------------------------------
|
||||||
|
// POLY_LEN POLY_TAP INV_PATTERN | nbr of bit seq. max 0 feedback
|
||||||
|
// | stages length sequence stages
|
||||||
|
//--------------------------------- ------------------------------------------
|
||||||
|
// 7(non standard) 6 false | 7 127 6 6, 7
|
||||||
|
// 9 5 false | 9 511 8 5, 9
|
||||||
|
// 11 9 false | 11 2047 10 9,11
|
||||||
|
// 15 14 true | 15 32767 15 14,15
|
||||||
|
// 20 3 false | 20 1048575 19 3,20
|
||||||
|
// 23 18 true | 23 8388607 23 18,23
|
||||||
|
// 29 27 true | 29 536870911 29 27,29
|
||||||
|
// 31 28 true | 31 2147483647 31 28,31
|
||||||
|
|
||||||
|
|
||||||
|
/* --- INSTANTIATION TEMPLATE BEGIN ---
|
||||||
|
|
||||||
|
prbs_gen_chk #(
|
||||||
|
.WIDTH( 32 ),
|
||||||
|
.CHK_MODE( 0 ),
|
||||||
|
.INV_PATTERN( 1 ),
|
||||||
|
.POLY_LEN( 31 ),
|
||||||
|
.POLY_TAP( 28 )
|
||||||
|
) prbs1 (
|
||||||
|
.clk( clk ),
|
||||||
|
.nrst( nrst ),
|
||||||
|
.en( 1'b1 )
|
||||||
|
.data_in( 0 ),
|
||||||
|
.data_out( d[31:0] )
|
||||||
|
)
|
||||||
|
|
||||||
|
--- INSTANTIATION TEMPLATE END ---*/
|
||||||
|
|
||||||
|
|
||||||
|
module prbs_gen_chk #( parameter
|
||||||
|
WIDTH = 32, // data_in, data_out port width
|
||||||
|
CHK_MODE = 0, // 0 - module is a gen
|
||||||
|
// 1 - module is a chk
|
||||||
|
INV_PATTERN = 1, // invert PRBS bit-wise
|
||||||
|
POLY_LEN = 31, // generator polynomial length
|
||||||
|
POLY_TAP = 28 // generator polynomial tap
|
||||||
|
)(
|
||||||
|
input clk,
|
||||||
|
input nrst,
|
||||||
|
input en,
|
||||||
|
input [(WIDTH-1):0] data_in, // CHK_MODE: data to be checked
|
||||||
|
// ~CHK_MODE: inject error
|
||||||
|
output logic [(WIDTH-1):0] data_out = {WIDTH{1'b1}}
|
||||||
|
// CHK_MODE: error found (checker), LSB is the oldest received bit
|
||||||
|
// ~CHK_MODE: generated prbs pattern, LSB is the oldest-generated bit
|
||||||
|
);
|
||||||
|
|
||||||
|
// considering inversion
|
||||||
|
logic [(WIDTH-1):0] data_in_i;
|
||||||
|
assign data_in_i[(WIDTH-1):0] = (INV_PATTERN)?
|
||||||
|
(~data_in[(WIDTH-1):0]):
|
||||||
|
(data_in[(WIDTH-1):0]);
|
||||||
|
|
||||||
|
logic [(POLY_LEN-1):0] prbs_register = {POLY_LEN{1'b1}}; // LFSR itself
|
||||||
|
logic [WIDTH:0][(POLY_LEN-1):0] shift_table;
|
||||||
|
logic [(WIDTH-1):0] xor_results;
|
||||||
|
|
||||||
|
// generating [POLY_LEN cols]x[WIDTH+1 rows] table by shifting prbs register
|
||||||
|
genvar i;
|
||||||
|
generate
|
||||||
|
assign shift_table[0] = prbs_register[(POLY_LEN-1):0];
|
||||||
|
for (i=0; i<WIDTH; i=i+1) begin : gen1
|
||||||
|
assign xor_results[i] = shift_table[i][POLY_LEN-POLY_TAP] ^ shift_table[i][0];
|
||||||
|
assign shift_table[i+1] = { (CHK_MODE)?(data_in_i[i]):(xor_results[i]),
|
||||||
|
shift_table[i][(POLY_LEN-1):1] };
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if(~nrst) begin
|
||||||
|
data_out[(WIDTH-1):0] <= {WIDTH{1'b1}};
|
||||||
|
prbs_register[(POLY_LEN-1):0] <= {POLY_LEN{1'b1}};
|
||||||
|
end else if (en) begin
|
||||||
|
// taking new bits generated by xor operation
|
||||||
|
data_out[(WIDTH-1):0] <= xor_results[(WIDTH-1):0] ^ data_in_i[(WIDTH-1):0];
|
||||||
|
// storing prbs register
|
||||||
|
prbs_register[(POLY_LEN-1):0] <= shift_table[WIDTH][(POLY_LEN-1):0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
121
prbs_gen_chk_tb.sv
Normal file
121
prbs_gen_chk_tb.sv
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// prbs_gen_chk_tb.sv
|
||||||
|
// Konstantin Pavlov, pavlovconst@gmail.com
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// INFO ------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
module prbs_gen_chk_tb();
|
||||||
|
|
||||||
|
logic clk200;
|
||||||
|
initial begin
|
||||||
|
#0 clk200 = 1'b0;
|
||||||
|
forever
|
||||||
|
#2.5 clk200 = ~clk200;
|
||||||
|
end
|
||||||
|
|
||||||
|
// external device "asynchronous" clock
|
||||||
|
logic clk33;
|
||||||
|
initial begin
|
||||||
|
#0 clk33 = 1'b0;
|
||||||
|
forever
|
||||||
|
#15.151 clk33 = ~clk33;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic rst;
|
||||||
|
initial begin
|
||||||
|
#0 rst = 1'b0;
|
||||||
|
#10.2 rst = 1'b1;
|
||||||
|
#5 rst = 1'b0;
|
||||||
|
//#10000;
|
||||||
|
forever begin
|
||||||
|
#9985 rst = ~rst;
|
||||||
|
#5 rst = ~rst;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
logic nrst;
|
||||||
|
assign nrst = ~rst;
|
||||||
|
|
||||||
|
logic rst_once;
|
||||||
|
initial begin
|
||||||
|
#0 rst_once = 1'b0;
|
||||||
|
#10.2 rst_once = 1'b1;
|
||||||
|
#5 rst_once = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic nrst_once;
|
||||||
|
assign nrst_once = ~rst_once;
|
||||||
|
|
||||||
|
logic [31:0] DerivedClocks;
|
||||||
|
clk_divider #(
|
||||||
|
.WIDTH( 32 )
|
||||||
|
) cd1 (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.nrst( nrst_once ),
|
||||||
|
.ena( 1'b1 ),
|
||||||
|
.out( DerivedClocks[31:0] )
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [31:0] E_DerivedClocks;
|
||||||
|
edge_detect ed1[31:0] (
|
||||||
|
.clk( {32{clk200}} ),
|
||||||
|
.nrst( {32{nrst_once}} ),
|
||||||
|
.in( DerivedClocks[31:0] ),
|
||||||
|
.rising( E_DerivedClocks[31:0] ),
|
||||||
|
.falling( ),
|
||||||
|
.both( )
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [15:0] RandomNumber1;
|
||||||
|
c_rand rng1 (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.rst( rst_once ),
|
||||||
|
.reseed( 1'b0 ),
|
||||||
|
.seed_val( DerivedClocks[31:0] ),
|
||||||
|
.out( RandomNumber1[15:0] )
|
||||||
|
);
|
||||||
|
|
||||||
|
logic start;
|
||||||
|
initial begin
|
||||||
|
#0 start = 1'b0;
|
||||||
|
#100 start = 1'b1;
|
||||||
|
#20 start = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Module under test ==========================================================
|
||||||
|
|
||||||
|
logic [31:0] d1;
|
||||||
|
prbs_gen_chk #(
|
||||||
|
.WIDTH( 32 ),
|
||||||
|
.CHK_MODE( 0 ),
|
||||||
|
.INV_PATTERN( 1 ),
|
||||||
|
.POLY_LEN( 31 ),
|
||||||
|
.POLY_TAP( 28 )
|
||||||
|
) gen (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.nrst( nrst_once ),
|
||||||
|
.en( 1'b1 ),
|
||||||
|
.data_in( {2{RandomNumber1[15:0]}} ),
|
||||||
|
.data_out( d1[31:0] )
|
||||||
|
);
|
||||||
|
|
||||||
|
prbs_gen_chk #(
|
||||||
|
.WIDTH( 32 ),
|
||||||
|
.CHK_MODE( 1 ),
|
||||||
|
.INV_PATTERN( 1 ),
|
||||||
|
.POLY_LEN( 31 ),
|
||||||
|
.POLY_TAP( 28 )
|
||||||
|
) checker (
|
||||||
|
.clk( clk200 ),
|
||||||
|
.nrst( nrst_once ),
|
||||||
|
.en( 1'b1 ),
|
||||||
|
.data_in( d1[31:0] ),
|
||||||
|
.data_out( )
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
Loading…
x
Reference in New Issue
Block a user