name: "Streaming Run-Length Encoder"
category: "Cryptography & Compression"
complexity: "Medium"
description: >
  Implement a streaming run-length encoder for an 8-bit input stream.

  On each cycle where `in_valid` is high, one input byte is accepted.
  Consecutive identical bytes belong to the same run. Each emitted output
  word uses `out_data[15:8]` for the run length and `out_data[7:0]` for
  the byte value.

  Behaviour requirements:
  - A run ends when a different valid input byte arrives, when the run
    length reaches 255, or when `in_last` is high on a valid input byte.
  - When a different valid input byte arrives, emit the completed run and
    begin a new run with the new byte.
  - When a matching byte brings the accumulated count to 255, emit
    `{8'd255, value}` on that same cycle. For example, if the current
    run has 254 bytes and the next valid byte matches, emit the 255-count
    run on that cycle. Any later matching bytes start a fresh run.
  - `in_last` is only meaningful when `in_valid` is high and marks the
    final input byte of the stream.
  - If the final input byte continues the current run, emit that final run
    with `out_last` asserted.
  - If the final input byte starts a new run after emitting the previous
    run, emit the final run on the next cycle and assert `out_last` on
    that output.
  - `out_valid` must be high only on cycles that emit a run.
  - `out_last` must be high only for the final emitted run of a stream.
  - When `out_valid` is low, `out_last` must be low.
  - When `in_valid` is low, ignore `in_data` and `in_last` and preserve
    any partially accumulated run.
  - After the final run is emitted, the encoder must be ready to start a
    new stream on a later valid cycle.
  - `rst` is synchronous active-high and clears all internal state and
    outputs.

interface:
  module_name: "rle_encoder"
  clocked: true
  ports:
    - name: "clk"
      type: "input"
      width: "1"
      description: "Clock"
    - name: "rst"
      type: "input"
      width: "1"
      description: "Synchronous active-high reset"
    - name: "in_valid"
      type: "input"
      width: "1"
      description: "Input byte valid"
    - name: "in_data"
      type: "input"
      width: "8"
      description: "Input byte value"
    - name: "in_last"
      type: "input"
      width: "1"
      description: "High with the final valid input byte of a stream"
    - name: "out_valid"
      type: "output"
      width: "1"
      description: "High when an encoded run is emitted"
    - name: "out_data"
      type: "output"
      width: "16"
      description: "Encoded output word: {run_length, byte_value}"
    - name: "out_last"
      type: "output"
      width: "1"
      description: "High on the final emitted run of a stream"

target_platform:
  device_family: "AMD Xilinx Zynq-7000"

tasks:
  - name: "Streaming RLE Encoder"
    constraints:
      max_lut: 110
      max_ff: 80
      max_bram: 0
      max_dsp: 0
      min_frequency: 250
    objective:
      goal: "maximise"
      target: "Fmax"
