tb: Break out the core of pcs_send_codes into its own function

The PMA also has to deal with "recoverd bitstreams" (that is, inputs which
can have 0, 1, or 2 valid bits). Export the core of pcs_send_codes into its
own function, as it is useful for generating these signals.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
Sean Anderson 2022-08-08 00:23:55 -04:00
parent fec8a0a9f6
commit c1301ca31a
2 changed files with 49 additions and 45 deletions

View File

@ -2,7 +2,6 @@
# Copyright (C) 2022 Sean Anderson <seanga2@gmail.com> # Copyright (C) 2022 Sean Anderson <seanga2@gmail.com>
import enum import enum
import random
import itertools import itertools
import cocotb import cocotb
@ -11,7 +10,7 @@ from cocotb.regression import TestFactory
from cocotb.triggers import ClockCycles, Edge, RisingEdge, FallingEdge, Timer from cocotb.triggers import ClockCycles, Edge, RisingEdge, FallingEdge, Timer
from cocotb.types import LogicArray from cocotb.types import LogicArray
from .util import alist, classproperty, ReverseList, timeout from .util import *
class Code(enum.Enum): class Code(enum.Enum):
_0 = (0b11110, '0') _0 = (0b11110, '0')
@ -195,49 +194,9 @@ async def pcs_recv_packet(pcs):
yield code.data yield code.data
raise PrematureEndError() raise PrematureEndError()
def one_valid():
return 1
def two_valid():
return 2
def rand_valid():
return random.randrange(3)
class saw_valid:
def __init__(self):
self.last = 0
# Lie for TestFactory
self.__qualname__ = self.__class__.__qualname__
def __call__(self):
self.last += 1
if self.last > 2:
self.last = 0
return self.last
async def pcs_send_codes(pcs, codes, valids): async def pcs_send_codes(pcs, codes, valids):
await FallingEdge(pcs.rx_clk) await send_recovered_bits(pcs.rx_clk, pcs.pma_data_rx, pcs.pma_data_rx_valid,
bits = itertools.chain(*codes) itertools.chain(*codes), valids)
try:
while True:
valid = valids()
pcs.pma_data_rx_valid.value = valid
if valid == 0:
data = 'XX'
elif valid == 1:
data = (next(bits), 'X')
else:
first = next(bits)
try:
second = next(bits)
except StopIteration:
second = 'X'
data = (first, second)
pcs.pma_data_rx.value = LogicArray(data)
await FallingEdge(pcs.rx_clk)
except StopIteration:
pass
@cocotb.test(timeout_time=10, timeout_unit='us') @cocotb.test(timeout_time=10, timeout_unit='us')
async def test_tx(pcs): async def test_tx(pcs):

View File

@ -2,10 +2,12 @@
# Copyright (C) 2022 Sean Anderson <seanga2@gmail.com> # Copyright (C) 2022 Sean Anderson <seanga2@gmail.com>
import functools import functools
import random
import cocotb import cocotb
from cocotb.triggers import with_timeout
from cocotb.result import SimTimeoutError from cocotb.result import SimTimeoutError
from cocotb.triggers import with_timeout, FallingEdge
from cocotb.types import LogicArray
async def alist(xs): async def alist(xs):
return [x async for x in xs] return [x async for x in xs]
@ -65,3 +67,46 @@ class ReverseList(list):
def __iter__(self): def __iter__(self):
return super().__reversed__() return super().__reversed__()
def one_valid():
return 1
def two_valid():
return 2
def rand_valid():
return random.randrange(3)
class saw_valid:
def __init__(self):
self.last = 0
# Lie for TestFactory
self.__qualname__ = self.__class__.__qualname__
def __call__(self):
self.last += 1
if self.last > 2:
self.last = 0
return self.last
async def send_recovered_bits(clk, data, valid, bits, valids):
await FallingEdge(clk)
try:
while True:
v = valids()
valid.value = v
if v == 0:
d = 'XX'
elif v == 1:
d = (next(bits), 'X')
else:
first = next(bits)
try:
second = next(bits)
except StopIteration:
second = 'X'
d = (first, second)
data.value = LogicArray(d)
await FallingEdge(clk)
except StopIteration:
pass