Bug 1244: changes to description pospopcount
[libreriscv.git] / docs / pinmux.mdwn
index 4a91b755493a1aca82de29c6e2b3afff9f40e679..40f4e9097795801901fde45b11d0a5a4218845cb 100644 (file)
@@ -6,8 +6,12 @@ Links:
 * <https://www10.edacafe.com/book/ASIC/CH02/CH02.7.php>
 * <https://ftp.libre-soc.org/Pin_Control_Subsystem_Overview.pdf>
 * <https://bugs.libre-soc.org/show_bug.cgi?id=50>
+* <https://bugs.libre-soc.org/show_bug.cgi?id=750>
+* <https://bugs.libre-soc.org/show_bug.cgi?id=762>
 * <https://git.libre-soc.org/?p=c4m-jtag.git;a=tree;hb=HEAD>
 * Extra info: [[/docs/pinmux/temp_pinmux_info]]
+* <https://git.libre-soc.org/?p=pinmux.git;a=blob;f=src/stage2.py> - Latest
+manual demo of pinmux generation
 
 Managing IO on an ASIC is nowhere near as simple as on an FPGA.
 An FPGA has built-in IO Pads, the wires terminate inside an
@@ -18,7 +22,12 @@ out-enable) to be routed right the way from the ASIC, all
 the way to the IO PAD, where only then does a wire bond connect
 it to a single external pin.
 
-[[!img CH02-44.gif]]
+Below, therefore is a (simplified) diagram of what is
+usually contained in an FPGA's bi-directional IO Pad,
+and consequently this is what you must also provide, and explicitly
+wire up in your ASIC's HDL.
+
+[[!img asic_iopad_gen.svg]]
 
 Designing an ASIC, there is no guarantee that the IO pad is
 working when manufactured. Worse, the peripheral could be
@@ -216,8 +225,7 @@ and triaging of faults.
   pad is working.  If the UART Rx peripheral was faulty
   this would not be possible.
 
-<img src="https://libre-soc.org/shakti/m_class/JTAG/jtag-block.jpg"
-  width=500 />
+[[!img jtag-block.svg ]]
 
 ## C4M JTAG TAP
 
@@ -261,9 +269,9 @@ It is then your responsibility to:
 * connect up each and every peripheral input and output
   to the right IO Core Record in your HDL
 * connect up each and every IO Pad input and output
-  to the right IO Pad in the Platform. **This
-  does not happen automatically and is not the
-  responsibility of the TAP Interface*
+  to the right IO Pad in the Platform.
+* **This does not happen automatically and is not the
+  responsibility of the TAP Interface, it is yours**
 
 The TAP interface connects the **other** side of the pads
 and cores Records: **to the Muxes**.  You **have** to
@@ -377,7 +385,7 @@ Signal, but the external peripheral (known as a PHY in Hardware terminology)
 
 Firstly: note that the Clock will, obviously, also need to be routed
 through JTAG Boundary Scan, because, after all, it is being received
-through just another ordinary IO Pad, after all.  Secondly: note thst
+through just another ordinary IO Pad, after all.  Secondly: note that
 if it didn't, then clock skew would occur for that peripheral because
 although the Data Wires went through JTAG Boundary Scan MUXes, the
 clock did not.  Clearly this would be a problem.
@@ -409,15 +417,269 @@ but to that clock *after going through H Tree Buffers*.  Therefore,
 there will be a lag on the output data compared to the incoming
 (external) clock
 
-# GPIO Muxing
+# Pinmux GPIO Block
+
+The following diagram is an example of a mux'd GPIO block that comes from the
+Ericson presentation on a GPIO architecture.
+
+[[!img gpio-block.svg size="800x"]]
+
+## Our Pinmux Block
+
+The block we are developing is very similar, but is lacking some of
+configuration of the former (due to complexity and time constraints).
+
+The implemented pinmux uses two sub-blocks:
+
+1. A Wishbone controlled N-GPIO block.
+
+1. N-port I/O multiplexer (for current usecase set to 4
+ports).
+
+### Terminology
+
+For clearer explanation, the following definitions will be used in the text.
+As the documentation is actively being written, the experimental code may not
+adhere to these all the time.
+
+* Bank - A group of contiguous pins under a common name.
+* Pin - Bi-directional wire connecting to the chip's pads.
+* Function (pin) - A signal used by the peripheral.
+* Port - Bi-directional signal on the peripheral and pad sides of the
+multiplexer.
+* Muxwidth - Number of input ports to the multiplexers
+* PinMux - Multiplexer for connecting multiple peripheral functions to one IO
+pad.
+
+For example:
+
+A 128-pin chip has 4 banks N/S/E/W corresponding to the 4 sides of the chip.
+Each bank has 32 pins. Each pin can have up to 4 multiplexed functions, thus
+the multiplexer width for each pin is 4.
+
+### PinSpec Class
+
+* <https://git.libre-soc.org/?p=pinmux.git;a=blob;f=src/spec/base.py;h=c8fa2b09d650b1b7cfdb499bfe711a3ebaf5848b;hb=HEAD> PinSpec class
+defined here.
+
+PinSpec is a powerful construct designed to hold all the necessary information
+about the chip's banks. This includes:
+
+1. Number of banks
+1. Number of pins per each bank
+1. Peripherals present (UART, GPIO, I2C, etc.)
+1. Mux configuration for every pin (mux0: gpio, mux1: uart tx, etc.)
+1. Peripheral function signal type (out/in/bi)
+
+### Pinouts
+
+* <https://git.libre-soc.org/?p=pinmux.git;a=blob;f=src/spec/interfaces.py;h=f5ecf4817ba439b607a1909a4fcb6aa2589e2afd;hb=HEAD> Pinouts class
+defined here.
+
+The Pinspec class inherits from the Pinouts class, which allows to view the
+dictionaries containing bank names and pin information.
+
+* keys() - returns dict_key object of all the pins (summing all the banks) which
+is iterable
+* items() - a dict_key of pins, with each pin's mux information
+
+For example, PinSpec object 'ps' has one bank 'A' with 4 pins
+ps.keys() returns dict_keys([0, 1, 2, 3])
+ps.items() returns
+dict_items([(0, {0: ('GPIOA_A0', 'A'), 1: ('UART0_TX', 'A'),
+                                2: ('TWI0_SDA', 'A')}),
+                   (1, {0: ('GPIOA_A1', 'A'), 1: ('UART0_RX', 'A'),
+                                2: ('TWI0_SCL', 'A')}),
+                       (2, {0: ('GPIOA_A2', 'A')}), (3, {0: ('GPIOA_A3', 'A')})])
+
+### PinGen
+
+pinfunctions.py contains the "pinspec" list containing the Python functions
+which generate the necessary signals for gpio, uart, i2c, etc. (with IOType
+information). PinGen class uses "__call__" and "pinspec" to effectively create a
+Lambda function for generating specified peripheral signals.
+
+## The GPIO block 
+
+*NOTE !* - Need to change 'bank' terminology for the GPIO block in doc and code!
+
+[[!img n-gpio.svg size="600x"]]
+
+The GPIO module is multi-GPIO block integral to the pinmux system.
+To make the block flexible, it has a variable number of of I/Os based on an
+input parameter.
+
+### Configuration Word
+
+After a discussion with Luke on IRC (14th January 2022), new layout of the
+8-bit data word for configuring the GPIO (through WB):
+
+* oe - Output Enable (see the Ericson presentation for the GPIO diagram)
+* ie - Input Enable *(Not used, as IOPad only supports i/o/oe)*
+* puen - Pull-Up resistor enable
+* pden - Pull-Down resistor enable
+* i/o - When configured as output (oe set), this bit sets/clears output. When
+configured as input, shows the current state of input (read-only)
+* bank[2:0] - Bank Select *(only 4 banks used, bank[2] used for JTAG chain)*
+
+### Simultaneous/Packed Configuration
+
+To make the configuration more efficient, multiple GPIOs can be configured with
+one data word. The number of GPIOs in one "row" is dependent on the WB data bus
+*width* and *granuality* (see Wishbone B4 spec, section 3.5 Data Organization
+for more details).
+
+If for example, the data bus is 64-bits wide and granuality is 8, eight GPIO
+configuration bytes - and thus eight GPIOs - can be configured in one go.
+To configure only certain GPIOs, the WB sel signal can be used (see next
+section).
+
+*(NOTE: Currently the code doesn't support granuality higher than 8)*
+
+The diagram below shows the layout of the configuration byte.
+
+[[!img gpio-config-word.jpg size="600x"]]
+
+If the block is created with more GPIOs than can fit in a single data word,
+the next set of GPIOs can be accessed by incrementing the address.
+For example, if 16 GPIOs are instantiated and 64-bit data bus is used, GPIOs
+0-7 are accessed via address 0, whereas GPIOs 8-15 are accessed by address 1.
+
+### Example Memory Map
+
+[[!img gpio-mem-layout.jpg size="600x"]]
+
+The diagrams above show the difference in memory layout between 16-GPIO block
+implemented with 64-bit and 32-bit WB data buses.
+The 64-bit case shows there are two rows with eight GPIOs in each, and it will
+take two writes (assuming simple WB write) to completely configure all 16 GPIOs.
+The 32-bit on the other hand has four address rows, and so will take four write transactions.
+
+64-bit:
+
+* 0x00 - Configure GPIOs  0-7  - requires 8-bit `sel` one bit per GPIO
+* 0x01 - Configure GPIOs  8-15 - requires 8-bit `sel` one bit per GPIO
+
+32-bit:
+
+* 0x00 - Configure GPIOs  0-3 - requires 4-bit `sel` one bit per GPIO
+* 0x01 - Configure GPIOs  4-7 - requires 4-bit `sel` one bit per GPIO
+* 0x02 - Configure GPIOs  8-11 - requires 4-bit `sel` one bit per GPIO
+* 0x03 - Configure GPIOs 12-15 - requires 4-bit `sel` one bit per GPIO
+
+Here is the pseudocode for reading the GPIO
+data structs:
+
+    read_bytes = []
+    for i in range(len(sel)):
+        GPIO_num = adr*len(sel)+i
+        if sel[i]:
+            read_bytes.append(GPIO[GPIO_num])
+        else:
+            read_bytes.append(Const(0, 8))
+    if not wen:
+        dat_r.eq(Cat(read_bytes))
+
+and for writing, slightly different style:
+
+    if wen:
+        write_bytes = []
+        for i in range(len(sel)):
+            GPIO_num = adr*len(sel)+i
+            write_byte = dat_w.bit_select(i*8, 8)
+            if sel[i]:
+                GPIO[GPIO_num].eq(write_byte)
+
+As explained in this video <https://m.youtube.com/watch?v=Pf6gmDQnw_4>
+if each GPIO is mapped to one single byte, and it is assumed that
+the `sel` lines are enough to **always** give byte-level read/write
+then the GPIO number *becomes* the Memory-mapped byte number, hence
+the use of `len(sel)` above.  `len(dat_r)//8` would do as well
+because these should be equal.
+
+
+## The IO Mux block
+
+[[!img iomux-4bank.svg size="600x"]]
+
+This block is an N-to-1 (4-port shown above) mux and it simultaneously connects:
+
+* o/oe signals from one of N peripheral ports, to the pad output port
+
+* i pad port signal to one of N peripheral ports (the rest being set to 0).
+
+The block is then used in a higher-level pinmux block, and instantiated for each
+pin.
+
+## Combined Block
+
+*NOTE !* - Need to change 'bank' terminology for the GPIO block in doc and code!
+
+[[!img pinmux-1pin.svg size="600x"]]
+
+The GPIO and IOMux blocks are combined in a single block called the
+Pinmux block.
+
+By default, bank 0 is hard-wired to the memory-mapped WB bus GPIO. The CPU
+core can just write the configuration word to the GPIO row address. From this
+perspective, it is no different to a conventional GPIO block.
+
+Bank select, allows to switch over the control of the IO pad to
+another peripheral. The peripheral will be given sole connectivity to the
+o/oe/i signals, while additional parameters such as pull up/down will either
+be automatically configured (as the case for I2C), or will be configurable
+via the WB bus. *(This has not been implemented yet, so open to discussion)*
+
+### Bank Select Options
+
+* bank 0 - WB bus has full control (GPIO peripheral)
+* bank 1,2,3 - WB bus only controls puen/pden, periphal gets o/oe/i
+(whether ie should be routed out is not finalised yet)
+
+
+### Adding JTAG BS Chain to the Pinmux block (In Progress)
+
+The JTAG BS chain need to have access to the bank select bits, to allow
+selecting different peripherals during testing. At the same time, JTAG may
+also require access to the WB bus to access GPIO configuration options
+not available to bank 1/2/3 peripherals.
+
+The proposed JTAG BS chain is as follows:
+
+* Connect puen/pden/bank from GPIO block to the IOMux through JTAG BS chain.
+* Connect the i/o/oe pad port from IOMux via JTAG BS chain.
+* (?) Test port for configuring GPIO without WB? - utilising bank bit 2?
+* (?) Way to drive WB via JTAG?
+
+Such a setup would allow the JTAG chain to control the bank select when testing
+connectivity of the peripherals, as well as give full control to the GPIO
+configuration when bank select bit 2 is set.
+
+For the purposes of muxing peripherals, bank select bit 2 is ignored. This
+means that even if JTAG is handed over full control, the peripheral is
+still connected to the GPIO block (via the BS chain).
+
+Signals for various ports:
+
+* WB bus or Periph0: WB data read, data write, address, sel, cyc, stb, ack
+* Periph1/2/3: o,oe,i (puen/pden are only controlled by WB, test port, or
+fixed by functionality; ie not used yet)
+* (?) Test port: bank[2:0], o,oe,i,ie,puen,pden. In addition, internal
+address to access individual GPIOs will be available (this will consist of a
+few bits, as more than 16 GPIOs per block is likely to be to big).
+
+As you can see by the above list, the pinmux block is becoming quite a complex
+beast. If there are suggestions to simplify or reduce some of the signals,
+that will be helpful.
 
-[[!img gpio_block.png]]
+The diagrams above showed 1-bit GPIO connectivity. Below you'll find the
+4-bit case *(NOT IMPLEMENTED YET)*.
 
-[[!img io_mux_bank_planning.JPG size="600px"]]
+[[!img gpio_jtag_4bit.jpg size="600x"]]
 
 # Core/Pad Connection + JTAG Mux
 
 Diagram constructed from the nmigen plat.py file.
 
-[[!img i_o_io_tristate_jtag.JPG size="600x"]]
+[[!img i_o_io_tristate_jtag.svg ]]