mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
add simple synthetizable BIST
This commit is contained in:
parent
d4cd159c9c
commit
707b43178b
3 changed files with 140 additions and 0 deletions
91
lib/sata/bist.py
Normal file
91
lib/sata/bist.py
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.genlib.fsm import FSM, NextState
|
||||||
|
|
||||||
|
from lib.sata.common import *
|
||||||
|
|
||||||
|
class SATABIST(Module):
|
||||||
|
def __init__(self, sector_size=512, max_count=1):
|
||||||
|
self.sink = sink = Sink(command_rx_description(32))
|
||||||
|
self.source = source = Source(command_tx_description(32))
|
||||||
|
|
||||||
|
self.start = Signal()
|
||||||
|
self.sector = Signal(48)
|
||||||
|
self.done = Signal()
|
||||||
|
self.errors = Signal(32)
|
||||||
|
|
||||||
|
errors = Signal(32)
|
||||||
|
inc_errors = Signal()
|
||||||
|
self.sync += \
|
||||||
|
If(self.start,
|
||||||
|
errors.eq(0),
|
||||||
|
).Elif(inc_errors,
|
||||||
|
errors.eq(errors+1)
|
||||||
|
)
|
||||||
|
self.comb += self.errors.eq(errors)
|
||||||
|
|
||||||
|
cnt = Signal(32)
|
||||||
|
inc_cnt = Signal()
|
||||||
|
clr_cnt = Signal()
|
||||||
|
self.sync += \
|
||||||
|
If(clr_cnt,
|
||||||
|
cnt.eq(0),
|
||||||
|
).Elif(inc_cnt,
|
||||||
|
cnt.eq(cnt+1)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm = FSM(reset_state="IDLE")
|
||||||
|
self.submodules += fsm
|
||||||
|
|
||||||
|
fsm.act("IDLE",
|
||||||
|
self.done.eq(1),
|
||||||
|
clr_cnt.eq(1),
|
||||||
|
If(self.start,
|
||||||
|
NextState("SEND_WRITE_CMD_AND_DATA")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("SEND_WRITE_CMD_AND_DATA",
|
||||||
|
source.stb.eq(1),
|
||||||
|
source.sop.eq((cnt==0)),
|
||||||
|
source.eop.eq((cnt==(sector_size*max_count)//4-1)),
|
||||||
|
source.write.eq(1),
|
||||||
|
source.sector.eq(self.sector),
|
||||||
|
source.count.eq(max_count),
|
||||||
|
source.data.eq(cnt), #XXX use LFSR
|
||||||
|
inc_cnt.eq(source.ack),
|
||||||
|
If(source.stb & source.eop & source.ack,
|
||||||
|
NextState("WAIT_WRITE_ACK")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("WAIT_WRITE_ACK",
|
||||||
|
sink.ack.eq(1),
|
||||||
|
If(sink.stb & sink.write,
|
||||||
|
NextState("SEND_READ_CMD")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("SEND_READ_CMD",
|
||||||
|
source.stb.eq(1),
|
||||||
|
source.sop.eq(1),
|
||||||
|
source.eop.eq(1),
|
||||||
|
source.read.eq(1),
|
||||||
|
source.sector.eq(self.sector),
|
||||||
|
source.count.eq(max_count),
|
||||||
|
If(source.ack,
|
||||||
|
NextState("WAIT_READ_ACK")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("WAIT_READ_ACK",
|
||||||
|
clr_cnt.eq(1),
|
||||||
|
If(sink.stb & sink.read,
|
||||||
|
NextState("RECEIVE_READ_DATA")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("RECEIVE_READ_DATA",
|
||||||
|
sink.ack.eq(1),
|
||||||
|
inc_cnt.eq(sink.stb),
|
||||||
|
If(sink.stb & (sink.data != cnt), #XXX use LFSR
|
||||||
|
inc_errors.eq(1)
|
||||||
|
),
|
||||||
|
If(sink.stb & sink.eop,
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
|
@ -20,6 +20,9 @@ link_tb:
|
||||||
command_tb:
|
command_tb:
|
||||||
$(CMD) command_tb.py
|
$(CMD) command_tb.py
|
||||||
|
|
||||||
|
bist_tb:
|
||||||
|
$(CMD) bist_tb.py
|
||||||
|
|
||||||
all: crc_tb scrambler_tb link_tb command_tb
|
all: crc_tb scrambler_tb link_tb command_tb
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
46
lib/sata/test/bist_tb.py
Normal file
46
lib/sata/test/bist_tb.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import random, copy
|
||||||
|
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.genlib.record import *
|
||||||
|
from migen.sim.generic import run_simulation
|
||||||
|
|
||||||
|
from lib.sata.common import *
|
||||||
|
from lib.sata.link import SATALink
|
||||||
|
from lib.sata.transport import SATATransport
|
||||||
|
from lib.sata.command import SATACommand
|
||||||
|
from lib.sata.bist import SATABIST
|
||||||
|
|
||||||
|
from lib.sata.test.hdd import *
|
||||||
|
from lib.sata.test.common import *
|
||||||
|
|
||||||
|
class TB(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.submodules.hdd = HDD(
|
||||||
|
link_debug=False, link_random_level=50,
|
||||||
|
transport_debug=False, transport_loopback=False,
|
||||||
|
hdd_debug=True)
|
||||||
|
self.submodules.link = SATALink(self.hdd.phy)
|
||||||
|
self.submodules.transport = SATATransport(self.link)
|
||||||
|
self.submodules.command = SATACommand(self.transport)
|
||||||
|
self.submodules.bist = SATABIST(sector_size=512, max_count=1)
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
self.bist.source.connect(self.command.sink),
|
||||||
|
self.command.source.connect(self.bist.sink)
|
||||||
|
]
|
||||||
|
|
||||||
|
def gen_simulation(self, selfp):
|
||||||
|
hdd = self.hdd
|
||||||
|
hdd.malloc(0, 64)
|
||||||
|
while True:
|
||||||
|
selfp.bist.start = 1
|
||||||
|
yield
|
||||||
|
selfp.bist.start = 0
|
||||||
|
yield
|
||||||
|
while selfp.bist.done == 0:
|
||||||
|
yield
|
||||||
|
print("errors: {}".format(selfp.bist.errors))
|
||||||
|
selfp.bist.sector += 1
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_simulation(TB(), ncycles=4096, vcd_name="my.vcd", keep_files=True)
|
Loading…
Reference in a new issue