55 lines
1.4 KiB
Python
55 lines
1.4 KiB
Python
|
# SPDX-License-Identifier: AGPL-3.0-Only
|
||
|
# Copyright (C) 2022 Sean Anderson <seanga2@gmail.com>
|
||
|
|
||
|
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
|
||
|
|
||
|
def descramble(scrambled):
|
||
|
locked = False
|
||
|
lfsr = ReverseList([0] * 11)
|
||
|
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())
|
||
|
|
||
|
outs = []
|
||
|
for _ in ins:
|
||
|
await RisingEdge(scrambler.clk)
|
||
|
outs.append(scrambler.scrambled.value)
|
||
|
|
||
|
compare_lists(ins[idles-1:], list(descramble(outs)))
|