invert cs_n pin in Tercel
[soc.git] / src / soc / bus / tercel.py
index a6ba9bef6ce7042e584bdcee999792bfe79f0a8b..3e71a3bfb61718c31c48de037bb01bb25e27904f 100644 (file)
@@ -15,6 +15,7 @@ from nmigen_soc.wishbone.bus import Interface
 from nmigen_soc.memory import MemoryMap
 from nmigen.utils import log2_int
 from nmigen.cli import rtlil, verilog
+from nmutil.byterev import byte_reverse
 import os
 
 __all__ = ["Tercel"]
@@ -45,10 +46,11 @@ class Tercel(Elaboratable):
         # TODO, sort this out.
         assert clk_freq is not None
         clk_freq = round(clk_freq)
-        self.clk_freq = Const(clk_freq, clk_freq.bit_length())
+        self.clk_freq = Const(clk_freq, 32) #clk_freq.bit_length())
 
         # set up the wishbone busses
         if features is None:
+            #features = frozenset({'err'}) # sigh
             features = frozenset()
         if bus is None:
             bus = Interface(addr_width=spi_region_addr_width,
@@ -83,6 +85,7 @@ class Tercel(Elaboratable):
         self.dq_in = Signal(4)
         self.cs_n_out = Signal()      # Slave select
         self.spi_clk = Signal()       # Clock
+        self.dbg_port = Signal(8)     # debug info
 
         # pins resource
         self.pins = pins
@@ -106,6 +109,16 @@ class Tercel(Elaboratable):
         # wb address is in words, offset is in bytes
         comb += spi_bus_adr.eq(bus.adr - (self.adr_offset >> 2))
 
+        # urrr.... byte-reverse the config bus and data bus read/write
+        cdat_w = Signal.like(cfg_bus.dat_w)
+        cdat_r = Signal.like(cfg_bus.dat_r)
+        dat_w = Signal.like(bus.dat_w)
+        dat_r = Signal.like(bus.dat_r)
+        comb += cdat_w.eq(byte_reverse(m, "rv_cdat_w", cfg_bus.dat_w, 4))
+        comb += cfg_bus.dat_r.eq(byte_reverse(m, "rv_cdat_r", cdat_r, 4))
+        comb += dat_w.eq(byte_reverse(m, "rv_dat_w", bus.dat_w, 4))
+        comb += bus.dat_r.eq(byte_reverse(m, "rv_dat_r", dat_r, 4))
+
         # create definition of external verilog Tercel code here, so that
         # nmigen understands I/O directions (defined by i_ and o_ prefixes)
         idx, bus = self.idx, self.bus
@@ -118,31 +131,36 @@ class Tercel(Elaboratable):
                             i_peripheral_reset=ResetSignal(),
 
                             # SPI region Wishbone bus signals
-                            i_wishbone_adr_i=spi_bus_adr,
-                            i_wishbone_dat_i=bus.dat_w,
-                            i_wishbone_sel_i=bus.sel,
-                            o_wishbone_dat_o=bus.dat_r,
-                            i_wishbone_we_i=bus.we,
-                            i_wishbone_stb_i=bus.stb,
-                            i_wishbone_cyc_i=bus.cyc,
-                            o_wishbone_ack_o=bus.ack,
+                            i_wishbone_adr=spi_bus_adr,
+                            i_wishbone_dat_w=dat_w,
+                            i_wishbone_sel=bus.sel,
+                            o_wishbone_dat_r=dat_r,
+                            i_wishbone_we=bus.we,
+                            i_wishbone_stb=bus.stb,
+                            i_wishbone_cyc=bus.cyc,
+                            o_wishbone_ack=bus.ack,
+                            #o_wishbone_err=bus.err,
 
                             # Configuration region Wishbone bus signals
-                            i_cfg_wishbone_adr_i=cfg_bus.adr,
-                            i_cfg_wishbone_dat_i=cfg_bus.dat_w,
-                            i_cfg_wishbone_sel_i=cfg_bus.sel,
-                            o_cfg_wishbone_dat_o=cfg_bus.dat_r,
-                            i_cfg_wishbone_we_i=cfg_bus.we,
-                            i_cfg_wishbone_stb_i=cfg_bus.stb,
-                            i_cfg_wishbone_cyc_i=cfg_bus.cyc,
-                            o_cfg_wishbone_ack_o=cfg_bus.ack,
+                            i_cfg_wishbone_adr=cfg_bus.adr,
+                            i_cfg_wishbone_dat_w=cdat_w,
+                            i_cfg_wishbone_sel=cfg_bus.sel,
+                            o_cfg_wishbone_dat_r=cdat_r,
+                            i_cfg_wishbone_we=cfg_bus.we,
+                            i_cfg_wishbone_stb=cfg_bus.stb,
+                            i_cfg_wishbone_cyc=cfg_bus.cyc,
+                            o_cfg_wishbone_ack=cfg_bus.ack,
+                            #o_cfg_wishbone_err=cfg_bus.err,
 
                             # QSPI signals
                             o_spi_d_out=self.dq_out,
                             o_spi_d_direction=self.dq_direction,
                             i_spi_d_in=self.dq_in,
                             o_spi_ss_n=self.cs_n_out,
-                            o_spi_clock=self.spi_clk
+                            o_spi_clock=self.spi_clk,
+
+                            # debug port
+                            o_debug_port=self.dbg_port
                             );
 
         m.submodules['tercel_%d' % self.idx] = tercel
@@ -150,15 +168,14 @@ class Tercel(Elaboratable):
         if pins is not None:
             comb += pins.dq.o.eq(self.dq_out)
             comb += pins.dq.oe.eq(self.dq_direction)
-            comb += pins.dq.oe.eq(self.dq_direction)
             comb += pins.dq.o_clk.eq(ClockSignal())
             comb += self.dq_in.eq(pins.dq.i)
             comb += pins.dq.i_clk.eq(ClockSignal())
             # XXX invert handled by SPIFlashResource
-            comb += pins.cs.eq(~self.cs_n_out)
+            comb += pins.cs_n.eq(self.cs_n_out)
             # ECP5 needs special handling for the SPI clock, sigh.
             if self.lattice_ecp5_usrmclk:
-                self.specials += Instance("USRMCLK",
+                m.submodules += Instance("USRMCLK",
                     i_USRMCLKI  = self.spi_clk,
                     i_USRMCLKTS = 0
                 )
@@ -167,6 +184,19 @@ class Tercel(Elaboratable):
 
         return m
 
+    def ports(self):
+        return [self.bus.cyc, self.bus.stb, self.bus.ack,
+                        self.bus.dat_r, self.bus.dat_w, self.bus.adr,
+                        self.bus.we, self.bus.sel,
+                        self.cfg_bus.cyc, self.cfg_bus.stb,
+                        self.cfg_bus.ack,
+                        self.cfg_bus.dat_r, self.cfg_bus.dat_w,
+                        self.cfg_bus.adr,
+                        self.cfg_bus.we, self.cfg_bus.sel,
+                        self.dq_out, self.dq_direction, self.dq_in,
+                        self.cs_n_out, self.spi_clk
+                       ]
+
 
 def create_ilang(dut, ports, test_name):
     vl = rtlil.convert(dut, name=test_name, ports=ports)
@@ -181,15 +211,5 @@ def create_verilog(dut, ports, test_name):
 
 if __name__ == "__main__":
     tercel = Tercel(name="spi_0", data_width=32, clk_freq=100e6)
-    create_ilang(tercel, [tercel.bus.cyc, tercel.bus.stb, tercel.bus.ack,
-                        tercel.bus.dat_r, tercel.bus.dat_w, tercel.bus.adr,
-                        tercel.bus.we, tercel.bus.sel,
-                        tercel.cfg_bus.cyc, tercel.cfg_bus.stb,
-                        tercel.cfg_bus.ack,
-                        tercel.cfg_bus.dat_r, tercel.cfg_bus.dat_w,
-                        tercel.cfg_bus.adr,
-                        tercel.cfg_bus.we, tercel.cfg_bus.sel,
-                        tercel.dq_out, tercel.dq_direction, tercel.dq_in,
-                        tercel.cs_n_out, tercel.spi_clk
-                       ], "spi_0")
+    create_ilang(tercel, tercel.ports(), "spi_0")