Commit 243d7c76 authored by Florent Kermarrec's avatar Florent Kermarrec

soc/cores: add PRBS (Pseudo Random Binary Sequence) Generator/Checker

Imported from LiteICLink. PRBS can be useful for different purposes, so is
better integrated in LiteX.
parent cfa952b0
from operator import xor, add
from functools import reduce
from migen import *
from migen.genlib.cdc import MultiReg
class PRBSGenerator(Module):
def __init__(self, n_out, n_state=23, taps=[17, 22]):
self.o = Signal(n_out)
# # #
state = Signal(n_state, reset=1)
curval = [state[i] for i in range(n_state)]
curval += [0]*(n_out - n_state)
for i in range(n_out):
nv = reduce(xor, [curval[tap] for tap in taps])
curval.insert(0, nv)
curval.pop()
self.sync += [
state.eq(Cat(*curval[:n_state])),
self.o.eq(Cat(*curval))
]
class PRBS7Generator(PRBSGenerator):
def __init__(self, n_out):
PRBSGenerator.__init__(self, n_out, n_state=7, taps=[5, 6])
class PRBS15Generator(PRBSGenerator):
def __init__(self, n_out):
PRBSGenerator.__init__(self, n_out, n_state=15, taps=[13, 14])
class PRBS31Generator(PRBSGenerator):
def __init__(self, n_out):
PRBSGenerator.__init__(self, n_out, n_state=31, taps=[27, 30])
class PRBSTX(Module):
def __init__(self, width, reverse=False):
self.config = Signal(2)
self.i = Signal(width)
self.o = Signal(width)
# # #
config = Signal(2)
# generators
self.specials += MultiReg(self.config, config)
prbs7 = PRBS7Generator(width)
prbs15 = PRBS15Generator(width)
prbs31 = PRBS31Generator(width)
self.submodules += prbs7, prbs15, prbs31
# select
prbs_data = Signal(width)
self.comb += \
If(config == 0b11,
prbs_data.eq(prbs31.o)
).Elif(config == 0b10,
prbs_data.eq(prbs15.o)
).Else(
prbs_data.eq(prbs7.o)
)
# optional bits reversing
if reverse:
new_prbs_data = Signal(width)
self.comb += new_prbs_data.eq(prbs_data[::-1])
prbs_data = new_prbs_data
# prbs / data mux
self.comb += \
If(config == 0,
self.o.eq(self.i)
).Else(
self.o.eq(prbs_data)
)
class PRBSChecker(Module):
def __init__(self, n_in, n_state=23, taps=[17, 22]):
self.i = Signal(n_in)
self.errors = Signal(n_in)
# # #
state = Signal(n_state, reset=1)
curval = [state[i] for i in range(n_state)]
for i in reversed(range(n_in)):
correctv = reduce(xor, [curval[tap] for tap in taps])
self.sync += self.errors[i].eq(self.i[i] != correctv)
curval.insert(0, self.i[i])
curval.pop()
self.sync += state.eq(Cat(*curval[:n_state]))
class PRBS7Checker(PRBSChecker):
def __init__(self, n_out):
PRBSChecker.__init__(self, n_out, n_state=7, taps=[5, 6])
class PRBS15Checker(PRBSChecker):
def __init__(self, n_out):
PRBSChecker.__init__(self, n_out, n_state=15, taps=[13, 14])
class PRBS31Checker(PRBSChecker):
def __init__(self, n_out):
PRBSChecker.__init__(self, n_out, n_state=31, taps=[27, 30])
class PRBSRX(Module):
def __init__(self, width, reverse=False):
self.i = Signal(width)
self.config = Signal(2)
self.errors = Signal(32)
# # #
config = Signal(2)
# optional bits reversing
prbs_data = self.i
if reverse:
new_prbs_data = Signal(width)
self.comb += new_prbs_data.eq(prbs_data[::-1])
prbs_data = new_prbs_data
# checkers
self.specials += MultiReg(self.config, config)
prbs7 = PRBS7Checker(width)
prbs15 = PRBS15Checker(width)
prbs31 = PRBS31Checker(width)
self.submodules += prbs7, prbs15, prbs31
self.comb += [
prbs7.i.eq(prbs_data),
prbs15.i.eq(prbs_data),
prbs31.i.eq(prbs_data)
]
# errors count
self.sync += \
If(config == 0,
self.errors.eq(0)
).Elif(self.errors != (2**32-1),
If(config == 0b01,
self.errors.eq(self.errors + (prbs7.errors != 0))
).Elif(config == 0b10,
self.errors.eq(self.errors + (prbs15.errors != 0))
).Elif(config == 0b11,
self.errors.eq(self.errors + (prbs31.errors != 0))
)
)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment