.. _module_common: Module common ============= This document contains technical documentation for the ``common`` module. To browse the source code, please visit the `repository on GitHub `__. This module contains a large collection of VHDL entities and packages that are useful in everyday FPGA design. .. _common.addr_pkg: addr_pkg.vhd ------------ `View source code on GitHub `__. Collection of types/functions for working with address decode/matching. .. _common.attribute_pkg: attribute_pkg.vhd ----------------- `View source code on GitHub `__. Commonly used attributes for Xilinx Vivado, with description and their valid values. Information gathered from documents UG901 and UG912. .. _common.axi_stream_protocol_checker: axi_stream_protocol_checker.vhd ------------------------------- `View source code on GitHub `__. .. symbolator:: component axi_stream_protocol_checker is generic ( data_width : natural; id_width : natural; user_width : natural; logger_name_suffix : string ); port ( clk : in std_ulogic; --# {{}} ready : in std_ulogic; valid : in std_ulogic; last : in std_ulogic; data : in std_ulogic_vector; strobe : in std_ulogic_vector; id : in u_unsigned; user : in std_ulogic_vector ); end component; Check that an AXI-Stream-like handshaking bus is compliant with the AXI-Stream standard. Will perform the following checks at each rising clock edge: 1. The handshake signals ``ready`` and ``valid`` must be well-defined (not ``'X'``, ``'-'``, etc). 2. ``valid`` must not fall without a transaction (``ready and valid``). 3. No payload on the bus may change while ``valid`` is asserted, unless there is a transaction. 4. ``strobe`` must be well-defined when ``valid`` is asserted. If any rule violation is detected, an assertion will be triggered. Use the ``logger_name_suffix`` generic to customize the error message. .. note:: This entity can be instantiated in simulation code as well as in synthesis code. The code is simple and will be stripped by synthesis. Can be useful to check the behavior of a stream that is deep in a hierarchy. Comparison to VUnit checker ___________________________ This entity was created as a lightweight and synthesizable alternative to the VUnit AXI-Stream protocol checker (``axi_stream_protocol_checker.vhd``). The VUnit checker is clearly more powerful and has more features, but it also consumes a lot more CPU cycles when simulating. One testbench in this project that uses five protocol checkers decreased its execution time by 45% when switching to this protocol checker instead. Compared to the VUnit checker, this entity is missing these features: 1. Reset support. 2. Checking for undefined bits in payload fields. 3. Checking that all started packets finish with a proper ``last``. 4. Performance checking that ``ready`` is asserted within a certain number of cycles. 5. Logger support. Meaning, it is not possible to mock or disable the checks in this entity. .. _common.clean_packet_dropper: clean_packet_dropper.vhd ------------------------ `View source code on GitHub `__. .. symbolator:: component clean_packet_dropper is generic ( data_width : positive; fifo_depth : positive ); port ( clk : in std_ulogic; --# {{}} drop : in std_ulogic; --# {{}} input_ready : out std_ulogic; input_valid : in std_ulogic; input_last : in std_ulogic; input_data : in std_ulogic_vector; input_strobe : in std_ulogic_vector; --# {{}} result_ready : in std_ulogic; result_valid : out std_ulogic; result_last : out std_ulogic; result_data : out std_ulogic_vector; result_strobe : out std_ulogic_vector ); end component; An incoming packet will be dropped cleanly if ``drop`` is asserted for at least one clock cycle during the active packet. Once ``drop`` has been asserted during an active packet, this entity will 1. Not pass anything of the current ``input`` packet on to the ``result`` side, including anything that was consumed before ``drop`` was asserted. This means that only whole, non-corrupted, packets will be available on the ``result`` side. 2. Keep ``input_ready`` high until the whole packet has been consumed, so the upstream on the ``input`` side is not stalled. .. note:: The :ref:`fifo.fifo` instance in this module is in packet mode, meaning that a whole packet has to be written to FIFO before any data is passed on to ``result`` side. Hence the ``fifo_depth`` generic has to be chosen so that it can hold the maximum possible packet length from the ``input`` side. .. _common.clock_counter: clock_counter.vhd ----------------- `View source code on GitHub `__. .. symbolator:: component clock_counter is generic ( resolution_bits : positive; max_relation_bits : positive; shift_register_length : positive ); port ( target_clock : in std_ulogic; --# {{}} reference_clock : in std_ulogic; target_tick_count : out u_unsigned ); end component; Measure the switching rate of an unknown clock by using a free-running reference clock of known frequency. .. note:: This entity instantiates a :ref:`resync.resync_counter` block. See documentation of that entity for constraining details. The frequency of target_clock is given by target_tick_count * reference_clock_frequency / 2 ** resolution_bits The ``target_tick_count`` value is updated every ``2 ** resolution_bits`` cycles. It is invalid for ``2 * 2 ** resolution_bits`` cycles in the beginning as ``reference_clock`` starts switching, but after that it is always valid. For the calculation to work, ``target_clock`` must be no more than ``2 ** (max_relation_bits - 1)`` times faster than reference_clock. .. _common.clock_counter.resource_utilization: Resource utilization ____________________ This entity has `netlist builds `__ set up with `automatic size checkers `__ in `module_common.py `__. The following table lists the resource utilization for the entity, depending on generic configuration. .. list-table:: Resource utilization for **clock_counter** netlist builds. :header-rows: 1 * - Generics - Total LUTs - SRLs - FFs * - resolution_bits = 24 max_relation_bits = 6 - 84 - 5 - 185 * - resolution_bits = 10 max_relation_bits = 4 - 38 - 2 - 86 .. _common.common_context: common_context.vhd ------------------ `View source code on GitHub `__. A VHDL context for including the packages in this library. .. _common.common_pkg: common_pkg.vhd -------------- `View source code on GitHub `__. Package with common features that do not fit in anywhere else, and are not significant enough to warrant their own package. .. _common.debounce: debounce.vhd ------------ `View source code on GitHub `__. .. symbolator:: component debounce is generic ( stable_count : positive; default_value : std_ulogic ); port ( noisy_input : in std_ulogic; --# {{}} clk : in std_ulogic; stable_result : out std_ulogic; stable_rising_edge : out std_ulogic; stable_falling_edge : out std_ulogic ); end component; Simple debounce mechanism to be used with e.g. the signal from a button or dip switch. It eliminates noise and metastability by requiring the input to have a stable value for a specified number of clock cycles before propagating the value. .. note:: This entity instantiates a :ref:`resync.resync_level` block (``async_reg`` chain) to make sure the input is not metastable. The :ref:`resync.resync_level` has a scoped constraint file that must be used. .. _common.handshake_merger: handshake_merger.vhd -------------------- `View source code on GitHub `__. .. symbolator:: component handshake_merger is generic ( num_interfaces : positive; assert_false_on_last_mismatch : boolean ); port ( clk : in std_ulogic; --# {{}} input_ready : out std_ulogic_vector; input_valid : in std_ulogic_vector; input_last : in std_ulogic_vector; --# {{}} result_ready : in std_ulogic; result_valid : out std_ulogic; result_last : out std_ulogic ); end component; Combinatorially merge multiple AXI-Stream-like handshake interfaces into one. The handling of data and other auxiliary signals must be performed outside of this entity. This entity guarantees that when ``result_valid`` is asserted, the data associated with all inputs is valid and can be used combinatorially on the result side. If no interface is stalling, then full throughput is sustained through this entity. .. _common.handshake_mux: handshake_mux.vhd ----------------- `View source code on GitHub `__. .. symbolator:: component handshake_mux is generic ( num_inputs : positive; data_width : positive ); port ( clk : in std_ulogic; --# {{}} input_ready : out std_ulogic_vector; input_valid : in std_ulogic_vector; input_last : in std_ulogic_vector; input_data : in slv_vec_t; input_strobe : in slv_vec_t; --# {{}} result_ready : in std_ulogic; result_valid : out std_ulogic; result_last : out std_ulogic; result_data : out std_ulogic_vector; result_strobe : out std_ulogic_vector; result_id : out natural range 0 to num_inputs - 1 ); end component; Multiplex between many AXI-Stream-like inputs towards one output bus. Will lock onto one ``input`` and let its data through until a packet has passed, as indicated by the ``last`` signal. The implementation is simple, which comes with a few limitations: .. warning:: If there are holes in an ``input`` packet stream after ``valid`` has been asserted, this multiplexer will be unnecessarily stalled even if another ``input`` has data available. It is up to the user to make sure that this does not occur, using e.g. a :ref:`fifo.fifo` in packet mode, or calculate that the system throughput is still sufficient. The arbitration is done in the most resource-efficient round-robin manner possible, which means that one ``input`` can starve out the others if it continuously sends data. .. _common.handshake_pipeline: handshake_pipeline.vhd ---------------------- `View source code on GitHub `__. .. symbolator:: component handshake_pipeline is generic ( data_width : natural; full_throughput : boolean; pipeline_control_signals : boolean; pipeline_data_signals : boolean; strobe_unit_width : positive ); port ( clk : in std_ulogic; --# {{}} input_ready : out std_ulogic; input_valid : in std_ulogic; input_last : in std_ulogic; input_data : in std_ulogic_vector; input_strobe : in std_ulogic_vector; --# {{}} output_ready : in std_ulogic; output_valid : out std_ulogic; output_last : out std_ulogic; output_data : out std_ulogic_vector; output_strobe : out std_ulogic_vector ); end component; Handshake pipeline. Is used to ease the timing of a streaming data interface by inserting register stages on the data and/or control signals. There are many modes available, with different characteristics, that are enabled with different combinations of ``full_throughput``, ``pipeline_control_signals`` and ``pipeline_data_signals``. See the descriptions within the code for more details about throughput and fanout. .. _common.handshake_pipeline.resource_utilization: Resource utilization ____________________ This entity has `netlist builds `__ set up with `automatic size checkers `__ in `module_common.py `__. The following table lists the resource utilization for the entity, depending on generic configuration. .. list-table:: Resource utilization for **handshake_pipeline** netlist builds. :header-rows: 1 * - Generics - Total LUTs - FFs - Maximum logic level * - data_width = 32 full_throughput = True pipeline_control_signals = True pipeline_data_signals = True - 41 - 78 - 2 * - data_width = 32 full_throughput = True pipeline_control_signals = False pipeline_data_signals = True - 1 - 38 - 2 * - data_width = 32 full_throughput = True pipeline_control_signals = False pipeline_data_signals = False - 0 - 0 - 0 * - data_width = 32 full_throughput = False pipeline_control_signals = True pipeline_data_signals = True - 1 - 39 - 2 * - data_width = 32 full_throughput = False pipeline_control_signals = True pipeline_data_signals = False - 2 - 3 - 2 * - data_width = 32 full_throughput = False pipeline_control_signals = False pipeline_data_signals = True - 2 - 38 - 2 * - data_width = 32 full_throughput = False pipeline_control_signals = False pipeline_data_signals = False - 0 - 0 - 0 .. _common.handshake_splitter: handshake_splitter.vhd ---------------------- `View source code on GitHub `__. .. symbolator:: component handshake_splitter is generic ( num_interfaces : positive ); port ( clk : in std_ulogic; --# {{}} input_ready : out std_ulogic; input_valid : in std_ulogic; --# {{}} output_ready : in std_ulogic_vector; output_valid : out std_ulogic_vector ); end component; Combinatorially split an AXI-Stream-like handshaking interface, for cases where many slaves are to receive the data. Maintains full throughput and is AXI-stream compliant in its handling of the handshake signals (``valid`` does not wait for ``ready``, ``valid`` does not fall unless a transaction has occurred). This entity has no pipelining of the handshake signals, but instead connects them combinatorially. This increases the logic depth for handshake signals where this entity is used. If timing issues occur (on the ``input`` or one of the ``output`` s) a :ref:`common.handshake_pipeline` instance can be used. .. _common.handshake_splitter.resource_utilization: Resource utilization ____________________ This entity has `netlist builds `__ set up with `automatic size checkers `__ in `module_common.py `__. The following table lists the resource utilization for the entity, depending on generic configuration. .. list-table:: Resource utilization for **handshake_splitter** netlist builds. :header-rows: 1 * - Generics - Total LUTs - FFs * - num_interfaces = 2 - 4 - 2 * - num_interfaces = 4 - 9 - 4 .. _common.keep_remover: keep_remover.vhd ---------------- `View source code on GitHub `__. .. symbolator:: component keep_remover is generic ( data_width : positive; strobe_unit_width : positive ); port ( clk : in std_ulogic; --# {{}} input_ready : out std_ulogic; input_valid : in std_ulogic; input_last : in std_ulogic; input_data : in std_ulogic_vector; input_keep : in std_ulogic_vector; --# {{}} output_ready : in std_ulogic; output_valid : out std_ulogic; output_last : out std_ulogic; output_data : out std_ulogic_vector; output_strobe : out std_ulogic_vector ); end component; This entity removes strobe'd out lanes from the input, resulting in an output stream where all lanes are always strobed (except for the last beat, potentially). The strobe on input can be considered as the TKEEP signal in AXI-Stream terminology, and the output strobe would be TKEEP/TSTRB. The entity works by continuously filling up a data buffer with data from the input. Only the lanes that are strobed will be saved to the buffer. Note that input words may have all their lanes strobed out (except for the last beat, see below). When enough lanes are saved to fill a whole word, data is passed to the output by asserting ``output_valid``. When ``input_last`` is asserted for an input word, an output word will be sent out, with ``output_last`` asserted, even if a whole strobed word is not currently filled in the buffer. The strobe unit data width is configurable via a generic. Most of the time it would be eight, i.e. a byte strobe. But in some cases the strobe represents a wider quanta, in which case the generic can be increased. Increasing the generic will drastically decrease the resource utilization, since that is the "atom" of data that is handled internally. The handling of ``input_last`` presents a corner case. Lets assume that ``data_width`` is 16 and ``strobe_unit_width`` is 8. Furthermore, there is one atom of data available in the buffer, and input stream has both lanes strobed. In this case, one input word shall result in two output words. The first output word comes from a whole word being filled in the buffer. The second word comes from a half filled word in the buffer, but input_last being asserted. This is solved by having a small state machine that pads input data with an extra word when this corner case arises. The padding stage makes it possible to have a very simple data buffer stage, with low resource utilization. Throughput __________ The entity achieves full throughput, except for the corner case mentioned above, where it might stall one cycle on the input. Limitations ___________ * ``input_last`` may not be asserted on an input word that has all lanes strobed out. * There may never be a '1' above a '0' in the input strobe. E.g. "0111" is allowed, but "1100" is not. .. _common.keep_remover.resource_utilization: Resource utilization ____________________ This entity has `netlist builds `__ set up with `automatic size checkers `__ in `module_common.py `__. The following table lists the resource utilization for the entity, depending on generic configuration. .. list-table:: Resource utilization for **keep_remover** netlist builds. :header-rows: 1 * - Generics - Total LUTs - FFs - Maximum logic level - DSP Blocks * - data_width = 32 strobe_unit_width = 16 - 88 - 79 - 3 - 0 * - data_width = 64 strobe_unit_width = 8 - 410 - 175 - 6 - 0 * - data_width = 128 strobe_unit_width = 32 - 414 - 282 - 5 - 0 .. _common.periodic_pulser: periodic_pulser.vhd ------------------- `View source code on GitHub `__. .. symbolator:: component periodic_pulser is generic ( period : positive range 2 to integer'high; shift_register_length : positive ); port ( clk : in std_ulogic; --# {{}} count_enable : in std_ulogic; pulse : out std_ulogic ); end component; Outputs a one cycle ``pulse`` after a generic number of assertions of ``count_enable``. Shift registers are used as far as possible to create the pulse. This makes the implementation resource efficient on devices with cheap shift registers (such as SRLs in Xilinx devices). In the worst case a single counter is created. The ``period`` is broken down into factors that are represented using shift registers, with the shift register length being the factor value. By rotating the shift register on each ``count_enable``, a fixed period is created. When possible, multiple shift registers are AND-gated to create a longer period. For example a period of 30 can be achieved by gating two registers of length 10 and 3. This method only works if the lengths are mutual primes (i.e. the greatest common divisor is 1). If the remaining factor is not 1 after the shift registers have been added, a new instance of this module is added through recursion. If ``period`` cannot be factorized into one or more shift registers, recursion ends with either a simple counter or a longer shift register (depending on the size of the factor). Example _______ Let's say that the maximum shift register length is 16. A period of 510 = 10 * 3 * 17 can then be achieved using two shift registers of length 10 and 3, and then instantiating a new :ref:`common.periodic_pulser` .. code-block:: none [0][0][0][0][0][0][0][0][0][1] \ [AND] -> pulse -> [periodic_pulser with period 17] / [0][0][1] The next stage will create a counter, because 17 is a prime larger than the maximum shift register length. .. _common.periodic_pulser.resource_utilization: Resource utilization ____________________ This entity has `netlist builds `__ set up with `automatic size checkers `__ in `module_common.py `__. The following table lists the resource utilization for the entity, depending on generic configuration. .. list-table:: Resource utilization for **periodic_pulser** netlist builds. :header-rows: 1 * - Generics - Total LUTs - SRLs - FFs * - period = 33 shift_register_length = 33 - 2 - 1 - 1 * - period = 33 shift_register_length = 1 - 6 - 0 - 6 * - period = 37 shift_register_length = 33 - 3 - 2 - 1 * - period = 37 shift_register_length = 1 - 6 - 0 - 6 * - period = 100 shift_register_length = 33 - 3 - 2 - 2 * - period = 100 shift_register_length = 1 - 8 - 0 - 7 * - period = 125 shift_register_length = 33 - 4 - 2 - 2 * - period = 125 shift_register_length = 1 - 7 - 0 - 7 * - period = 127 shift_register_length = 33 - 5 - 4 - 1 * - period = 127 shift_register_length = 1 - 8 - 0 - 7 * - period = 4625 shift_register_length = 33 - 7 - 4 - 3 * - period = 4625 shift_register_length = 1 - 2 - 0 - 13 * - period = 311000000 shift_register_length = 33 - 15 - 4 - 15 * - period = 311000000 shift_register_length = 1 - 2 - 0 - 29 .. _common.strobe_on_last: strobe_on_last.vhd ------------------ `View source code on GitHub `__. .. symbolator:: component strobe_on_last is generic ( data_width : positive ); port ( clk : in std_ulogic; --# {{}} input_ready : out std_ulogic; input_valid : in std_ulogic; input_last : in std_ulogic; input_data : in std_ulogic_vector; input_strobe : in std_ulogic_vector; --# {{}} output_ready : in std_ulogic; output_valid : out std_ulogic; output_last : out std_ulogic; output_data : out std_ulogic_vector; output_strobe : out std_ulogic_vector ); end component; The goal of this entity is to process an AXI-Stream so that packets where ``last`` is asserted on a word that is completely strobed out are modified so that ``last`` is instead asserted on the last word which does have a strobe. As a consequence of this, all words in the stream that are completely strobed out are dropped by this entity. .. _common.strobe_on_last.resource_utilization: Resource utilization ____________________ This entity has `netlist builds `__ set up with `automatic size checkers `__ in `module_common.py `__. The following table lists the resource utilization for the entity, depending on generic configuration. .. list-table:: Resource utilization for **strobe_on_last** netlist builds. :header-rows: 1 * - Generics - Total LUTs - FFs - Maximum logic level * - data_width = 8 - 7 - 12 - 3 * - data_width = 32 - 8 - 39 - 3 * - data_width = 64 - 9 - 75 - 3 .. _common.time_pkg: time_pkg.vhd ------------ `View source code on GitHub `__. Contains a couple of methods for working with the VHDL ``time`` type. The ``time`` type can be tricky sometimes because its precision is implementation dependent, just like the ``integer`` and ``universal_integer`` types: ``integer'high`` is * 2147483647 in GHDL 3.0.0-dev, corresponding to a 32 bit signed integer. * 2147483647 in Vivado 2021.2, corresponding to a 32 bit signed integer. ``time'high`` is * 9223372036854775807 fs in GHDL 3.0.0-dev, corresponding to a 64 bit signed integer. Time values greater than this will result in an error. * 2147483647 fs in Vivado 2021.2, corresponding to a 32 bit signed integer. However, Vivado 2021.2 can represent time values greater than this since it uses a dynamic secondary unit for ``time``, as outlined in IEEE Std 1076-2008, page 39. Precision is never greater than 32 bits though. In the standard library, the following functions are available for working with ``time`` values (IEEE Std 1076-2008, page 260): .. code-block:: function "=" (anonymous, anonymous: TIME) return BOOLEAN; function "/=" (anonymous, anonymous: TIME) return BOOLEAN; function "<" (anonymous, anonymous: TIME) return BOOLEAN; function "<=" (anonymous, anonymous: TIME) return BOOLEAN; function ">" (anonymous, anonymous: TIME) return BOOLEAN; function ">=" (anonymous, anonymous: TIME) return BOOLEAN; function "+" (anonymous: TIME) return TIME; function "- (anonymous: TIME) return TIME; function "abs" (anonymous: TIME) return TIME; function "+" (anonymous, anonymous: TIME) return TIME; function "-" (anonymous, anonymous: TIME) return TIME; function "*" (anonymous: TIME; anonymous: INTEGER) return TIME; function "*" (anonymous: TIME; anonymous: REAL) return TIME; function "*" (anonymous: INTEGER; anonymous: TIME) return TIME; function "*" (anonymous: REAL; anonymous: TIME) return TIME; function "/" (anonymous: TIME; anonymous: INTEGER) return TIME; function "/" (anonymous: TIME; anonymous: REAL) return TIME; function "/" (anonymous, anonymous: TIME) return universal_integer; function "mod" (anonymous, anonymous: TIME) return TIME; function "rem" (anonymous, anonymous: TIME) return TIME; function MINIMUM (L, R: TIME) return TIME; function MAXIMUM (L, R: TIME) return TIME; Notably missing is a convenient and accurate way of converting a ``time`` value to ``real`` or ``integer``. So that is most of the complexity in the conversion functions below. .. _common.types_pkg: types_pkg.vhd ------------- `View source code on GitHub `__. Some basic types that make it easier to work with VHDL. Also some basic functions operating on these types. .. _common.width_conversion: width_conversion.vhd -------------------- `View source code on GitHub `__. .. symbolator:: component width_conversion is generic ( input_width : positive; output_width : positive; enable_last : boolean; enable_strobe : boolean; strobe_unit_width : positive; user_width : natural; support_unaligned_packet_length : boolean ); port ( clk : in std_ulogic; --# {{}} input_ready : out std_ulogic; input_valid : in std_ulogic; input_last : in std_ulogic; input_data : in std_ulogic_vector; input_strobe : in std_ulogic_vector; input_user : in std_ulogic_vector; --# {{}} output_ready : in std_ulogic; output_valid : out std_ulogic; output_last : out std_ulogic; output_data : out std_ulogic_vector; output_strobe : out std_ulogic_vector; output_user : out std_ulogic_vector ); end component; Width conversion of an AXI-Stream-like data bus. Can handle downsizing (wide to thin) or upsizing (thin to wide). The data widths must be a power-of-two multiple of each other. E.g. 10->40 is supported while 8->24 is not. There is a generic to enable usage of the ``last`` signal. The ``last`` indicator will be passed along with the data from the ``input`` to ``output`` side as-is. Note that enabling the ``support_unaligned_packet_length`` generic will enable further processing of ``last``, but in barebone configuration the signal is merely passed on. There is a generic to enable strobing of data. The ``strobe`` will be passed on from ``input`` to ``output`` side as-is. Note that enabling ``support_unaligned_packet_length`` generic will enable further processing of ``strobe``, but in barebone configuration the signal is merely passed on. This means, for example, that there might be output words where all strobe lanes are zero when downsizing. There are some limitations, and possible remedies, concerning packet length alignment, depending on if we are doing upsizing or downsizing. See below. Downsizing behavior ___________________ When doing downsizing, one input beat will result in two or more output beats, depending on width configuration. This means that the output packet length is always aligned with the input data width. This is not always desirable when working with the ``strobe`` and ``last`` signals. Say for example that we are converting a bus from 16 to 8, and ``input_last`` is asserted on a beat where the lowest byte is strobed but the highest is not. In this case, we would want ``output_last`` to be asserted on the second to last byte, and the last byte (which is strobed out) to be removed. This is achieved by enabling the ``support_unaligned_packet_length`` generic. If the generic is not set, ``output_last`` will be asserted on the very last byte, which will be strobed out. Upsizing behavior _________________ When upsizing, two or more ``input`` beats result in one ``output`` beat, depending on width configuration. This means that the input packet length must be aligned with the output data width, so that each packet fills up a whole number of output words. If this can not be guaranteed, then the ``support_unaligned_packet_length`` mode can be used. When that is enabled, the input stream will be padded upon ``last`` indication so that a whole output word is filled. Consider the example of converting a bus from 8 to 16, and ``input`` last is asserted on the third input beat. If ``support_unaligned_packet_length`` is disabled, there will be one output beat sent and half an output beat left in the converter. If the mode is enabled however, the input stream will be padded with another byte so that an output beat can be sent. The padded parts will have ``strobe`` set to zero. Note that the handling of unaligned packet lengths is highly dependent on the input stream being well behaved. Specifically 1. There may never be input beats where ``input_strobe`` is all zeros. 2. For all beats except the one where ``input_last`` is asserted, ``input_strobe`` must be asserted on all lanes. 3. There may never be a ``'1'`` above a ``'0'`` in the ``input_strobe``. User signalling _______________ By setting the ``user_width`` generic to a non-zero value, the ``input_user`` port can be used to pass auxillary data along the bus. When downsizing, i.e. when one input beat results in multiple output beats, the ``output_user`` port will have the same width as the ``input_user`` port. Each output beat will have the same ``user`` value as the input beat that created it. When upsizing, i.e. when multiple input beats result in one output beat, the ``output_user`` port will have the same width as the ``input_user`` port multiplied by the conversion factor. The ``output_user`` port will have the concatenated ``input_user`` values from all the input beats that created the output beat. .. _common.width_conversion.resource_utilization: Resource utilization ____________________ This entity has `netlist builds `__ set up with `automatic size checkers `__ in `module_common.py `__. The following table lists the resource utilization for the entity, depending on generic configuration. .. list-table:: Resource utilization for **width_conversion** netlist builds. :header-rows: 1 * - Generics - Total LUTs - FFs - Maximum logic level * - input_width = 32 output_width = 16 enable_last = False enable_strobe = False user_width = 0 support_unaligned_packet_length = False - 20 - 51 - 2 * - input_width = 32 output_width = 16 enable_last = True enable_strobe = True user_width = 0 support_unaligned_packet_length = False - 23 - 59 - 2 * - input_width = 32 output_width = 16 enable_last = True enable_strobe = True user_width = 0 support_unaligned_packet_length = True - 27 - 60 - 3 * - input_width = 32 output_width = 16 enable_last = True enable_strobe = True user_width = 5 support_unaligned_packet_length = True - 32 - 70 - 3 * - input_width = 16 output_width = 32 enable_last = False enable_strobe = False user_width = 0 support_unaligned_packet_length = False - 35 - 51 - 2 * - input_width = 16 output_width = 32 enable_last = True enable_strobe = True user_width = 0 support_unaligned_packet_length = False - 40 - 59 - 2 * - input_width = 16 output_width = 32 enable_last = True enable_strobe = True user_width = 0 support_unaligned_packet_length = True - 44 - 62 - 2 * - input_width = 16 output_width = 32 enable_last = True enable_strobe = True user_width = 5 support_unaligned_packet_length = True - 54 - 77 - 2 .. _common.width_conversion_pkg: width_conversion_pkg.vhd ------------------------ `View source code on GitHub `__. Package with functions for :ref:`common.width_conversion`.