Cell Relay Archive

Cell Relay Retreat>List Archive>month:1998-Nov> msg00166



[Date Prev][Date Next][Thread Prev][Thread Next]  
  [Date Index][Thread Index][Author Index][Subject Index]

Re: 8bit PRBS generation & BER Detection?

  • From: "C. M. Heard/VVNET, Inc." <heard@vvnet.com>
  • Date: 27 Nov 1998 23:26:47 GMT

--a0000000000000000000000000000000
Content-Type: TEXT/PLAIN; charset=US-ASCII
Content-Transfer-Encoding: 7Bit

On Mon Nov 23 1998 novice@korea.com wrote:
> 
> Hi,
> 
> I'm implementing BER Tester.
> How can I generate PRBS code in BYTE size of O.151 & O.153, etc?
> 
> And How can I detect Bit Error with BYTE boundary?
> 
> Any Info will be very appreciated.

The attached test program might help ... it is a modification of one
that we have used to count the number of errors in data we received
from a DeskNet OC3port tester set up to send the 2^15-1 PRBS sequence.

In a real BER tester you will, of course, need to have resynchronization
logic which re-seeds the PRBS accumulator whenever the measured error
rate is too high (more than 10%, according to O.151).  The attached test
program does not do this;  it assumes the initial 32 bits of the received
sequence is correct and counts the number of errors in the remainder.

Cordially,

Mike
-- 
C. M. Heard/VVNET, Inc.
heard@vvnet.com

--a0000000000000000000000000000000
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

/* PRBS polynomials */
#define PRBS_2_23_1_POLYNOMIAL  0x00420000UL    /* x^23 + x^18 + 1 */
#define PRBS_2_15_1_POLYNOMIAL  0x00006000UL    /* x^15 + x^14 + 1 */
#define PRBS_2_11_1_POLYNOMIAL  0x00000500UL    /* x^11 + x^9  + 1 */
#define PRBS_2_9_1_POLYNOMIAL   0x00000110UL    /* x^9  + x^5  + 1 */
#define PRBS_2_6_1_POLYNOMIAL   0x00000030UL    /* x^6  + x^5  + 1 */

/* table of matrix products used to update a 32-bit PRBS generator */
static unsigned long prbs_table [4] [256];

/* PRBS generator polarity mask */
static unsigned char polarity_mask;

/* table of weights for 8-bit bytes */
unsigned char weight[256];

/*
 * Generate a parity check for a 32-bit word.
 */
static unsigned long
parity_check (unsigned long prbs_accum) {
    unsigned long mask=1UL, parity=0UL;
    int i;
    for (i = 0;  i < 32;  ++i) {
        parity ^= ((prbs_accum & mask) != 0UL);
        mask <<= 1;
    }
    return parity;
}

/*
 * Generate a table of matrix products to update a 32-bit PRBS generator.
 */
static void
gen_prbs_table (unsigned long polynomial) {
    int i;
    for (i = 0;  i < 4;  ++i) {
        int j;
        for (j = 0;  j < 256;  ++j) {
            unsigned long prbs_accum = ((unsigned long)j << (i * 8));
            int k;
            for (k = 0;  k < 8;  ++k) {
                prbs_accum = (prbs_accum << 1)
                                ^ parity_check(prbs_accum & polynomial);
            }
            prbs_table[i][j] = (prbs_accum & 0xff);
        }
    }
}

/*
 * Update a 32-bit PRBS generator eight bits at a time.
 */
static unsigned long
update_prbs (unsigned long prbs_accum) {
    unsigned char acc_lsb = 0;
    int i;
    for (i = 0;  i < 4;  ++i ) {
        acc_lsb ^= prbs_table [i] [ (prbs_accum >> (i * 8) ) & 0xff ];
    }
    return (prbs_accum << 8) ^ ((unsigned long)acc_lsb);
}

/*
 * Generate the weight table.
 */
static void
gen_weight_table (void) {
  int i;
  for (i = 0;  i < 256;  ++i) {
      unsigned char mask=1U, ones_count = 0U;
      int j;
      for (j = 0;  j < 8;  ++j) {
          ones_count += ((i & mask) != 0U);
          mask = mask << 1;
      }
      weight[i] = ones_count;
  }
}

/*
 * Count the number of errors in a block of received data.
 */
static unsigned long
error_count (unsigned char *rx_data, int rx_data_length)
{
    unsigned long error_count = 0U;
    unsigned long prbs_accum = 0U;
    int i;

    /* seed the PRBS accumulator */
    for (i = 0;  i < 4;  ++i) {
        prbs_accum = (prbs_accum << 8) ^ (rx_data[i] ^ polarity_mask);
    }

    /* check the received data */
    for (i = 0;  i < rx_data_length;  ++i) {
        unsigned char error_pattern =
                          (prbs_accum >> 24) ^ (rx_data[i] ^ polarity_mask);
        if (error_pattern != 0U) {
            error_count += weight[error_pattern];
        }
        prbs_accum = update_prbs(prbs_accum);
    }
    return error_count;
}

/* data received from Desknet OC3port set up to send 2^15-1 PRBS pattern */
static unsigned char received_data [] = {
0xeb, 0xff, 0x00, 0x01, 0xff, 0xfb, 0xff, 0xe7,
0xff, 0xaf, 0xfe, 0x1f, 0xfb, 0xbf, 0xe6, 0x7f,
0xaa, 0xfe, 0x01, 0xfb, 0xfb, 0xe7, 0xe7, 0xaf,
0xae, 0x1e, 0x1b, 0xbb, 0xa6, 0x66, 0x2a, 0xab,
0x00, 0x05, 0xff, 0xe3, 0xff, 0xb7, 0xfe, 0x4f,
0xfa, 0x5f, 0xe2, 0x3f, 0xb3, 0x7e, 0x54, 0xfa,

0x05, 0xe3, 0xe3, 0xb7, 0xb6, 0x4e, 0x4a, 0x5a,
0x42, 0x22, 0x73, 0x32, 0xd5, 0x51, 0x00, 0x19,
0xff, 0xab, 0xfe, 0x07, 0xfb, 0xef, 0xe7, 0x9f,
0xae, 0xbe, 0x18, 0x7b, 0xae, 0xe6, 0x19, 0xab,
0xaa, 0x06, 0x03, 0xeb, 0xf7, 0x87, 0xce, 0xef,
0x59, 0x9c, 0x2a, 0xb7, 0x00, 0x4d, 0xfe, 0x53,

0xfa, 0x17, 0xe3, 0x8f, 0xb6, 0xde, 0x49, 0x3a,
0x49, 0x62, 0x48, 0xb2, 0x4c, 0x52, 0x56, 0x12,
0x0b, 0x93, 0xc6, 0x97, 0x68, 0x8c, 0x8c, 0xd4,
0xd5, 0x05, 0x01, 0xe1, 0xfb, 0xbb, 0xe6, 0x67,
0xaa, 0xae, 0x00, 0x1b, 0xff, 0xa7, 0xfe, 0x2f,
0xfb, 0x1f, 0xe5, 0xbf, 0xa2, 0x7e, 0x32, 0xfb,

0x51, 0xe4, 0x1b, 0xa7, 0xa6, 0x2e, 0x2b, 0x1b,
0x05, 0xa5, 0xe2, 0x23, 0xb3, 0x36, 0x55, 0x4a,
0x00, 0x43, 0xfe, 0x77, 0xfa, 0xcf, 0xe1, 0x5f,
0xb8, 0x3e, 0x6f, 0x7a, 0x9c, 0xe0, 0xb5, 0xbc,
0x42, 0x76, 0x72, 0xca, 0xd1, 0x41, 0x18, 0x79,
0xae, 0xea, 0x19, 0x83, 0xaa, 0xf6, 0x01, 0xcb,
};

#include <stdio.h>

int
main (void) {
    gen_prbs_table(PRBS_2_15_1_POLYNOMIAL);

    polarity_mask = 0xff;

    gen_weight_table();

    printf(
           "error count = %lu\n",
           error_count(
                       received_data,
                       (sizeof received_data)/sizeof(unsigned char)
                      )
          );

    return 0;
}

--a0000000000000000000000000000000--