From 243d7c76963c3119006048211d90a9b8c64e4b0a Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 10 Jun 2019 16:05:36 +0200 Subject: [PATCH] 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. --- litex/soc/cores/prbs.py | 160 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 litex/soc/cores/prbs.py diff --git a/litex/soc/cores/prbs.py b/litex/soc/cores/prbs.py new file mode 100644 index 000000000..365fb32fe --- /dev/null +++ b/litex/soc/cores/prbs.py @@ -0,0 +1,160 @@ +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)) + ) + )