From: Florent Kermarrec Date: Mon, 3 Nov 2014 17:54:41 +0000 (+0100) Subject: link: add CRC and testbench X-Git-Tag: 24jan2021_ls180~2572^2~172 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=80622986686cdd5b4508f5de576402fc643e4b6e;p=litex.git link: add CRC and testbench --- diff --git a/lib/sata/link/crc.py b/lib/sata/link/crc.py new file mode 100644 index 00000000..8f483005 --- /dev/null +++ b/lib/sata/link/crc.py @@ -0,0 +1,106 @@ +from migen.fhdl.std import * +from migen.genlib.misc import optree + +class CRCEngine(Module): + """Cyclic Redundancy Check Engine + + Compute next CRC value from last CRC value and data input using + an optimized asynchronous LFSR. + + Parameters + ---------- + width : int + Width of the data bus and CRC. + polynom : int + Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC) + + Attributes + ---------- + d : in + Data input. + last : in + last CRC value. + next : + next CRC value. + """ + def __init__(self, width, polynom): + self.d = Signal(width) + self.last = Signal(width) + self.next = Signal(width) + + ### + + + def _optimize_eq(l): + """ + Replace even numbers of XORs in the equation + with an equivalent XOR + """ + d = {} + for e in l: + if e in d: + d[e] += 1 + else: + d[e] = 1 + r = [] + for key, value in d.items(): + if value%2 != 0: + r.append(key) + return r + + new = Signal(32) + self.comb += new.eq(self.last ^ self.d) + + # compute and optimize CRC's LFSR + curval = [[("new", i)] for i in range(width)] + for i in range(width): + feedback = curval.pop() + curval.insert(0, feedback) + for j in range(1, width-1): + if (polynom&(1< crc_ref + $(CMD) crc_tb.py scrambler_tb: $(CC) $(CFLAGS) $(INC) -o scrambler scrambler.c diff --git a/lib/sata/link/test/crc_tb.py b/lib/sata/link/test/crc_tb.py new file mode 100644 index 00000000..459e4e17 --- /dev/null +++ b/lib/sata/link/test/crc_tb.py @@ -0,0 +1,52 @@ +from subprocess import check_output + +from migen.fhdl.std import * + +from lib.sata.std import * +from lib.sata.link.crc import * + +def check(ref, res): + shift = 0 + while((ref[0] != res[0]) and (len(res)>1)): + res.pop(0) + shift += 1 + length = min(len(ref), len(res)) + errors = 0 + for i in range(length): + if ref.pop(0) != res.pop(0): + errors += 1 + return shift, length, errors + +class TB(Module): + def __init__(self): + self.submodules.crc = SATACRC() + + def gen_simulation(self, selfp): + + # init CRC + selfp.crc.d = 0x12345678 + selfp.crc.ce = 1 + selfp.crc.reset = 1 + yield + selfp.crc.reset = 0 + + # get C code results + ref = [] + f = open("crc_ref", "r") + for l in f: + ref.append(int(l, 16)) + f.close() + + # log results + res = [] + for i in range(256): + res.append(selfp.crc.value) + yield + + # check results + s, l, e = check(ref, res) + print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) + +if __name__ == "__main__": + from migen.sim.generic import run_simulation + run_simulation(TB(), ncycles=1000, vcd_name="my.vcd", keep_files=True) diff --git a/lib/sata/std.py b/lib/sata/std.py new file mode 100644 index 00000000..3f3ea2f4 --- /dev/null +++ b/lib/sata/std.py @@ -0,0 +1,8 @@ +from migen.fhdl.std import * + +def phy_layout(dw): + layout = [ + ("p_packetized", True), + ("d", dw) + ] + return layout