-- 
Robert Jordens.
From beaacd7754be0255a98cde82a06611f1f0638508 Mon Sep 17 00:00:00 2001
From: Robert Jordens <jord...@gmail.com>
Date: Fri, 8 Nov 2013 00:56:17 -0700
Subject: [PATCH 03/11] spiflash: add read-only variable data width spi flash

Signed-off-by: Robert Jordens <jord...@gmail.com>
---
 misoclib/spiflash/__init__.py | 131 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 131 insertions(+)
 create mode 100644 misoclib/spiflash/__init__.py

diff --git a/misoclib/spiflash/__init__.py b/misoclib/spiflash/__init__.py
new file mode 100644
index 0000000..bc83594
--- /dev/null
+++ b/misoclib/spiflash/__init__.py
@@ -0,0 +1,131 @@
+from migen.fhdl.std import *
+from migen.bus.transactions import *
+from migen.bus import wishbone
+from migen.genlib.misc import timeline
+from migen.genlib.record import Record
+
+
+class SpiFlash(Module):
+	def __init__(self, pads, cmd=0xfffefeff, cmd_width=32, addr_width=24,
+			dummy=15, div=2):
+		"""
+		Simple read-only SPI flash, e.g. N25Q128 on the LX9 Microboard.
+
+		Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
+		Read). Only supports mode0 (cpol=0, cpha=0).
+
+		`cmd` is the read instruction. Since everything is transmitted on all
+		dq lines (cmd, adr and data), extend/interleave cmd to full pads.dq
+		width even if dq1-dq3 are don't care during the command phase:
+		For example, for N25Q128, 0xeb is the quad i/o fast read, and
+		extended to 4 bits (dq1,dq2,dq3 high) is: 0xfffefeff
+		"""
+		self.bus = bus = wishbone.Interface()
+
+		##
+
+		wbone_width = flen(bus.dat_r)
+		spi_width = flen(pads.dq)
+
+		pads.cs_n.reset = 1
+
+		dq = TSTriple(spi_width)
+		self.specials.dq = dq.get_tristate(pads.dq)
+
+		sr = Signal(max(cmd_width, addr_width, wbone_width))
+		self.comb += [
+				bus.dat_r.eq(sr[:wbone_width]),
+				dq.o.eq(sr[-spi_width:]),
+				]
+
+		if div == 1:
+			i = 0
+			self.comb += pads.clk.eq(~ClockSignal())
+			self.sync += sr.eq(Cat(dq.i, sr[:-spi_width]))
+		else:
+			i = Signal(max=div)
+			dqi = Signal(spi_width)
+			self.sync += [
+					If(i == div//2 - 1,
+						pads.clk.eq(1),
+						dqi.eq(dq.i),
+					),
+					If(i == div - 1,
+						i.eq(0),
+						pads.clk.eq(0),
+						sr.eq(Cat(dqi, sr[:-spi_width]))
+					).Else(
+						i.eq(i + 1),
+					),
+				]
+
+		# spi is byte-addressed, prefix by zeros
+		z = Replicate(0, log2_int(wbone_width//8))
+
+		seq = [
+			(cmd_width//spi_width*div,
+				[dq.oe.eq(1), pads.cs_n.eq(0), sr[-cmd_width:].eq(cmd)]),
+			(addr_width//spi_width*div,
+				[sr[-addr_width:].eq(Cat(z, bus.adr))]),
+			((dummy + wbone_width//spi_width)*div,
+				[dq.oe.eq(0)]),
+			(1,
+				[bus.ack.eq(1), pads.cs_n.eq(1)]),
+			(div, # tSHSL!
+				[bus.ack.eq(0)]),
+			(0,
+				[]),
+		]
+
+		# accumulate timeline deltas
+		t, tseq = 0, []
+		for dt, a in seq:
+			tseq.append((t, a))
+			t += dt
+
+		self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
+
+
+
+class SpiFlashTB(Module):
+	def __init__(self):
+		self.submodules.master = wishbone.Initiator(self.gen_reads())
+		self.pads = Record([("cs_n", 1), ("clk", 1), ("dq", 4)])
+		self.submodules.slave = SpiFlash(self.pads)
+		self.submodules.tap = wishbone.Tap(self.slave.bus)
+		self.submodules.intercon = wishbone.InterconnectPointToPoint(
+				self.master.bus, self.slave.bus)
+		self.cycle = 0
+
+	def gen_reads(self):
+		for a in range(10):
+			t = TRead(a)
+			yield t
+			print("read {} in {} cycles(s)".format(t.data, t.latency))
+
+	def do_simulation(self, s):
+		if s.rd(self.pads.cs_n):
+			self.cycle = 0
+		else:
+			self.cycle += 1
+			if not s.rd(self.slave.dq.oe):
+				s.wr(self.slave.dq.i, self.cycle & 0xf)
+		s.interrupt = self.master.done
+
+
+def _main():
+	from migen.sim.generic import Simulator, TopLevel
+	from migen.fhdl import verilog
+
+	pads = Record([("cs_n", 1), ("clk", 1), ("dq", 4)])
+	s = SpiFlash(pads)
+	print(verilog.convert(s, ios={pads.clk, pads.cs_n, pads.dq, s.bus.adr,
+		s.bus.dat_r, s.bus.cyc, s.bus.ack, s.bus.stb}))
+
+	tb = SpiFlashTB()
+	sim = Simulator(tb, TopLevel("spiflash.vcd"))
+	sim.run()
+
+
+if __name__ == "__main__":
+	_main()
-- 
1.8.3.2

_______________________________________________
Devel mailing list
Devel@lists.milkymist.org
https://ssl.serverraum.org/lists/listinfo/devel

Reply via email to