add simple synthetizable BIST
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 15 Dec 2014 15:44:12 +0000 (16:44 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 15 Dec 2014 15:44:12 +0000 (16:44 +0100)
lib/sata/bist.py [new file with mode: 0644]
lib/sata/test/Makefile
lib/sata/test/bist_tb.py [new file with mode: 0644]

diff --git a/lib/sata/bist.py b/lib/sata/bist.py
new file mode 100644 (file)
index 0000000..2aed02f
--- /dev/null
@@ -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")
+                       )
+               )
index ffee2fdd47920ff513aef826e71c784132e2e9f9..ef772ae9665839697049c0696632cdfd0fbd3151 100644 (file)
@@ -20,6 +20,9 @@ link_tb:
 command_tb:
        $(CMD) command_tb.py
 
+bist_tb:
+       $(CMD) bist_tb.py
+
 all: crc_tb scrambler_tb link_tb command_tb
 
 clean:
diff --git a/lib/sata/test/bist_tb.py b/lib/sata/test/bist_tb.py
new file mode 100644 (file)
index 0000000..41d5af5
--- /dev/null
@@ -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)