name: "AXI4-Stream 8-to-32 Upsizer"
category: "Networking & Communications"
complexity: "Medium"
description: >
  Implement an AXI4-Stream upsizer that converts an 8-bit input stream
  into a 32-bit output stream.

  The module accepts one byte at a time on the slave AXI4-Stream
  interface and packs consecutive input bytes into a single 32-bit output
  word on the master AXI4-Stream interface.

  AXI4-STREAM HANDSHAKE:
  - An input transfer occurs on a rising clock edge when both
    `s_axis_tvalid` and `s_axis_tready` are high.
  - An output transfer occurs on a rising clock edge when both
    `m_axis_tvalid` and `m_axis_tready` are high.
  - When `m_axis_tready` is low, the module must hold any pending output
    word stable and must apply backpressure on the input side whenever
    it cannot accept additional bytes.

  DATA PACKING:
  - The first accepted byte of an output word is stored in bits [7:0].
  - The second accepted byte is stored in bits [15:8].
  - The third accepted byte is stored in bits [23:16].
  - The fourth accepted byte is stored in bits [31:24].
  - After four bytes have been accepted, `m_axis_tvalid` must assert to
    present the packed 32-bit word.

  PACKET BOUNDARIES:
  - `s_axis_tlast` marks the final byte of an input packet.
  - If `s_axis_tlast` is accepted before four bytes have been collected,
    the module must make the partial 32-bit word available on the output
    immediately after that accepting clock edge, with no extra flush
    cycle.
  - Any unused byte lanes in a partial output word must be filled with
    zeros.
  - `m_axis_tkeep` indicates which output byte lanes are valid:
      4'b0001 = 1 valid byte
      4'b0011 = 2 valid bytes
      4'b0111 = 3 valid bytes
      4'b1111 = 4 valid bytes
  - `m_axis_tlast` must be asserted on the output word that contains the
    final byte of the input packet.

  RESET:
  - `rst` is synchronous and active-high.
  - On reset, clear any partially collected input bytes, deassert all
    output valid signals, and return the module to its idle state.

interface:
  module_name: "axis_width_converter"
  clocked: true
  ports:
    - name: "clk"
      type: "input"
      width: "1"
      description: "Clock signal"
    - name: "rst"
      type: "input"
      width: "1"
      description: "Synchronous active-high reset"
    - name: "s_axis_tdata"
      type: "input"
      width: "8"
      description: "Input AXI4-Stream data byte"
    - name: "s_axis_tvalid"
      type: "input"
      width: "1"
      description: "Input AXI4-Stream valid"
    - name: "s_axis_tready"
      type: "output"
      width: "1"
      description: "Input AXI4-Stream ready"
    - name: "s_axis_tlast"
      type: "input"
      width: "1"
      description: "Input end-of-packet marker"
    - name: "m_axis_tdata"
      type: "output"
      width: "32"
      description: "Packed output AXI4-Stream word"
    - name: "m_axis_tkeep"
      type: "output"
      width: "4"
      description: "Output byte-valid mask"
    - name: "m_axis_tvalid"
      type: "output"
      width: "1"
      description: "Output AXI4-Stream valid"
    - name: "m_axis_tready"
      type: "input"
      width: "1"
      description: "Output AXI4-Stream ready"
    - name: "m_axis_tlast"
      type: "output"
      width: "1"
      description: "Output end-of-packet marker"

target_platform:
  device_family: "AMD Xilinx Zynq-7000"

tasks:
  - name: "Area-Efficient AXI4-Stream Upsizer"
    constraints:
      max_lut: 90
      max_ff: 64
      max_bram: 0
      max_dsp: 0
      min_frequency: 200
    objective:
      goal: "minimise"
      target: "LUT"
