norflash: add support for writes
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 30 Nov 2013 19:37:56 +0000 (20:37 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 30 Nov 2013 19:37:56 +0000 (20:37 +0100)
misoclib/norflash/__init__.py [deleted file]
misoclib/norflash16/__init__.py [new file with mode: 0644]
targets/mlabs_video.py

diff --git a/misoclib/norflash/__init__.py b/misoclib/norflash/__init__.py
deleted file mode 100644 (file)
index 241d6ac..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.misc import timeline
-
-class NorFlash(Module):
-       def __init__(self, pads, rd_timing):
-               self.bus = wishbone.Interface()
-       
-               ###
-
-               adr_width = flen(pads.adr) + 1
-               self.comb += [pads.oe_n.eq(0), pads.we_n.eq(1),
-                       pads.ce_n.eq(0)]
-               self.sync += timeline(self.bus.cyc & self.bus.stb, [
-                       (0, [pads.adr.eq(Cat(0, self.bus.adr[:adr_width-2]))]),
-                       (rd_timing, [
-                               self.bus.dat_r[16:].eq(pads.d),
-                               pads.adr.eq(Cat(1, self.bus.adr[:adr_width-2]))]),
-                       (2*rd_timing, [
-                               self.bus.dat_r[:16].eq(pads.d),
-                               self.bus.ack.eq(1)]),
-                       (2*rd_timing + 1, [
-                               self.bus.ack.eq(0)])
-               ])
diff --git a/misoclib/norflash16/__init__.py b/misoclib/norflash16/__init__.py
new file mode 100644 (file)
index 0000000..ba0f009
--- /dev/null
@@ -0,0 +1,105 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.genlib.fsm import FSM, NextState
+
+class NorFlash16(Module):
+       def __init__(self, pads, rd_timing, wr_timing):
+               self.bus = wishbone.Interface()
+
+               ###
+
+               adr_width = flen(pads.adr) + 1
+               adr_r = Signal(adr_width) # in 16-bit memory words
+               data = TSTriple(16)
+               lsb = Signal()
+
+               self.specials += data.get_tristate(pads.d)
+               self.comb += [
+                       pads.adr.eq(Cat(lsb, adr_r[1:])),
+                       data.oe.eq(pads.oe_n),
+                       pads.ce_n.eq(0)
+               ]
+
+               load_lo = Signal()
+               load_hi = Signal()
+               store = Signal()
+
+               pads.oe_n.reset, pads.we_n.reset = 1, 1
+               self.sync += [
+                       pads.oe_n.eq(1),
+                       pads.we_n.eq(1),
+
+                       # Register data/address to avoid off-chip glitches
+                       If(self.bus.cyc & self.bus.stb,
+                               adr_r.eq(Cat(0, self.bus.adr)),
+                               If(self.bus.we,
+                                       # Only 16-bit writes are supported. Assume sel=0011 or 1100.
+                                       If(self.bus.sel[0],
+                                               data.o.eq(self.bus.dat_w[:16])
+                                       ).Else(
+                                               data.o.eq(self.bus.dat_w[16:])
+                                       )
+                               ).Else(
+                                       pads.oe_n.eq(0)
+                               )
+                       ),
+
+                       If(load_lo, self.bus.dat_r[:16].eq(data.i)),
+                       If(load_hi, self.bus.dat_r[16:].eq(data.i)),
+                       If(store, pads.we_n.eq(0))
+               ]
+
+               # Typical timing of the flash chips:
+               #  - 110ns address to output
+               #  - 50ns write pulse width
+               counter = Signal(max=max(rd_timing, wr_timing)+1)
+               counter_en = Signal()
+               counter_wr_mode = Signal()
+               counter_done = Signal()
+               self.comb += counter_done.eq(counter == Mux(counter_wr_mode, wr_timing, rd_timing))
+               self.sync += If(counter_en & ~counter_done,
+                               counter.eq(counter + 1)
+                       ).Else(
+                               counter.eq(0)
+                       )
+
+               fsm = FSM()
+               self.submodules += fsm
+
+               fsm.act("IDLE",
+                       If(self.bus.cyc & self.bus.stb,
+                               If(self.bus.we,
+                                       NextState("WR")
+                               ).Else(
+                                       NextState("RD_HI")
+                               )
+                       )
+               )
+               fsm.act("RD_HI",
+                       lsb.eq(0),
+                       counter_en.eq(1),
+                       If(counter_done,
+                               load_hi.eq(1),
+                               NextState("RD_LO")
+                       )
+               )
+               fsm.act("RD_LO",
+                       lsb.eq(1),
+                       counter_en.eq(1),
+                       If(counter_done,
+                               load_lo.eq(1),
+                               NextState("ACK")
+                       )
+               )
+               fsm.act("WR",
+                       # supported cases: sel=0011 [lsb=1] and sel=1100 [lsb=0]
+                       lsb.eq(self.bus.sel[0]),
+                       counter_wr_mode.eq(1),
+                       counter_en.eq(1),
+                       store.eq(1),
+                       If(counter_done, NextState("ACK"))
+               )
+               fsm.act("ACK",
+                       self.bus.ack.eq(1),
+                       NextState("IDLE")
+               )
index 7bc675f14878f3c26ff93d9d8f841b4285c53a62..727449e5618aae0964c305ed8b580fba9bda6ae0 100644 (file)
@@ -4,7 +4,7 @@ from fractions import Fraction
 from migen.fhdl.std import *
 from mibuild.generic_platform import ConstraintError
 
-from misoclib import lasmicon, mxcrg, norflash, s6ddrphy, minimac3, framebuffer, dvisampler, gpio
+from misoclib import lasmicon, mxcrg, norflash16, s6ddrphy, minimac3, framebuffer, dvisampler, gpio
 from misoclib.gensoc import SDRAMSoC
 
 class _MXClockPads:
@@ -72,7 +72,8 @@ class MiniSoC(SDRAMSoC):
                self.register_sdram_phy(self.ddrphy.dfi, self.ddrphy.phy_settings, sdram_geom, sdram_timing)
 
                # Wishbone
-               self.submodules.norflash = norflash.NorFlash(platform.request("norflash"), 12)
+               self.submodules.norflash = norflash16.NorFlash16(platform.request("norflash"),
+                       self.ns(110), self.ns(50))
                self.submodules.minimac = minimac3.MiniMAC(platform.request("eth"))
                self.register_rom(self.norflash.bus)
                self.add_wb_slave(lambda a: a[26:29] == 3, self.minimac.membus)