e8f96fc98bd50915489756f75bcdbe1873bf2a1c
[pinmux.git] / docs / AddingPeripherals.mdwn
1 # How to add a new peripheral
2
3 This document describes the process of adding a new peripheral to
4 the pinmux and auto-generator, through a worked example, adding
5 SDRAM.
6
7 # Creating the specifications
8
9 The tool is split into two halves that are separated by tab-separated
10 files. The first step is therefore to add a function that defines
11 the peripheral as a python function. That implies in turn that the
12 pinouts of the peripheral must be known. Looking at the BSV code
13 for the SDRAM peripheral, we find its interface is defined as follows:
14
15 interface Ifc_sdram_out;
16 (*always_enabled,always_ready*)
17 method Action ipad_sdr_din(Bit#(64) pad_sdr_din);
18 method Bit#(9) sdram_sdio_ctrl();
19 method Bit#(64) osdr_dout();
20 method Bit#(8) osdr_den_n();
21 method Bool osdr_cke();
22 method Bool osdr_cs_n();
23 method Bool osdr_ras_n ();
24 method Bool osdr_cas_n ();
25 method Bool osdr_we_n ();
26 method Bit#(8) osdr_dqm ();
27 method Bit#(2) osdr_ba ();
28 method Bit#(13) osdr_addr ();
29 interface Clock sdram_clk;
30 endinterface
31
32 So now we go to src/spec/pinfunctions.py and add a corresponding function
33 that returns a list of all of the required pin signals. However, we note
34 that it is a huge number of pins so a decision is made to split it into
35 groups: sdram1, sdram2 and sdram3. Firstly, sdram1, covering the base
36 functionality:
37
38 def sdram1(suffix, bank):
39 buspins = []
40 inout = []
41 for i in range(8):
42 pname = "SDRDQM%d*" % i
43 buspins.append(pname)
44 for i in range(8):
45 pname = "SDRD%d*" % i
46 buspins.append(pname)
47 inout.append(pname)
48 for i in range(12):
49 buspins.append("SDRAD%d+" % i)
50 for i in range(8):
51 buspins.append("SDRDEN%d+" % i)
52 for i in range(2):
53 buspins.append("SDRBA%d+" % i)
54 buspins += ['SDRCKE+', 'SDRRASn+', 'SDRCASn+', 'SDRWEn+',
55 'SDRCSn0++']
56 return (buspins, inout)
57
58 This function, if used on its own, would define an 8-bit SDRAM bus with
59 12-bit addressing. Checking off the names against the corresponding BSV
60 definition we find that most of them are straightforward. Outputs
61 must have a "+" after the name (in the python representation), inputs
62 must have a "-".
63
64 However we run smack into an interesting brick-wall with the in/out pins.
65 In/out pins which are routed through the same IO pad need a *triplet* of
66 signals: one input wire, one output wire and *one direction control wire*.
67 Here however we find that the SDRAM controller, which is a wrapper around
68 the opencores SDRAM controller, has a *banked* approach to direction-control
69 that will need to be dealt with, later.
70
71 The second function extends the 8-bit data bus to 64-bits, and extends
72 the address lines to 13-bit wide:
73
74 def sdram3(suffix, bank):
75 buspins = []
76 inout = []
77 for i in range(12, 13):
78 buspins.append("SDRAD%d+" % i)
79 for i in range(8, 64):
80 pname = "SDRD%d*" % i
81 buspins.append(pname)
82 inout.append(pname)
83 return (buspins, inout)
84
85 In this way, alternative SDRAM controller implementations can use sdram1
86 on its own; implementors may add "extenders" (named sdram2, sdram4) that
87 cover extra functionality, and, interestingly, in a pinbank scenario,
88 the number of pins on any given GPIO bank may be kept to a sane level.
89
90 The next phase is to add the (now supported) peripheral to the list
91 of pinspecs at the bottom of the file, so that it can actually be used:
92
93 pinspec = (('IIS', i2s),
94 ('MMC', emmc),
95 ('FB', flexbus1),
96 ('FB', flexbus2),
97 ('SDR', sdram1),
98 ('SDR', sdram2),
99 ('SDR', sdram3), <---
100 ('EINT', eint),
101 ('PWM', pwm),
102 ('GPIO', gpio),
103 )
104
105 This gives a declaration that any time the function(s) starting with
106 "sdram" are used to add pins to a pinmux, it will be part of the
107 "SDR" peripheral. Note that flexbus is similarly subdivided into
108 two groups.
109