2015-01-16 17:52:41 -05:00
|
|
|
from litesata.common import *
|
|
|
|
from litesata.core.link.scrambler import Scrambler
|
2015-01-14 03:19:41 -05:00
|
|
|
|
|
|
|
from migen.fhdl.decorators import ModuleDecorator
|
2014-12-23 12:26:07 -05:00
|
|
|
from migen.bank.description import *
|
2014-12-15 13:04:45 -05:00
|
|
|
|
2015-01-16 17:52:41 -05:00
|
|
|
class LiteSATABISTGenerator(Module):
|
2015-01-14 03:19:41 -05:00
|
|
|
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-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-20 11:14:01 -05:00
|
|
|
self.aborted = 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
|
|
|
|
2014-12-19 16:50:35 -05:00
|
|
|
self.counter = counter = Counter(bits_sign=32)
|
2014-12-15 13:04:45 -05:00
|
|
|
|
2014-12-19 16:50:35 -05:00
|
|
|
self.scrambler = scrambler = InsertReset(Scrambler())
|
2014-12-15 13:04:45 -05:00
|
|
|
self.comb += [
|
|
|
|
scrambler.reset.eq(counter.reset),
|
|
|
|
scrambler.ce.eq(counter.ce)
|
|
|
|
]
|
2014-12-15 10:44:12 -05:00
|
|
|
|
2014-12-19 16:50:35 -05:00
|
|
|
self.fsm = fsm = FSM(reset_state="IDLE")
|
2014-12-15 10:44:12 -05:00
|
|
|
fsm.act("IDLE",
|
|
|
|
self.done.eq(1),
|
2014-12-15 13:04:45 -05:00
|
|
|
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),
|
2014-12-15 13:04:45 -05:00
|
|
|
If(sink.stb,
|
2015-01-16 12:14:13 -05:00
|
|
|
NextState("IDLE")
|
2014-12-15 10:44:12 -05:00
|
|
|
)
|
|
|
|
)
|
2015-01-20 11:14:01 -05:00
|
|
|
self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed))
|
2015-01-14 03:19:41 -05:00
|
|
|
|
2015-01-16 17:52:41 -05:00
|
|
|
class LiteSATABISTChecker(Module):
|
2015-01-14 03:19:41 -05:00
|
|
|
def __init__(self, sata_master_port):
|
|
|
|
self.start = Signal()
|
|
|
|
self.sector = Signal(48)
|
|
|
|
self.count = Signal(16)
|
|
|
|
self.random = Signal()
|
|
|
|
|
|
|
|
self.done = Signal()
|
2015-01-20 11:14:01 -05:00
|
|
|
self.aborted = Signal()
|
2015-01-14 03:19:41 -05:00
|
|
|
self.errors = Signal(32)
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
source, sink = sata_master_port.source, sata_master_port.sink
|
|
|
|
|
|
|
|
self.counter = counter = Counter(bits_sign=32)
|
|
|
|
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),
|
|
|
|
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),
|
2014-12-15 13:04:45 -05:00
|
|
|
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)
|
2014-12-15 13:04:45 -05:00
|
|
|
),
|
|
|
|
If(sink.eop,
|
2015-01-06 10:48:19 -05:00
|
|
|
If(sink.last,
|
2015-01-16 12:14:13 -05:00
|
|
|
NextState("IDLE")
|
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 13:04:45 -05:00
|
|
|
)
|
2014-12-15 10:44:12 -05:00
|
|
|
)
|
|
|
|
)
|
2015-01-20 11:14:01 -05:00
|
|
|
self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed))
|
2014-12-23 12:26:07 -05:00
|
|
|
|
2015-01-16 17:52:41 -05:00
|
|
|
class LiteSATABISTUnitCSR(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)
|
2015-01-06 12:17:11 -05:00
|
|
|
self._count = CSRStorage(16)
|
2015-01-14 03:19:41 -05:00
|
|
|
self._random = CSRStorage()
|
2015-01-07 16:15:57 -05:00
|
|
|
self._done = CSRStatus()
|
2015-01-20 11:14:01 -05:00
|
|
|
self._aborted = CSRStatus()
|
2014-12-23 12:26:07 -05:00
|
|
|
self._errors = CSRStatus(32)
|
2015-01-16 12:14:13 -05:00
|
|
|
self._cycles = CSRStatus(32)
|
2014-12-23 12:26:07 -05:00
|
|
|
|
2015-01-14 03:19:41 -05:00
|
|
|
###
|
2015-01-16 17:52:41 -05:00
|
|
|
|
2015-01-14 03:19:41 -05:00
|
|
|
self.bist_unit = bist_unit
|
2014-12-23 12:26:07 -05:00
|
|
|
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.random.eq(self._random.storage),
|
|
|
|
|
|
|
|
self._done.status.eq(bist_unit.done),
|
2015-01-20 11:14:01 -05:00
|
|
|
self._aborted.status.eq(bist_unit.aborted),
|
2015-01-14 03:19:41 -05:00
|
|
|
self._errors.status.eq(bist_unit.errors)
|
2014-12-23 12:26:07 -05:00
|
|
|
]
|
2015-01-14 03:19:41 -05:00
|
|
|
|
2015-01-16 12:14:13 -05:00
|
|
|
self.cycles_counter = Counter(self._cycles.status)
|
|
|
|
self.sync += [
|
|
|
|
self.cycles_counter.reset.eq(bist_unit.start),
|
|
|
|
self.cycles_counter.ce.eq(~bist_unit.done)
|
|
|
|
]
|
2015-01-16 16:49:34 -05:00
|
|
|
|
2015-01-16 17:52:41 -05:00
|
|
|
class LiteSATABISTIdentify(Module):
|
2015-01-16 16:49:34 -05:00
|
|
|
def __init__(self, sata_master_port):
|
|
|
|
self.start = Signal()
|
|
|
|
self.done = Signal()
|
|
|
|
|
|
|
|
self.fifo = fifo = SyncFIFO([("data", 32)], 512, buffered=True)
|
|
|
|
self.source = self.fifo.source
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
source, sink = sata_master_port.source, sata_master_port.sink
|
|
|
|
|
|
|
|
self.fsm = fsm = FSM(reset_state="IDLE")
|
|
|
|
fsm.act("IDLE",
|
|
|
|
self.done.eq(1),
|
|
|
|
If(self.start,
|
|
|
|
NextState("SEND_CMD")
|
|
|
|
)
|
|
|
|
)
|
|
|
|
self.comb += [
|
|
|
|
source.sop.eq(1),
|
|
|
|
source.eop.eq(1),
|
|
|
|
source.identify.eq(1),
|
|
|
|
]
|
|
|
|
fsm.act("SEND_CMD",
|
|
|
|
source.stb.eq(1),
|
|
|
|
If(source.stb & source.ack,
|
|
|
|
NextState("WAIT_ACK")
|
|
|
|
)
|
|
|
|
)
|
|
|
|
fsm.act("WAIT_ACK",
|
|
|
|
If(sink.stb & sink.identify,
|
|
|
|
NextState("RECEIVE_DATA")
|
|
|
|
)
|
|
|
|
)
|
|
|
|
self.comb += fifo.sink.data.eq(sink.data)
|
|
|
|
fsm.act("RECEIVE_DATA",
|
|
|
|
sink.ack.eq(fifo.sink.ack),
|
|
|
|
If(sink.stb,
|
|
|
|
fifo.sink.stb.eq(1),
|
|
|
|
If(sink.eop,
|
|
|
|
NextState("IDLE")
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2015-01-16 17:52:41 -05:00
|
|
|
class LiteSATABISTIdentifyCSR(Module, AutoCSR):
|
2015-01-16 16:49:34 -05:00
|
|
|
def __init__(self, bist_identify):
|
|
|
|
self._start = CSR()
|
|
|
|
self._done = CSRStatus()
|
|
|
|
self._source_stb = CSRStatus()
|
|
|
|
self._source_ack = CSR()
|
|
|
|
self._source_data = CSRStatus(32)
|
|
|
|
|
|
|
|
###
|
2015-01-16 17:52:41 -05:00
|
|
|
|
2015-01-16 16:49:34 -05:00
|
|
|
self.bist_identify = bist_identify
|
|
|
|
self.comb += [
|
|
|
|
bist_identify.start.eq(self._start.r & self._start.re),
|
|
|
|
self._done.status.eq(bist_identify.done),
|
|
|
|
|
|
|
|
self._source_stb.status.eq(bist_identify.source.stb),
|
|
|
|
self._source_data.status.eq(bist_identify.source.data),
|
|
|
|
bist_identify.source.ack.eq(self._source_ack.r & self._source_ack.re)
|
|
|
|
]
|
|
|
|
|
2015-01-16 17:52:41 -05:00
|
|
|
class LiteSATABIST(Module, AutoCSR):
|
|
|
|
def __init__(self, crossbar, with_csr=False):
|
|
|
|
generator = LiteSATABISTGenerator(crossbar.get_port())
|
|
|
|
checker = LiteSATABISTChecker(crossbar.get_port())
|
|
|
|
identify = LiteSATABISTIdentify(crossbar.get_port())
|
|
|
|
if with_csr:
|
|
|
|
self.generator = LiteSATABISTUnitCSR(generator)
|
|
|
|
self.checker = LiteSATABISTUnitCSR(checker)
|
|
|
|
self.identify = LiteSATABISTIdentifyCSR(identify)
|
2015-01-14 03:19:41 -05:00
|
|
|
else:
|
|
|
|
self.generator = generator
|
|
|
|
self.checker = checker
|
2015-01-16 16:49:34 -05:00
|
|
|
self.identify = identify
|