litex/lib/sata/bist.py

190 lines
4.4 KiB
Python
Raw Normal View History

2014-12-15 10:44:12 -05:00
from lib.sata.common import *
from lib.sata.link.scrambler import Scrambler
2015-01-14 03:19:41 -05:00
from migen.fhdl.decorators import ModuleDecorator
from migen.bank.description import *
2015-01-14 03:19:41 -05:00
class SATABISTGenerator(Module):
def __init__(self, sata_master_port):
self.start = Signal()
2014-12-15 10:44:12 -05:00
self.sector = Signal(48)
2015-01-06 10:48:19 -05:00
self.count = Signal(16)
2015-01-07 16:15:57 -05:00
self.loops = Signal(8)
2015-01-14 03:19:41 -05:00
self.random = Signal()
2015-01-07 16:15:57 -05:00
2014-12-15 10:44:12 -05:00
self.done = Signal()
2015-01-14 03:19:41 -05:00
self.errors = Signal(32) # Note: Not used for writes
2015-01-07 16:15:57 -05:00
2015-01-14 03:19:41 -05:00
###
2015-01-07 16:15:57 -05:00
2015-01-14 03:19:41 -05:00
source, sink = sata_master_port.source, sata_master_port.sink
2014-12-15 10:44:12 -05:00
self.counter = counter = Counter(bits_sign=32)
2015-01-07 16:15:57 -05:00
self.loops_counter = loops_counter = Counter(bits_sign=8)
self.scrambler = scrambler = InsertReset(Scrambler())
self.comb += [
scrambler.reset.eq(counter.reset),
scrambler.ce.eq(counter.ce)
]
2014-12-15 10:44:12 -05:00
self.fsm = fsm = FSM(reset_state="IDLE")
2014-12-15 10:44:12 -05:00
fsm.act("IDLE",
self.done.eq(1),
counter.reset.eq(1),
2015-01-07 16:15:57 -05:00
loops_counter.reset.eq(1),
2015-01-14 03:19:41 -05:00
If(self.start,
NextState("SEND_CMD_AND_DATA")
2014-12-15 10:44:12 -05:00
)
)
2015-01-14 03:19:41 -05:00
self.comb += [
2015-01-07 16:15:57 -05:00
source.sop.eq(counter.value == 0),
source.eop.eq(counter.value == (logical_sector_size//4*self.count)-1),
2014-12-15 10:44:12 -05:00
source.write.eq(1),
source.sector.eq(self.sector),
2014-12-15 13:48:22 -05:00
source.count.eq(self.count),
2015-01-14 03:19:41 -05:00
If(self.random,
source.data.eq(scrambler.value)
).Else(
source.data.eq(counter.value)
)
]
fsm.act("SEND_CMD_AND_DATA",
source.stb.eq(1),
2015-01-07 16:15:57 -05:00
If(source.stb & source.ack,
counter.ce.eq(1),
If(source.eop,
2015-01-14 03:19:41 -05:00
NextState("WAIT_ACK")
2015-01-07 16:15:57 -05:00
)
2014-12-15 10:44:12 -05:00
)
)
2015-01-14 03:19:41 -05:00
fsm.act("WAIT_ACK",
2014-12-15 10:44:12 -05:00
sink.ack.eq(1),
If(sink.stb,
2015-01-07 16:15:57 -05:00
loops_counter.ce.eq(1),
If(loops_counter.value == (self.loops-1),
NextState("IDLE")
).Else(
2015-01-07 16:15:57 -05:00
counter.reset.eq(1),
2015-01-14 03:19:41 -05:00
NextState("SEND_CMD_AND_DATA")
)
2014-12-15 10:44:12 -05:00
)
)
2015-01-14 03:19:41 -05:00
class SATABISTChecker(Module):
def __init__(self, sata_master_port):
self.start = Signal()
self.sector = Signal(48)
self.count = Signal(16)
self.loops = Signal(8)
self.random = Signal()
self.done = Signal()
self.errors = Signal(32)
###
source, sink = sata_master_port.source, sata_master_port.sink
self.counter = counter = Counter(bits_sign=32)
self.loops_counter = loops_counter = Counter(bits_sign=8)
self.error_counter = Counter(self.errors, bits_sign=32)
self.scrambler = scrambler = InsertReset(Scrambler())
self.comb += [
scrambler.reset.eq(counter.reset),
scrambler.ce.eq(counter.ce)
]
self.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
self.done.eq(1),
counter.reset.eq(1),
loops_counter.reset.eq(1),
If(self.start,
self.error_counter.reset.eq(1),
NextState("SEND_CMD")
)
)
self.comb += [
2014-12-15 10:44:12 -05:00
source.sop.eq(1),
source.eop.eq(1),
source.read.eq(1),
source.sector.eq(self.sector),
2014-12-15 13:48:22 -05:00
source.count.eq(self.count),
2015-01-14 03:19:41 -05:00
]
fsm.act("SEND_CMD",
source.stb.eq(1),
2014-12-15 10:44:12 -05:00
If(source.ack,
2015-01-06 10:48:19 -05:00
counter.reset.eq(1),
2015-01-14 03:19:41 -05:00
NextState("WAIT_ACK")
2014-12-15 10:44:12 -05:00
)
)
2015-01-14 03:19:41 -05:00
fsm.act("WAIT_ACK",
2014-12-15 10:44:12 -05:00
If(sink.stb & sink.read,
2015-01-14 03:19:41 -05:00
NextState("RECEIVE_DATA")
2014-12-15 10:44:12 -05:00
)
)
2015-01-14 03:19:41 -05:00
expected_data = Signal(32)
self.comb += \
If(self.random,
expected_data.eq(scrambler.value)
).Else(
expected_data.eq(counter.value)
)
fsm.act("RECEIVE_DATA",
2014-12-15 10:44:12 -05:00
sink.ack.eq(1),
If(sink.stb,
counter.ce.eq(1),
2015-01-14 03:19:41 -05:00
If(sink.data != expected_data,
2015-01-07 16:15:57 -05:00
self.error_counter.ce.eq(1)
),
If(sink.eop,
2015-01-06 10:48:19 -05:00
If(sink.last,
2015-01-07 16:15:57 -05:00
loops_counter.ce.eq(1),
If(loops_counter.value == (self.loops-1),
NextState("IDLE")
).Else(
2015-01-14 03:19:41 -05:00
NextState("SEND_CMD")
2015-01-07 16:15:57 -05:00
)
2015-01-06 10:48:19 -05:00
).Else(
2015-01-14 03:19:41 -05:00
NextState("WAIT_ACK")
2015-01-06 10:48:19 -05:00
)
)
2014-12-15 10:44:12 -05:00
)
)
2015-01-07 16:15:57 -05:00
class SATABISTControl(Module, AutoCSR):
2015-01-14 03:19:41 -05:00
def __init__(self, bist_unit):
self._start = CSR()
2015-01-07 16:15:57 -05:00
self._sector = CSRStorage(48)
self._count = CSRStorage(16)
2015-01-14 03:19:41 -05:00
self._random = CSRStorage()
2015-01-07 16:15:57 -05:00
self._loops = CSRStorage(8)
self._done = CSRStatus()
self._errors = CSRStatus(32)
2015-01-14 03:19:41 -05:00
###
self.bist_unit = bist_unit
self.comb += [
2015-01-14 03:19:41 -05:00
bist_unit.start.eq(self._start.r & self._start.re),
bist_unit.sector.eq(self._sector.storage),
bist_unit.count.eq(self._count.storage),
bist_unit.loops.eq(self._loops.storage),
bist_unit.random.eq(self._random.storage),
self._done.status.eq(bist_unit.done),
self._errors.status.eq(bist_unit.errors)
]
2015-01-14 03:19:41 -05:00
class SATABIST(Module, AutoCSR):
def __init__(self, sata_master_ports, with_control=False):
generator = SATABISTGenerator(sata_master_ports[0])
checker = SATABISTChecker(sata_master_ports[1])
if with_control:
self.generator = SATABISTControl(generator)
self.checker = SATABISTControl(checker)
else:
self.generator = generator
self.checker = checker