[[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