def sdram3(suffix, bank):
buspins = []
- inout = []
+ inout = []
for i in range(12, 13):
buspins.append("SDRAD%d+" % i)
for i in range(8, 64):
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
fb0 <- mkAXI4_Slave_to_FlexBus_Master_Xactor;
Ifc_rgbttl_dummy lcd0 <- mkrgbttl_dummy();
+The next thing to do: searching for the string "sdram\_out" shows that the
+original hand-generated code contains (contained) a declaration of the
+SDRAM Interface, presumably to which, when compiling to run on an FPGA,
+the SDRAM interface would be connected at the top level. Through this
+interface, connections would be done *by hand* to the IO pads, whereas
+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*
+
+ def extfastifinstance(self, name, count):
+ return "// TODO" + self._extifinstance(name, count, "_out", "", True,
+ ".if_sdram_out")
+
+ def fastifdecl(self, name, count):
+ 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
+
+