Effect of DFE Error Propagation on the Performance of Reed-Solomon Codes

Bursty channel (DFE) model

We model the 1-tap DFE as a Markov chain.

The Markov chain has two states:

  • G : Good/normal state, i.e. previous decision was correct
  • B : Bad/burst state, i.e. previous decision was wrong

with transition probabilities:

  • Pr(G->G) = 1 - pe
  • Pr(G->B) = pe
  • Pr(B->G) = 1 - pb
  • Pr(B->B) = pb

where

  • $pe = Pr\{\textrm{E | G}\} =$ Probability of bit-error given previous bit/decision was correct, i.e., the raw BER.
  • $pb = Pr\{\textrm{E | B}\} =$ Probability of bit-error given previous bit/decision was wrong, i.e., the burst probability.

This model is "solved" analytically as well as computed using a Monte Carlo simulation approach. The key quantity of interest that is computed is

P(x, n) = Pr{x symbol errors in a n symbol block}

FEC performace

Let X = number of symbol errors pre-FEC, and Y = number of symbol errors post-FEC. If a RS(n, k) code (where k = message size, n = codeword size => n-k = parity size) is being used to correct t = (n – k)/2 errors, the probability of not-decoding-correctly is

$$ P_{ndc} = Pr\{X >= t + 1\} = \sum_{x = t+1}^{n} P_X(x) $$

Also, the expected number of symbols errors is

$$ E[X] = \sum_{x = 0}^{n} x \cdot P_X(x) $$$$ E[Y] = \sum_{y = t+1}^{n} y \cdot P_X(y) $$

The pre and post FEC symbol-error rates and bit error rates can be calculated as $$ \begin{align} SER_{pre} &= \frac{E[X]}{n} \\ SER_{post} &= \frac{E[Y]}{n} \\ BER_{post} &= \frac{E[Y]}{mn}. \end{align} $$


In [ ]:


In [5]:
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import factorial
from errsim import *
%matplotlib inline
import matplotlib.pylab as pylab
pylab.rcParams['figure.figsize'] = 12, 10

In [12]:
# Error PMF, P(x, n) = Prob{x symbol errors in a block of n symbols}
# pe = Prob. of bit error in normal/good state
# pb = Prob. of bit error in burst/bad state
# m = Number of bits per symbol
# n = Number of symbols per block

# Simulated PMF: pe=1e-2, pb=0.5, m=4, n=15, nblks=1e6
spmf_1em2_0p5_4_15 = errhist(1e-2, 0.5, 4, 15, int(1e6)) / 1e6

# Analytical PMF: pe=1e-2, pb=0.5, m=4, n=15
apmf_1em2_0p5_4_15 = errpmf(1e-2, 0.5, 4, 15)

In [19]:
x = np.arange(16)
plt.semilogy(x, apmf_1em2_0p5_4_15[x], 'b-',   label='Analytical 1e-2, 0.5, 4, 15')
plt.semilogy(x, spmf_1em2_0p5_4_15[x], 'ro--', label='Simulation 1e-2, 0.5, 4, 15')
plt.title('P(x, n) = Prob{x symbol errors in n symbol block}')
plt.xlabel('Symbols, x')
plt.ylabel('Probability')
plt.legend()
plt.grid()



In [14]:
# Simulated PMF: pe=1e-6, pb=0.5, m=8, n=255, nblks=1e8
hist_1em6_0p5_8_255 = np.load('errhist-1e-6-0.5-8-255-1e8.npy')
spmf_1em6_0p5_8_255 = hist_1em6_0p5_8_255 / 1e8

# Analytical PMF: pe=1e-6, pb=0.5, m=8, n=255
apmf_1em6_0p5_8_255 = errpmf(1e-6, 0.5, 8, 255)

In [20]:
x = np.arange(16)
plt.semilogy(x, apmf_1em6_0p5_8_255[x], 'b-',   label='Analytical 1e-6, 0.5, 8, 255')
plt.semilogy(x, spmf_1em6_0p5_8_255[x], 'ro--', label='Simulation 1e-6, 0.5, 8, 255')
plt.title('P(x, n) = Prob{x symbol errors in n symbol block}')
plt.xlabel('Symbols, x')
plt.ylabel('Probability')
plt.legend()
plt.grid()



In [23]:
x = np.arange(16)
plt.semilogy(x, apmf_1em6_0p5_8_255[x], label='P_X(x)')
plt.semilogy(x, prob_ndc(apmf_1em6_0p5_8_255)[x], label='Pndc(t)')
plt.semilogy(x, prob_symerr(apmf_1em6_0p5_8_255)[x], label='SER_post(t)')
plt.semilogy(x, prob_symerr(apmf_1em6_0p5_8_255)[x]/8, label='BER_post(t)')
plt.title('RS(255, k) performance with pe=1e-6, pb=0.5, m=8, n=255')
plt.xlabel('Number of Symbols, x or Number of Symbols Corrected, t')
plt.ylabel('Probability')
plt.legend()
plt.grid()



In [78]:
# Analytical PMF: pe=1e-6, pb=0.5, m=10, n=544
pe=1e-6
pb=0.5
m=10
n=544
apmf_1em6_0p5_10_544 = errpmf(pe, pb, m, n)

In [76]:
x = np.arange(16)
plt.semilogy(x, apmf_1em6_0p5_10_544[x], label='P_X(x)')
plt.semilogy(x, prob_ndc(apmf_1em6_0p5_10_544)[x], label='Pndc(t)')
plt.semilogy(x, prob_symerr(apmf_1em6_0p5_10_544)[x], label='SER_post(t)')
plt.semilogy(x, prob_symerr(apmf_1em6_0p5_10_544)[x]/10, label='BER_post(t)')
plt.title('RS(544, k) performance with pe=1e-6, pb=0.5, m=10, n=544')
plt.xlabel('Number of Symbols, x or Number of Symbols Corrected, t')
plt.ylabel('Probability')
plt.legend()
plt.grid()



In [77]:
x = np.arange(5, 9)

plt.semilogy(x, apmf_1em6_0p5_8_255[x], label='$P_X(x)$, m=8, n=255')
plt.semilogy(x, prob_ndc(apmf_1em6_0p5_8_255)[x], label='$P_{ndc}(t)$, m=8, n=255')
plt.semilogy(x, prob_symerr(apmf_1em6_0p5_8_255)[x], label='$SER_{post}(t)$, m=8, n=255')
plt.semilogy(x, prob_symerr(apmf_1em6_0p5_8_255)[x]/8, label='$BER_{post}(t)$, m=8, n=255')

plt.semilogy(x, apmf_1em6_0p5_10_544[x], label='$P_X(x)$, m=10, n=544')
plt.semilogy(x, prob_ndc(apmf_1em6_0p5_10_544)[x], label='$P_{ndc}(t)$, m=10, n=544')
plt.semilogy(x, prob_symerr(apmf_1em6_0p5_10_544)[x], label='$SER_{post}(t)$, m=10, n=544')
plt.semilogy(x, prob_symerr(apmf_1em6_0p5_10_544)[x]/10, label='$BER_{post}(t)$, m=10, n=544')

plt.semilogy(x, np.ones_like(x)*1e-15, 'k--')

plt.xticks(x)
plt.title('RS(n, k) performance with pe=1e-6, pb=0.5')
plt.xlabel('Number of Symbols, x or Number of Symbols Corrected, t')
plt.ylabel('Probability')
plt.legend()
plt.grid()



In [74]:
print('RS(255, k) over GF(2^4)')
print('-----------------------')
print('P_X(x=[6, 7, 8])    =', apmf_1em6_0p5_8_255[6:9])
print('P_ndc(t=[6, 7, 8])  =', prob_ndc(apmf_1em6_0p5_8_255)[6:9])
print('P_derr(t=[6, 7, 8]) <', prob_ndc(apmf_1em6_0p5_8_255)[6:9] / factorial([6, 7, 8]))
print('SER(t=[6, 7, 8])    =', prob_symerr(apmf_1em6_0p5_8_255)[6:9])
print('BER(t=[6, 7, 8])    =', prob_symerr(apmf_1em6_0p5_8_255)[6:9] / 8)


RS(255, k) over GF(2^4)
-----------------------
P_X(x=[6, 7, 8])    = [  4.54580508e-12   4.47585038e-14   4.93386845e-16]
P_ndc(t=[6, 7, 8])  = [  4.52567779e-14   4.98274101e-16   4.88725557e-18]
P_derr(t=[6, 7, 8]) < [  6.28566359e-17   9.88639088e-20   1.21211696e-22]
SER(t=[6, 7, 8])    = [  1.24431629e-15   1.56514844e-17   1.72681411e-19]
BER(t=[6, 7, 8])    = [  1.55539537e-16   1.95643555e-18   2.15851764e-20]

In [88]:
pmf_1em5_0p5_8_255 = errpmf(1e-5, 0.5, 8, 255)
pmf_1em5_0p5_10_544 = errpmf(1e-5, 0.5, 10, 544)

In [89]:
x = np.arange(16)

plt.semilogy(x, pmf_1em5_0p5_8_255[x], label='$P_X(x)$, m=8, n=255')
plt.semilogy(x, prob_ndc(pmf_1em5_0p5_8_255)[x], label='$P_{ndc}(t)$, m=8, n=255')
plt.semilogy(x, prob_symerr(pmf_1em5_0p5_8_255)[x], label='$SER_{post}(t)$, m=8, n=255')
plt.semilogy(x, prob_symerr(pmf_1em5_0p5_8_255)[x]/8, label='$BER_{post}(t)$, m=8, n=255')

plt.semilogy(x, pmf_1em5_0p5_10_544[x], label='$P_X(x)$, m=10, n=544')
plt.semilogy(x, prob_ndc(pmf_1em5_0p5_10_544)[x], label='$P_{ndc}(t)$, m=10, n=544')
plt.semilogy(x, prob_symerr(pmf_1em5_0p5_10_544)[x], label='$SER_{post}(t)$, m=10, n=544')
plt.semilogy(x, prob_symerr(pmf_1em5_0p5_10_544)[x]/10, label='$BER_{post}(t)$, m=10, n=544')

plt.semilogy(x, np.ones_like(x)*1e-15, 'k--')

plt.xticks(x)
plt.title('RS(n, k) performance with pe=1e-5, pb=0.5')
plt.xlabel('Number of Symbols, x or Number of Symbols Corrected, t')
plt.ylabel('Probability')
plt.legend()
plt.grid()



In [85]:
pmf_1em4_0p5_8_255 = errpmf(1e-4, 0.5, 8, 255)
pmf_1em4_0p5_10_544 = errpmf(1e-4, 0.5, 10, 544)

In [91]:
x = np.arange(21)

plt.semilogy(x, pmf_1em4_0p5_8_255[x], 'b-', label='$P_X(x)$, m=8, n=255')
plt.semilogy(x, prob_ndc(pmf_1em4_0p5_8_255)[x], 'r-', label='$P_{ndc}(t)$, m=8, n=255')
plt.semilogy(x, prob_symerr(pmf_1em4_0p5_8_255)[x], 'g-', label='$SER_{post}(t)$, m=8, n=255')
plt.semilogy(x, prob_symerr(pmf_1em4_0p5_8_255)[x]/8, 'm-', label='$BER_{post}(t)$, m=8, n=255')

plt.semilogy(x, pmf_1em4_0p5_10_544[x], 'b--', label='$P_X(x)$, m=10, n=544')
plt.semilogy(x, prob_ndc(pmf_1em4_0p5_10_544)[x], 'r--', label='$P_{ndc}(t)$, m=10, n=544')
plt.semilogy(x, prob_symerr(pmf_1em4_0p5_10_544)[x], 'g--', label='$SER_{post}(t)$, m=10, n=544')
plt.semilogy(x, prob_symerr(pmf_1em4_0p5_10_544)[x]/10, 'm--', label='$BER_{post}(t)$, m=10, n=544')

plt.semilogy(x, np.ones_like(x)*1e-15, 'k--')

plt.xticks(x)
plt.title('RS(n, k) performance with pe=1e-4, pb=0.5')
plt.xlabel('Number of Symbols, x or Number of Symbols Corrected, t')
plt.ylabel('Probability')
plt.legend()
plt.grid()



In [ ]: