add sdram dual axi4 configs
[pinmux.git] / docs / AddingPeripherals.mdwn
index ae00d559de5a18ac45e1eab3530ea933f081f22b..e1b470d2fef99d9d9778a51e16aef3402365935b 100644 (file)
@@ -75,7 +75,7 @@ the address lines to 13-bit wide:
 
     def sdram3(suffix, bank):
         buspins = []
-        inout = [] 
+        inout = []
         for i in range(12, 13):
             buspins.append("SDRAD%d+" % i)
         for i in range(8, 64):
@@ -215,7 +215,7 @@ The first requirement is that the pins from the peripheral side be connected
 through to IO cells.  This can be verified by running the pinmux code
 generator (to activate "default" behaviour), just to see what happens:
 
-    $ python src/pinmux_generator.py -o i_class 
+    $ python src/pinmux_generator.py -o i_class
 
 Files are auto-generated in ./i\_class/bsv\_src and it is recommended
 to examine the pinmux.bsv file in an editor, and search for occurrences
@@ -424,7 +424,7 @@ now they are to be connected *automatically* (on the peripheral side)
 to the IO pads in the pinmux.  However, at the time of writing this is
 not fully understood by the author, so the fastifdecl and extfastifinstance
 functions are modified to generate the correct output but the code is
-*commented out*:
+*commented out*
 
     def extfastifinstance(self, name, count):
         return "// TODO" + self._extifinstance(name, count, "_out", "", True,
@@ -434,4 +434,79 @@ functions are modified to generate the correct output but the code is
         return "// (*always_ready*) interface " + \
                 "Ifc_sdram_out sdr{0}_out;".format(count)
 
+Also the corresponding (old) manual declarations of sdram\_out
+removed from the template:
+
+    `ifdef SDRAM                                            <-- xxxx
+        (*always_ready*) interface Ifc_sdram_out sdram_out; <-- xxxx
+    `endif                                                  <-- xxxx
+    ...
+    ...
+    `ifdef SDRAM                                  <--- xxxx
+        interface sdram_out=sdram.ifc_sdram_out;  <--- xxxx
+    `endif                                        <--- xxxx
+
+Next, again searching for signs of the "hand-written" code, we encounter
+the fabric connectivity, which wires the SDRAM to the AXI4.  We note however
+that there is not just one AXI slave device but *two*: one for the SDRAM
+itself and one for *configuring* the SDRAM.  We therefore need to be
+quite careful about assigning these, as will be subsequently explained.
+First however, the two AXI4 slave interfaces of this peripheral are
+declared:
+
+    class sdram(PBase):
+
+        ...
+        ...
+        def _mk_connection(self, name=None, count=0):
+            return ["sdr{0}.axi4_slave_sdram",
+                    "sdr{0}.axi4_slave_cntrl_reg"]
+
+Note that, again, in case multiple instances are ever to be added, the
+python "format" string "{0}" is inserted so that it can be substituted
+with the numerical identifier suffix.  Also note that the order
+of declaration of these two AXI4 slave is **important**.
+
+Re-running the auto-generator tool, we note the following output has
+been created, and match it against the corresponding hand-generated (old)
+code:
+
+    `ifdef SDRAM
+            mkConnection (fabric.v_to_slaves
+                              [fromInteger(valueOf(Sdram_slave_num))],
+                              sdram.axi4_slave_sdram); // 
+            mkConnection (fabric.v_to_slaves
+                              [fromInteger(valueOf(Sdram_cfg_slave_num))],
+                              sdram.axi4_slave_cntrl_reg); // 
+    `endif
+
+    // fabric connections
+    mkConnection (fabric.v_to_slaves
+                [fromInteger(valueOf(SDR0_fastslave_num))],
+                sdr0.axi4_slave_sdram);
+    mkConnection (fabric.v_to_slaves
+                [fromInteger(valueOf(SDR0_fastslave_num))],
+                sdr0.axi4_slave_cntrl_reg);
+
+Immediately we can spot an issue: whilst the correctly-named slave(s) have
+been added, they have been added with the *same* fabric slave index.  This
+is unsatisfactory and needs resolving.
+
+Here we need to explain a bit more about what is going on.  The fabric
+on an AXI4 Bus is allocated numerical slave numbers, and each slave is
+also allocated a memory-mapped region that must be resolved in a bi-directional
+fashion.  i.e whenever a particular memory region is accessed, the AXI
+slave peripheral responsible for dealing with it **must** be correctly
+identified.  So this requires some further crucial information, which is
+the size of the region that is to be allocated to each slave device.  Later
+this will be extended to being part of the specification, but for now
+it is auto-allocated based on the size.  As a huge hack, it is allocated
+in 32-bit chunks, as follows:
+
+class sdram(PBase):
+
+    def num_axi_regs32(self):
+        return [0x400000,  # defines an entire memory range (hack...)
+                12]        # defines the number of configuration regs
+