Merge pull request #3 from mithro/bist
Improve the BIST testbench and documentation
This commit is contained in:
commit
c090593e52
|
@ -1,3 +1,5 @@
|
|||
"""Built In Self Test (BIST) modules for testing liteDRAM functionality."""
|
||||
|
||||
from functools import reduce
|
||||
from operator import xor
|
||||
|
||||
|
@ -11,6 +13,23 @@ from litedram.frontend.dma import LiteDRAMDMAWriter, LiteDRAMDMAReader
|
|||
|
||||
@CEInserter()
|
||||
class LFSR(Module):
|
||||
"""Linear-Feedback Shift Register to generate a pseudo-random sequence.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_out : int
|
||||
Width of the output data signal.
|
||||
n_state : int
|
||||
???
|
||||
taps : list of int
|
||||
???
|
||||
|
||||
Attributes
|
||||
----------
|
||||
o : in
|
||||
Output data
|
||||
"""
|
||||
|
||||
def __init__(self, n_out, n_state=31, taps=[27, 30]):
|
||||
self.o = Signal(n_out)
|
||||
|
||||
|
@ -26,12 +45,25 @@ class LFSR(Module):
|
|||
|
||||
self.sync += [
|
||||
state.eq(Cat(*curval[:n_state])),
|
||||
self.o.eq(Cat(*curval))
|
||||
self.o.eq(Cat(*curval)),
|
||||
]
|
||||
|
||||
|
||||
@CEInserter()
|
||||
class Counter(Module):
|
||||
"""Simple incremental counter.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_out : int
|
||||
Width of the output data signal.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
o : in
|
||||
Output data
|
||||
"""
|
||||
|
||||
def __init__(self, n_out):
|
||||
self.o = Signal(n_out)
|
||||
|
||||
|
@ -41,6 +73,7 @@ class Counter(Module):
|
|||
|
||||
|
||||
class _LiteDRAMBISTGenerator(Module):
|
||||
|
||||
def __init__(self, dram_port, random):
|
||||
self.start = Signal()
|
||||
self.done = Signal()
|
||||
|
@ -59,11 +92,10 @@ class _LiteDRAMBISTGenerator(Module):
|
|||
self.submodules += fsm
|
||||
|
||||
fsm.act("IDLE",
|
||||
self.done.eq(1),
|
||||
If(self.start,
|
||||
NextValue(cmd_counter, 0),
|
||||
NextState("RUN")
|
||||
)
|
||||
NextState("RUN"),
|
||||
),
|
||||
)
|
||||
fsm.act("RUN",
|
||||
dma.sink.valid.eq(1),
|
||||
|
@ -71,17 +103,38 @@ class _LiteDRAMBISTGenerator(Module):
|
|||
gen.ce.eq(1),
|
||||
NextValue(cmd_counter, cmd_counter + 1),
|
||||
If(cmd_counter == (self.length-1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
NextState("DONE"),
|
||||
),
|
||||
),
|
||||
)
|
||||
fsm.act("DONE",
|
||||
self.done.eq(1),
|
||||
)
|
||||
self.comb += [
|
||||
dma.sink.address.eq(self.base + cmd_counter),
|
||||
dma.sink.data.eq(gen.o)
|
||||
dma.sink.data.eq(gen.o),
|
||||
]
|
||||
|
||||
|
||||
class LiteDRAMBISTGenerator(Module, AutoCSR):
|
||||
"""litex module to generate a given pattern in memory.abs
|
||||
|
||||
Attributes
|
||||
----------
|
||||
reset : in
|
||||
Reset the module.
|
||||
start : in
|
||||
Start the generation.
|
||||
|
||||
base : in
|
||||
DRAM address to start from.
|
||||
length : in
|
||||
Number of DRAM words to write.
|
||||
|
||||
done : out
|
||||
The module has completed writing the pattern.
|
||||
"""
|
||||
|
||||
def __init__(self, dram_port, random=True):
|
||||
self.reset = CSR()
|
||||
self.start = CSR()
|
||||
|
@ -98,37 +151,43 @@ class LiteDRAMBISTGenerator(Module, AutoCSR):
|
|||
|
||||
reset_sync = BusSynchronizer(1, "sys", cd)
|
||||
start_sync = PulseSynchronizer("sys", cd)
|
||||
done_sync = BusSynchronizer(1, cd, "sys")
|
||||
self.submodules += reset_sync, start_sync, done_sync
|
||||
|
||||
base_sync = BusSynchronizer(dram_port.aw, "sys", cd)
|
||||
length_sync = BusSynchronizer(dram_port.aw, "sys", cd)
|
||||
self.submodules += base_sync, length_sync
|
||||
|
||||
self.submodules += reset_sync, start_sync
|
||||
self.comb += [
|
||||
reset_sync.i.eq(self.reset.re),
|
||||
core.reset.eq(reset_sync.o),
|
||||
|
||||
start_sync.i.eq(self.start.re),
|
||||
core.start.eq(start_sync.o),
|
||||
]
|
||||
|
||||
done_sync = BusSynchronizer(1, cd, "sys")
|
||||
self.submodules += done_sync
|
||||
self.comb += [
|
||||
done_sync.i.eq(core.done),
|
||||
self.done.status.eq(done_sync.o),
|
||||
]
|
||||
|
||||
base_sync = BusSynchronizer(dram_port.aw, "sys", cd)
|
||||
length_sync = BusSynchronizer(dram_port.aw, "sys", cd)
|
||||
self.submodules += base_sync, length_sync
|
||||
self.comb += [
|
||||
base_sync.i.eq(self.base.storage),
|
||||
core.base.eq(base_sync.o),
|
||||
|
||||
length_sync.i.eq(self.length.storage),
|
||||
core.length.eq(length_sync.o)
|
||||
core.length.eq(length_sync.o),
|
||||
]
|
||||
|
||||
|
||||
class _LiteDRAMBISTChecker(Module, AutoCSR):
|
||||
|
||||
def __init__(self, dram_port, random):
|
||||
self.start = Signal()
|
||||
self.done = Signal()
|
||||
|
||||
self.base = Signal(dram_port.aw)
|
||||
self.length = Signal(dram_port.aw)
|
||||
|
||||
self.err_count = Signal(32)
|
||||
|
||||
# # #
|
||||
|
@ -138,64 +197,98 @@ class _LiteDRAMBISTChecker(Module, AutoCSR):
|
|||
self.submodules.gen = gen = gen_cls(dram_port.dw)
|
||||
|
||||
# address
|
||||
cmd_counter = Signal(dram_port.aw)
|
||||
self._cmd_counter = cmd_counter = Signal(dram_port.aw)
|
||||
cmd_fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += cmd_fsm
|
||||
|
||||
cmd_fsm.act("IDLE",
|
||||
If(self.start,
|
||||
NextValue(cmd_counter, 0),
|
||||
NextState("RUN")
|
||||
)
|
||||
NextState("RUN"),
|
||||
),
|
||||
)
|
||||
cmd_fsm.act("RUN",
|
||||
dma.sink.valid.eq(1),
|
||||
If(dma.sink.ready,
|
||||
NextValue(cmd_counter, cmd_counter + 1),
|
||||
If(cmd_counter == (self.length-1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
NextState("DONE")
|
||||
),
|
||||
),
|
||||
)
|
||||
cmd_fsm.act("DONE")
|
||||
self.comb += dma.sink.address.eq(self.base + cmd_counter)
|
||||
|
||||
# data
|
||||
data_counter = Signal(dram_port.aw)
|
||||
self._data_counter = data_counter = Signal(dram_port.aw)
|
||||
data_fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += data_fsm
|
||||
|
||||
self.error = error = Signal()
|
||||
self.actual = actual = Signal(dram_port.aw)
|
||||
self.expect = expect = Signal(dram_port.aw)
|
||||
self.comb += [
|
||||
actual.eq(dma.source.data),
|
||||
expect.eq(gen.o),
|
||||
error.eq(dma.source.valid & (expect != actual)),
|
||||
]
|
||||
|
||||
data_fsm.act("IDLE",
|
||||
If(self.start,
|
||||
NextValue(data_counter, 0),
|
||||
NextValue(self.err_count, 0),
|
||||
NextState("RUN")
|
||||
)
|
||||
NextState("RUN"),
|
||||
),
|
||||
)
|
||||
data_fsm.act("RUN",
|
||||
dma.source.ready.eq(1),
|
||||
If(dma.source.valid,
|
||||
gen.ce.eq(1),
|
||||
NextValue(data_counter, data_counter + 1),
|
||||
If(dma.source.data != gen.o,
|
||||
NextValue(self.err_count, self.err_count + 1)
|
||||
If(error,
|
||||
NextValue(self.err_count, self.err_count + 1),
|
||||
),
|
||||
If(data_counter == (self.length-1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
NextState("DONE"),
|
||||
),
|
||||
),
|
||||
)
|
||||
data_fsm.act("DONE")
|
||||
|
||||
self.comb += self.done.eq(cmd_fsm.ongoing("IDLE") &
|
||||
data_fsm.ongoing("IDLE"))
|
||||
self.comb += self.done.eq(
|
||||
cmd_fsm.ongoing("DONE") & data_fsm.ongoing("DONE"))
|
||||
|
||||
|
||||
class LiteDRAMBISTChecker(Module, AutoCSR):
|
||||
"""litex module to check a given pattern in memory.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
reset : in
|
||||
Reset the module
|
||||
start : in
|
||||
Start the checking
|
||||
|
||||
base : in
|
||||
DRAM address to start from.
|
||||
length : in
|
||||
Number of DRAM words to check.
|
||||
|
||||
done : out
|
||||
The module has completed checking
|
||||
|
||||
err_count : out
|
||||
Number of DRAM words which don't match.
|
||||
"""
|
||||
|
||||
def __init__(self, dram_port, random=True):
|
||||
self.reset = CSR()
|
||||
self.start = CSR()
|
||||
self.done = CSRStatus()
|
||||
|
||||
self.base = CSRStorage(dram_port.aw)
|
||||
self.length = CSRStorage(dram_port.aw)
|
||||
|
||||
self.done = CSRStatus()
|
||||
self.err_count = CSRStatus(32)
|
||||
|
||||
# # #
|
||||
|
@ -205,32 +298,39 @@ class LiteDRAMBISTChecker(Module, AutoCSR):
|
|||
core = ResetInserter()(_LiteDRAMBISTChecker(dram_port, random))
|
||||
self.submodules.core = ClockDomainsRenamer(cd)(core)
|
||||
|
||||
#reset_sync = PulseSynchronizer("sys", cd)
|
||||
reset_sync = BusSynchronizer(1, "sys", cd)
|
||||
start_sync = PulseSynchronizer("sys", cd)
|
||||
done_sync = BusSynchronizer(1, cd, "sys")
|
||||
self.submodules += reset_sync, start_sync, done_sync
|
||||
|
||||
base_sync = BusSynchronizer(dram_port.aw, "sys", cd)
|
||||
length_sync = BusSynchronizer(dram_port.aw, "sys", cd)
|
||||
err_count_sync = BusSynchronizer(32, cd, "sys")
|
||||
self.submodules += base_sync, length_sync, err_count_sync
|
||||
|
||||
self.submodules += reset_sync, start_sync
|
||||
self.comb += [
|
||||
reset_sync.i.eq(self.reset.re),
|
||||
core.reset.eq(reset_sync.o),
|
||||
|
||||
start_sync.i.eq(self.start.re),
|
||||
core.start.eq(start_sync.o),
|
||||
]
|
||||
|
||||
done_sync = BusSynchronizer(1, cd, "sys")
|
||||
self.submodules += done_sync
|
||||
self.comb += [
|
||||
done_sync.i.eq(core.done),
|
||||
self.done.status.eq(done_sync.o),
|
||||
]
|
||||
|
||||
base_sync = BusSynchronizer(dram_port.aw, "sys", cd)
|
||||
length_sync = BusSynchronizer(dram_port.aw, "sys", cd)
|
||||
self.submodules += base_sync, length_sync
|
||||
self.comb += [
|
||||
base_sync.i.eq(self.base.storage),
|
||||
core.base.eq(base_sync.o),
|
||||
|
||||
length_sync.i.eq(self.length.storage),
|
||||
core.length.eq(length_sync.o),
|
||||
|
||||
err_count_sync.i.eq(core.err_count),
|
||||
self.err_count.status.eq(err_count_sync.o)
|
||||
]
|
||||
|
||||
err_count_sync = BusSynchronizer(32, cd, "sys")
|
||||
self.submodules += err_count_sync
|
||||
self.comb += [
|
||||
err_count_sync.i.eq(core.err_count),
|
||||
self.err_count.status.eq(err_count_sync.o),
|
||||
]
|
||||
|
|
|
@ -1,9 +1,37 @@
|
|||
"""Direct Memory Access (DMA) reader and writer modules."""
|
||||
|
||||
from litex.gen import *
|
||||
|
||||
from litex.soc.interconnect import stream
|
||||
|
||||
|
||||
class LiteDRAMDMAReader(Module):
|
||||
"""Read data from DRAM memory.
|
||||
|
||||
For every address written to the sink, one DRAM word will be produced on
|
||||
the source.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
port : dram_port
|
||||
Port on the DRAM memory controller to read from.
|
||||
|
||||
fifo_depth : int
|
||||
How many request results the output FIFO can contain (and thus how many
|
||||
read requests can be outstanding at once).
|
||||
|
||||
fifo_buffered : bool
|
||||
???
|
||||
|
||||
Attributes
|
||||
----------
|
||||
sink : Record("address")
|
||||
Sink for DRAM addresses to be read.
|
||||
|
||||
source : Record("data")
|
||||
Source for DRAM word results from reading.
|
||||
"""
|
||||
|
||||
def __init__(self, port, fifo_depth=16, fifo_buffered=False):
|
||||
self.sink = sink = stream.Endpoint([("address", port.aw)])
|
||||
self.source = source = stream.Endpoint([("data", port.dw)])
|
||||
|
@ -48,6 +76,25 @@ class LiteDRAMDMAReader(Module):
|
|||
|
||||
|
||||
class LiteDRAMDMAWriter(Module):
|
||||
"""Write data to DRAM memory.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
port : dram_port
|
||||
Port on the DRAM memory controller to write to.
|
||||
|
||||
fifo_depth : int
|
||||
How many requests the input FIFO can contain (and thus how many write
|
||||
requests can be outstanding at once).
|
||||
|
||||
fifo_buffered : bool
|
||||
???
|
||||
|
||||
Attributes
|
||||
----------
|
||||
sink : Record("address", "data")
|
||||
Sink for DRAM addresses and DRAM data word to be written too.
|
||||
"""
|
||||
def __init__(self, port, fifo_depth=16, fifo_buffered=False):
|
||||
self.sink = sink = stream.Endpoint([("address", port.aw),
|
||||
("data", port.dw)])
|
||||
|
|
|
@ -12,9 +12,11 @@ from litedram.frontend.bist import LiteDRAMBISTGenerator
|
|||
from litedram.frontend.bist import LiteDRAMBISTChecker
|
||||
from litedram.frontend.adaptation import LiteDRAMPortCDC
|
||||
|
||||
|
||||
from litedram.phy.model import SDRAMPHYModel
|
||||
|
||||
from test.common import *
|
||||
|
||||
|
||||
class SimModule(SDRAMModule):
|
||||
# geometry
|
||||
nbanks = 2
|
||||
|
@ -70,20 +72,14 @@ def main_generator(dut):
|
|||
for i in range(100):
|
||||
yield
|
||||
# init
|
||||
yield dut.generator.reset.storage.eq(1)
|
||||
yield dut.checker.reset.storage.eq(1)
|
||||
yield
|
||||
yield dut.generator.reset.storage.eq(0)
|
||||
yield dut.checker.reset.storage.eq(0)
|
||||
yield
|
||||
yield from reset_bist_module(dut.generator)
|
||||
yield from reset_bist_module(dut.checker)
|
||||
# write
|
||||
yield dut.generator.base.storage.eq(16)
|
||||
yield dut.generator.length.storage.eq(16)
|
||||
for i in range(32):
|
||||
yield
|
||||
yield dut.generator.shoot.re.eq(1)
|
||||
yield
|
||||
yield dut.generator.shoot.re.eq(0)
|
||||
yield from toggle_re(dut.generator.start)
|
||||
for i in range(32):
|
||||
yield
|
||||
while((yield dut.generator.done.status) == 0):
|
||||
|
@ -93,9 +89,7 @@ def main_generator(dut):
|
|||
yield dut.checker.length.storage.eq(16)
|
||||
for i in range(32):
|
||||
yield
|
||||
yield dut.checker.shoot.re.eq(1)
|
||||
yield
|
||||
yield dut.checker.shoot.re.eq(0)
|
||||
yield from toggle_re(dut.generator.start)
|
||||
for i in range(32):
|
||||
yield
|
||||
while((yield dut.checker.done.status) == 0):
|
||||
|
|
160
test/bist_tb.py
160
test/bist_tb.py
|
@ -1,5 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import random
|
||||
|
||||
from litex.gen import *
|
||||
|
||||
from litex.soc.interconnect.stream import *
|
||||
|
@ -8,58 +10,172 @@ from litedram.common import LiteDRAMWritePort, LiteDRAMReadPort
|
|||
from litedram.frontend.bist import LiteDRAMBISTGenerator
|
||||
from litedram.frontend.bist import LiteDRAMBISTChecker
|
||||
|
||||
from test.common import DRAMMemory
|
||||
from test.common import *
|
||||
|
||||
class TB(Module):
|
||||
def __init__(self):
|
||||
self.write_port = LiteDRAMWritePort(aw=32, dw=32)
|
||||
self.read_port = LiteDRAMReadPort(aw=32, dw=32)
|
||||
self.submodules.generator = LiteDRAMBISTGenerator(self.write_port)
|
||||
self.submodules.checker = LiteDRAMBISTChecker(self.read_port)
|
||||
self.submodules.generator = LiteDRAMBISTGenerator(self.write_port, random=True)
|
||||
self.submodules.checker = LiteDRAMBISTChecker(self.read_port, random=True)
|
||||
|
||||
|
||||
def main_generator(dut, mem):
|
||||
# Populate memory with random data
|
||||
random.seed(0)
|
||||
for i in range(0, len(mem.mem)):
|
||||
mem.mem[i] = random.randint(0, 2**mem.width)
|
||||
|
||||
def main_generator(dut):
|
||||
# init
|
||||
yield dut.generator.reset.storage.eq(1)
|
||||
yield dut.checker.reset.storage.eq(1)
|
||||
yield
|
||||
yield dut.generator.reset.storage.eq(0)
|
||||
yield dut.checker.reset.storage.eq(0)
|
||||
yield
|
||||
# write
|
||||
yield from reset_bist_module(dut.generator)
|
||||
|
||||
yield dut.generator.base.storage.eq(16)
|
||||
yield dut.generator.length.storage.eq(64)
|
||||
for i in range(8):
|
||||
yield
|
||||
yield dut.generator.shoot.re.eq(1)
|
||||
yield dut.generator.start.re.eq(1)
|
||||
yield
|
||||
yield dut.generator.shoot.re.eq(0)
|
||||
yield dut.generator.start.re.eq(0)
|
||||
for i in range(8):
|
||||
yield
|
||||
while((yield dut.generator.done.status) == 0):
|
||||
yield
|
||||
# read
|
||||
done = yield dut.generator.done.status
|
||||
assert done, done
|
||||
|
||||
# read with no errors
|
||||
yield from reset_bist_module(dut.checker)
|
||||
errors = yield dut.checker.err_count.status
|
||||
assert errors == 0, errors
|
||||
|
||||
yield dut.checker.base.storage.eq(16)
|
||||
yield dut.checker.length.storage.eq(64)
|
||||
for i in range(8):
|
||||
yield
|
||||
yield dut.checker.shoot.re.eq(1)
|
||||
yield
|
||||
yield dut.checker.shoot.re.eq(0)
|
||||
yield from toggle_re(dut.checker.start)
|
||||
for i in range(8):
|
||||
yield
|
||||
while((yield dut.checker.done.status) == 0):
|
||||
yield
|
||||
# check
|
||||
print("errors {:d}".format((yield dut.checker.error_count.status)))
|
||||
done = yield dut.checker.done.status
|
||||
assert done, done
|
||||
errors = yield dut.checker.err_count.status
|
||||
assert errors == 0, errors
|
||||
|
||||
yield
|
||||
yield
|
||||
|
||||
# read with one error
|
||||
yield from reset_bist_module(dut.checker)
|
||||
errors = yield dut.checker.err_count.status
|
||||
assert errors == 0, errors
|
||||
|
||||
print("mem.mem[20]", hex(mem.mem[20]))
|
||||
assert mem.mem[20] == 0xffff000f, hex(mem.mem[20])
|
||||
mem.mem[20] = 0x200 # Make position 20 an error
|
||||
|
||||
yield dut.checker.base.storage.eq(16)
|
||||
yield dut.checker.length.storage.eq(64)
|
||||
for i in range(8):
|
||||
yield
|
||||
yield from toggle_re(dut.checker.start)
|
||||
for i in range(8):
|
||||
yield
|
||||
while((yield dut.checker.done.status) == 0):
|
||||
yield
|
||||
done = yield dut.checker.done.status
|
||||
assert done, done
|
||||
errors = yield dut.checker.err_count.status
|
||||
assert errors == 1, errors
|
||||
|
||||
yield
|
||||
yield
|
||||
|
||||
# read with two errors
|
||||
yield from reset_bist_module(dut.checker)
|
||||
errors = yield dut.checker.err_count.status
|
||||
assert errors == 0, errors
|
||||
|
||||
print("mem.mem[21]", hex(mem.mem[21]))
|
||||
assert mem.mem[21] == 0xfff1ff1f, hex(mem.mem[21])
|
||||
mem.mem[21] = 0x210 # Make position 21 an error
|
||||
|
||||
yield dut.checker.base.storage.eq(16)
|
||||
yield dut.checker.length.storage.eq(64)
|
||||
for i in range(8):
|
||||
yield
|
||||
yield from toggle_re(dut.checker.start)
|
||||
for i in range(8):
|
||||
yield
|
||||
while((yield dut.checker.done.status) == 0):
|
||||
yield
|
||||
done = yield dut.checker.done.status
|
||||
assert done, done
|
||||
errors = yield dut.checker.err_count.status
|
||||
assert errors == 2, errors
|
||||
|
||||
yield
|
||||
yield
|
||||
|
||||
# read with two errors but halting on the first one
|
||||
yield from reset_bist_module(dut.checker)
|
||||
errors = yield dut.checker.err_count.status
|
||||
assert errors == 0, errors
|
||||
|
||||
yield dut.checker.base.storage.eq(16)
|
||||
yield dut.checker.length.storage.eq(64)
|
||||
for i in range(8):
|
||||
yield
|
||||
yield from toggle_re(dut.checker.start)
|
||||
for i in range(8):
|
||||
yield
|
||||
while((yield dut.checker.core.error) == 0):
|
||||
yield
|
||||
|
||||
err_addr = yield dut.checker.core._data_counter + dut.checker.core.base
|
||||
assert err_addr == 20, err_addr
|
||||
err_expect = yield dut.checker.core.expect
|
||||
assert err_expect == 0xffff000f, hex(err_expect)
|
||||
err_actual = yield dut.checker.core.actual
|
||||
assert err_actual == 0x200, err_actual
|
||||
yield
|
||||
errors = yield dut.checker.core.err_count
|
||||
assert errors == 1, errors
|
||||
|
||||
while((yield dut.checker.core.error) == 0):
|
||||
yield
|
||||
|
||||
err_addr = yield dut.checker.core._data_counter + dut.checker.core.base
|
||||
assert err_addr == 21, err_addr
|
||||
err_expect = yield dut.checker.core.expect
|
||||
assert err_expect == 0xfff1ff1f, hex(err_expect)
|
||||
err_actual = yield dut.checker.core.actual
|
||||
assert err_actual == 0x210, hex(err_actual)
|
||||
yield
|
||||
errors = yield dut.checker.core.err_count
|
||||
assert errors == 2, errors
|
||||
|
||||
while((yield dut.checker.done.status) == 0):
|
||||
yield
|
||||
|
||||
done = yield dut.checker.done.status
|
||||
assert done, done
|
||||
errors = yield dut.checker.err_count.status
|
||||
assert errors == 2, errors
|
||||
|
||||
yield
|
||||
yield
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
tb = TB()
|
||||
mem = DRAMMemory(32, 128)
|
||||
generators = {
|
||||
"sys" : [main_generator(tb),
|
||||
mem.write_generator(tb.write_port),
|
||||
mem.read_generator(tb.read_port)]
|
||||
"sys" : [
|
||||
main_generator(tb, mem),
|
||||
mem.write_generator(tb.write_port),
|
||||
mem.read_generator(tb.read_port),
|
||||
],
|
||||
}
|
||||
clocks = {"sys": 10}
|
||||
run_simulation(tb, generators, clocks, vcd_name="sim.vcd")
|
||||
|
|
|
@ -1,6 +1,28 @@
|
|||
from litex.gen import *
|
||||
|
||||
|
||||
def toggle_re(reg):
|
||||
resig = reg.re
|
||||
# Check that reset isn't set
|
||||
reval = yield resig
|
||||
assert not reval, reval
|
||||
yield resig.eq(1)
|
||||
yield
|
||||
yield resig.eq(0)
|
||||
|
||||
|
||||
def reset_bist_module(module):
|
||||
# Toggle the reset
|
||||
yield from toggle_re(module.reset)
|
||||
# Takes 8 more clock cycles for the reset to have an effect
|
||||
for i in range(8):
|
||||
yield
|
||||
|
||||
# Check some initial conditions are correct after reset.
|
||||
done = yield module.done.status
|
||||
assert not done, done
|
||||
|
||||
|
||||
def seed_to_data(seed, random=True, nbits=32):
|
||||
if nbits == 32:
|
||||
if random:
|
||||
|
|
Loading…
Reference in New Issue