name: "16x8 Binarized Dense Layer"
category: "AI/ML Accelerators"
complexity: "Medium"
description: |
  Implement a combinational single-layer binary neural network inference block
  with 16 binary inputs and 8 binary outputs.

  The module receives one 16-bit input vector `x_in` and produces one 8-bit
  output vector `y_out`. Output bit `y_out[i]` corresponds to neuron `i` and
  must be computed from the current input vector only. There is no clock,
  latency, valid signal, or internal state.

  One useful interpretation is a tiny binarized digit-pattern detector:
  `x_in` can be viewed as a 4x4 black/white image patch, and each output
  neuron acts like a fixed learned detector for one candidate class or
  feature. For example, `y_out[0]` through `y_out[7]` may be viewed as
  detections for digits 0 through 7. Because this module is only a single
  thresholded dense layer, the output is not required to be one-hot: multiple
  output bits may be 1 at the same time, and all output bits may also be 0.

  BINARY VALUE INTERPRETATION:
  - Each bit represents a bipolar value, not an unsigned integer bit.
  - For any input bit or weight bit:
    - bit value 1 represents +1
    - bit value 0 represents -1
  - Because of this encoding, treating the bits as ordinary 0/1 integers is
    incorrect.

  For each output neuron `i` from 0 to 7:
  - Let `w_i` be the fixed 16-bit weight vector listed below.
  - Let `T_i` be the signed integer threshold listed below.
  - Define
    `score_i = sum for k=0..15 of value(x_in[k]) * value(w_i[k])`
    where `value(1)=+1` and `value(0)=-1`.
  - `y_out[i]` must be 1 when `score_i >= T_i`, otherwise 0.
  - If `score_i` is exactly equal to `T_i`, the output is 1.

  BIT ORDERING:
  - `x_in[0]` is compared with bit 0 of each weight constant.
  - `x_in[15]` is compared with bit 15 of each weight constant.
  - `y_out[0]` is neuron 0 and `y_out[7]` is neuron 7.

  FIXED NEURON PARAMETERS:
  - neuron 0: weight = `16'hB3A6`, threshold = 2
  - neuron 1: weight = `16'h5CD9`, threshold = 0
  - neuron 2: weight = `16'hE3C5`, threshold = -4
  - neuron 3: weight = `16'h35B6`, threshold = 6
  - neuron 4: weight = `16'hCA79`, threshold = -2
  - neuron 5: weight = `16'h6E1E`, threshold = 4
  - neuron 6: weight = `16'h95E3`, threshold = 8
  - neuron 7: weight = `16'hF42D`, threshold = 0

interface:
  module_name: "bnn_dense8"
  clocked: false
  ports:
    - name: "x_in"
      type: "input"
      width: "16"
      description: "16-bit binary input activation vector, for example a binarized 4x4 image patch"
    - name: "y_out"
      type: "output"
      width: "8"
      description: "8-bit binary output activation vector, one bit per neuron or candidate class detector"

target_platform:
  device_family: "AMD Xilinx Zynq-7000"

tasks:
  - name: "Ultra-Compact Binarized Digit Detector"
    constraints:
      max_lut: 220
      max_ff: 0
      max_bram: 0
      max_dsp: 0
      min_frequency: 150
    objective:
      goal: "minimise"
      target: "LUT"
