name: "Streaming 3x3 CNN Convolution Layer"
category: "AI/ML Accelerators"
complexity: "Hard"
description: >
  Design an efficient 3x3 convolution module for a CNN layer on FPGA.
  Input: 28x28 grayscale image (1 input channel, 8-bit unsigned pixels).
  Apply 4 output filters with 3x3 kernels (8-bit signed weights, hardcoded).
  Filter 0 (horizontal edge): [[-1,-2,-1], [0,0,0], [1,2,1]].
  Filter 1 (vertical edge): [[-1,0,1], [-2,0,2], [-1,0,1]].
  Filter 2 (blur): [[1,2,1], [2,4,2], [1,2,1]].
  Filter 3 (sharpen): [[0,-1,0], [-1,5,-1], [0,-1,0]].
  Biases per filter: [0, 0, 8, 10] (8-bit signed).
  Use stride 1 and zero-padding 1 to produce output feature maps of 28x28x4.
  Apply bias addition and ReLU activation (clamp negatives to 0, saturate at 255).
  Output: 4 x 8-bit unsigned packed into 32-bit per output position.
  Row-major input/output streaming. Module asserts 'done' for one cycle when complete.

sources:
  - "Yan et al. (2022) - FPGA CNN with Resource Multiplexing (1745 LUTs, 97.3% MNIST)"
  - "Laurain et al. (2022) - Efficient FPGA CNN Accelerators (142 LUTs per conv layer)"
  - "Zhang et al. (2015) - Optimizing FPGA-based Accelerator Design for Deep CNNs"
  - "https://arxiv.org/pdf/1809.01536 - Depthwise Separable Conv on FPGA"

interface:
  module_name: "cnn_conv3x3"
  clocked: true
  ports:
    - name: "clk"
      type: "input"
      width: "1"
    - name: "rst"
      type: "input"
      width: "1"
    - name: "start"
      type: "input"
      width: "1"
    - name: "pixel_in"
      type: "input"
      width: "8"
    - name: "pixel_valid"
      type: "input"
      width: "1"
    - name: "pixel_ready"
      type: "output"
      width: "1"
    - name: "out_pixel"
      type: "output"
      width: "32"
    - name: "out_valid"
      type: "output"
      width: "1"
    - name: "out_ready"
      type: "input"
      width: "1"
    - name: "done"
      type: "output"
      width: "1"

target_platform:
  device_family: "AMD Xilinx Zynq-7000"

tasks:
  - name: "Resource-Efficient CNN Conv Layer"
    constraints:
      max_lut: 600
      max_registers: 390
      min_frequency: 100
      max_latency: 5000
    objective:
      goal: "maximise"
      target: "Fmax"
