[[Glasgow Notes]]
see [[glasgow Demultiplexer]]
## FIFO ports
Initialized with a variable "fifo"
### FIFOReadPort
Attributes:
```python
_ctrl_en : Signal
Control enable. Deasserting control enable prevents any reads from the FIFO from happening, but does not change the readable flag.
_data_en : Signal
Data enable. Deasserting data enable prevents any reads and also deasserts the readable flag.
```
### FIFOWritePort
Attributes:
```python
_ctrl_en : Signal
Control enable. Deasserting control enable prevents any writes to the FIFO from happening, but does not change the writable flag.
_data_en : Signal
Data enable. Deasserting data enable prevents any writes and also deasserts the writable flag.
```
## DirectMultiplexer
Superclass: AccessMultiplexer
Init arguments:
- Ports
- Pipes
- Registers
- FX2_crossbaar
Methods:
`set_analyzer` - takes `analyzer`, and sets `self._analyzer` to that if it's currently `None`
`pipe_count` - returns `self._claimed_pipes`
### claim_interface
Arguments:
- applet
- args (CLI arguments?)
- with_analyzer - default `True`
- throttle - default `fifo`
Sets `pipe_num` and increments `self._claimed_pipes`
If --PORT (`port_spec`) is in the arguments, then do some stuff..
- If any of the ports are already claimed, error
- If port does not exist, error
- If port is found in `self._ports`, then it's good to go
- Creates a list of pins, a pin for every bit in the specified `port_width`
Adds an analyzer if `with_analyzer` is True and an analyzer has been set
Logs either "claimed pipe X and port(s) X" or "claimed pipe X", depending on if ports were specified
==Creates `iface`== - initializes a `DirectMultiPlexerInterface` object
Adds `iface` to `self.submodules`
==Returns== `iface`
## DirectMultiplexerInterface
Init arguments
- applet
- analyzer
- registers
- fx2_crossbar
- pipe_num
- pins
- throttle
Methods:
`get_pin_name` - when given a `pin_num`, it gets info about that pin (`port` and `bit`) from `self._ports` and returns a string with that info
### build_pin_tristate
just putting the code in here bc it's the best explanation of itself at the moment
```python
port, bit, req = self._pins[pin_num]
pin_parts = req(bit)
self.comb += [
pin_parts.io.oe.eq(oe),
pin_parts.io.o.eq(o),
i.eq(pin_parts.io.i),
]
if hasattr(pin_parts, "oe"):
self.comb += pin_parts.oe.o.eq(oe)
```
`_throttle_fifo` - if `self._throttle` is "full", sets `_ctrl_en`, if it's "fifo", sets `_data_en`. Either way, sets a pin to be the opposite of `self.analyzer.throttle`
### `get_in_fifo`, `get_out_fifo`
gets fifo from `self._fx2_crossbar.get_out_fifo` / in_fifo
arguments passed: `self._pipe_num`, kwargs, reset
if an analyzer is present, then `self.analyzer.add_out_fifo_event` / in_fifo_event
- arguments passed: `self.applet`, fifo
### add_subtarget
```python
if self._throttle == "full":
# When in the "full" throttling mode, once the throttle signal is asserted while
# the applet asserts `r_en` or `w_en`, the applet will cause spurious reads or writes;
# this happens because the FIFO is not in the control enable domain of the applet.
#
# (This is deliberate; throttling often happens because the analyzer CY7C FIFO is
# full, but we might still be able to transfer data between the other FIFOs.)
#
# Thus, in `_throttle_fifo` above, we add the read (for OUT FIFOs) or write
# (for IN FIFOs) ports into the applet control enable domain.
subtarget = EnableInserter(~self.analyzer.throttle)(subtarget)
# Reset the subtarget simultaneously with the USB-side and FPGA-side FIFOs. This ensures
# that when the demultiplexer interface is reset, the gateware and the host software are
# synchronized with each other.
subtarget = ResetInserter(self.reset)(subtarget)
```
Adds subtarget to `self.submodules`
and returns subtarget