# SPDX-License-Identifier: AGPL-3.0-Only # Copyright (C) 2022 Sean Anderson import itertools import random import cocotb from cocotb.clock import Clock from cocotb.triggers import FallingEdge, RisingEdge, Timer from .util import alist, ReverseList, print_list_at, compare_lists threshold = 32 async def descramble(scrambled): consecutive = 0 locked = False lfsr = ReverseList([0] * 11) async for s in scrambled: ldd = lfsr[8] ^ lfsr[10] if s ^ ldd: consecutive += 1 else: consecutive = 0 if consecutive >= threshold: locked = True if locked: yield s ^ ldd lfsr.append(ldd) else: lfsr.append(0 if s else 1) @cocotb.test(timeout_time=10, timeout_unit='us') async def test_scramble(scrambler): scrambler.unscrambled.value = 1 await Timer(1) await cocotb.start(Clock(scrambler.clk, 8, units='ns').start()) idles = threshold + 10 ins = [1] * idles + [0] + [random.randrange(2) for _ in range(1000)] async def send(): for bit in ins: await FallingEdge(scrambler.clk) scrambler.unscrambled.value = bit await cocotb.start(send()) async def recv(): for _ in ins: await RisingEdge(scrambler.clk) yield scrambler.scrambled.value compare_lists(ins[idles-1:], await alist(descramble(recv())))