"SDR" peripheral. Note that flexbus is similarly subdivided into
two groups.
+Note however that due to a naming convention issue, interfaces must
+be declared with names that are lexicographically unique even in
+subsets of their names. i.e two interfaces, one named "SD" which is
+shorthand for SDMMC and another named "SDRAM" may *not* be added:
+the first has to be the full "SDMMC" or renamed to "MMC".
+
# Adding the peripheral to a chip's pinmux specification
Next, we add the peripheral to an actual chip's specification. In this
corresponds to the functions in src/spec/pinfunctions.py which is
exactly what we want. It is however extremely important to verify.
+Lastly, the peripheral is a "fast" peripheral, i.e. it must not
+be added to the "slow" peripherals AXI4-Lite Bus, so must be added
+to the list of "fast" peripherals, here:
+
+ ps = PinSpec(pinbanks, fixedpins, function_names,
+ ['lcd', 'jtag', 'fb', 'sdr']) <--
+
+ # Bank A, 0-27
+ ps.gpio("", ('A', 0), 0, 0, 28)
+
This basically concludes the first stage of adding a peripheral to
the pinmux / autogenerator tool. It allows peripherals to be assessed
for viability prior to actually committing the engineering resources
to their deployment.
+
+# Adding the code auto-generators.
+
+With the specification now created and well-defined (and now including
+the SDRAM interface), the next completely separate phase is to auto-generate
+the code that will drop an SDRAM instance onto the fabric of the SoC.
+
+This particular peripheral is classified as a "Fast Bus" peripheral.
+"Slow" peripherals will need to be the specific topic of an alternative
+document, however the principles are the same.
+
+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
+
+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
+of the string "sdrd63". It can clearly be seen that an interface
+named "PeripheralSideSDR" has been auto-generated:
+
+ // interface declaration between SDR and pinmux
+ (*always_ready,always_enabled*)
+ interface PeripheralSideSDR;
+ interface Put#(Bit#(1)) sdrdqm0;
+ interface Put#(Bit#(1)) sdrdqm1;
+ interface Put#(Bit#(1)) sdrdqm2;
+ interface Put#(Bit#(1)) sdrdqm3;
+ interface Put#(Bit#(1)) sdrdqm4;
+ interface Put#(Bit#(1)) sdrdqm5;
+ interface Put#(Bit#(1)) sdrdqm6;
+ interface Put#(Bit#(1)) sdrdqm7;
+ interface Put#(Bit#(1)) sdrd0_out;
+ interface Put#(Bit#(1)) sdrd0_outen;
+ interface Get#(Bit#(1)) sdrd0_in;
+ ....
+ ....
+ endinterface
+
+Note that for the data lines, that where in the sdram1 specification function
+the signals were named "SDRDn+, out, out-enable *and* in interfaces/methods
+have been created, as these will be *directly* connected to the I/O pads.
+
+Further down the file we see the *actual* connection to the I/O pad (cell).
+An example:
+
+ // --------------------
+ // ----- cell 161 -----
+
+ // output muxer for cell idx 161
+ cell161_mux_out=
+ wrsdr_sdrd63_out;
+
+ // outen muxer for cell idx 161
+ cell161_mux_outen=
+ wrsdr_sdrd63_outen; // bi-directional
+
+ // priority-in-muxer for cell idx 161
+
+ rule assign_wrsdr_sdrd63_in_on_cell161;
+ wrsdr_sdrd63_in<=cell161_mux_in;
+ endrule
+
+Here, given that this is a "dedicated" cell (with no muxing), we have
+*direct* assignment of all three signals (in, out, outen). 2-way, 3-way
+and 4-way muxing creates the required priority-muxing for inputs and
+straight-muxing for outputs, however in this instance, a deliberate
+pragmatic decision is being taken not to put 92 pins of 133mhz+ signalling
+through muxing.
+
+In examining the slow\_peripherals.bsv file, there should at this stage
+be no sign of an SDRAM peripheral having been added, at all. This is
+because it is missing from the peripheral\_gen side of the tool.
+
+However, as the slow\_peripherals module takes care of the IO cells
+(because it contains a declared and configured instance of the pinmux
+package), signals from the pinmux PeripheralSideSDR instance need
+to be passed *through* the slow peripherals module as an external
+interface. This will happen automatically once a code-generator class
+is added.
+
+So first, we must identify the nearest similar class. FlexBus looks
+like a good candidate, so we take a copy of src/bsv/peripheral\_gen/flexbus.py
+called sdram.py. The simplest next step is to global/search/replace
+"flexbus" with "sdram", and for peripheral instance declaration replace
+"fb" with "sdr". At this phase, despite knowing that it will
+auto-generate the wrong code, we add it as a "supported" peripheral
+at the bottom of src/bsv/peripheral\_gen/base.py, in the "PFactory"
+(Peripheral Factory) class:
+
+ from gpio import gpio
+ from rgbttl import rgbttl
+ from flexbus import flexbus
+ from sdram import sdram <--
+
+ for k, v in {'uart': uart,
+ 'rs232': rs232,
+ 'sdr': sdram,
+ 'twi': twi,
+ 'quart': quart,
+
+Note that the name "SDR" matches with the prefix used in the pinspec
+declaration, back in src/spec/pinfunctions.py, except lower-cased. Once this
+is done, and the auto-generation tool re-run, examining the
+slow\_peripherals.bsv file again shows the following (correct) and only
+the following (correct) additions:
+
+ method Bit#(1) quart0_intr;
+ method Bit#(1) quart1_intr;
+ interface GPIO_config#(28) pad_configa;
+ interface PeripheralSideSDR sdr0; <--
+ interface PeripheralSideFB fb0;
+
+ ....
+ ....
+ interface iocell_side=pinmux.iocell_side;
+ interface sdr0 = pinmux.peripheral_side.sdr; <--
+ interface fb0 = pinmux.peripheral_side.fb;
+
+These automatically-generated declarations are sufficient to "pass through"
+the SDRAM "Peripheral Side", which as we know from examination of the code
+is directly connected to the relevant IO pad cells, so that the *actual*
+peripheral may be declared in the "fast" fabric and connected up to the
+relevant and required "fast" bus.
+
+Now we can begin the process of systematically inserting the correct
+"voodoo magic" incantations that, as far as this auto-generator tool is
+concerned, are just bits of ASCII text. In this particular instance, an
+SDRAM peripheral happened to already be *in* the SoC's BSV source code,
+such that the process of adding it to the tool is primarily one of
+*conversion*.
+
+**Please note that it is NOT recommended to do two tasks at once.
+It is strongly recommended to add any new peripheral to a pre-existing
+verified project, manually, by hand, and ONLY then to carry out a
+conversion process to have this tool understand how to auto-generate
+the fabric**
+
+So examining the i\_class socgen.bsv file, we also open up
+src/bsv/bsv\_lib/soc\_template.bsv in side-by-side windows of maximum
+80 characters in width each, and *respect the coding convention for
+this exact purpose*, can easily fit two such windows side-by-side
+*as well as* a third containing the source code files that turn that
+same template into its corresponding output.
+
+We can now begin by searching for strings "SDRAM" and "sdr" in both
+the template and the auto-generated socgen.bsv file. The first such
+encounter is the import, in the template:
+
+ `ifdef BOOTROM
+ import BootRom ::*;
+ `endif
+ `ifdef SDRAM <-- xxxx
+ import sdr_top :: *; <-- xxxx
+ `endif <-- xxxx
+ `ifdef BRAM
+
+This we can **remove**, and drop the corresponding code-fragment into
+the sdram slowimport function:
+
+ class sdram(PBase):
+
+ def slowimport(self):
+ return "import sdr_top::*;" <--
+
+ def num_axi_regs32(self):
+
+Now we re-run the auto-generator tool and confirm that, indeed, the
+ifdef'd code is gone and replaced with an unconditional import:
+
+ import mqspi :: *;
+ import sdr_top::*; <--
+ import Uart_bs :: *;
+ import RS232_modified::*;
+ import mspi :: *;
+
+Progress! Next, we examine the instance declaration clause. Remember
+that we cut/paste the flexbus class, so we are expecting to find code
+that declares the sdr0 instance as a FlexBus peripheral. We are
+also looking for the hand-created code that is to be *replaced*. Sure enough:
+
+ AXI4_Slave_to_FlexBus_Master_Xactor_IFC #(`PADDR, `DATA, `USERSPACE)
+ sdr0 <- mkAXI4_Slave_to_FlexBus_Master_Xactor; <--
+ AXI4_Slave_to_FlexBus_Master_Xactor_IFC #(`PADDR, `DATA, `USERSPACE)
+ fb0 <- mkAXI4_Slave_to_FlexBus_Master_Xactor;
+ ...
+ ...
+ `ifdef BOOTROM
+ BootRom_IFC bootrom <-mkBootRom;
+ `endif
+ `ifdef SDRAM <--
+ Ifc_sdr_slave sdram<- mksdr_axi4_slave(clk0); <--
+ `endif <--
+
+So, the mksdr\_axi4\_slave call we *remove* from the template and cut/paste
+it into the sdram class's mkfast_peripheral function, making sure to
+substitute the hard-coded instance name "sdram" with a python-formatted
+template that can insert numerical instance identifiers, should it ever
+be desired that there be more than one SDRAM peripheral put into a chip:
+
+class sdram(PBase):
+
+ ...
+ ...
+ def mkfast_peripheral(self):
+ return "Ifc_sdr_slave sdr{0} <- mksdr_axi4_slave(clk0);"
+
+Re-run the tool and check that the correct-looking code has been created:
+
+ Ifc_sdr_slave sdr0 <- mksdr_axi4_slave(clk0); <--
+ AXI4_Slave_to_FlexBus_Master_Xactor_IFC #(`PADDR, `DATA, `USERSPACE)
+ 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)
+
+