name: "Sliding-Window Heart-Rate Estimator"
category: "Embedded Control & I/O"
complexity: "Medium"
description: |
  Implement a synchronous heart-rate estimator that reports beats per
  minute (BPM) from a stream of detected heartbeat events.

  Each rising edge of `clk` represents one 50 ms sample period. The
  input `peak_in` is a debounced one-cycle pulse that indicates one
  detected heartbeat at that sample. When `peak_in` is low, no heartbeat
  event occurred in that sample period.

  OUTPUT DEFINITION:
  - The BPM estimate is based on a sliding window covering the most
    recent 100 sampled cycles, including the current cycle.
  - `bpm_out` must equal 12 times the number of heartbeat events present
    in that 100-sample window. This corresponds to converting the count
    from a 5-second window into beats per minute.
  - The module must update the estimate every clock cycle after sampling
    the current `peak_in` input.

  VALIDITY RULES:
  - `bpm_valid` remains LOW until the module has observed 100 sampled
    cycles since reset was last asserted.
  - While `bpm_valid` is LOW, `bpm_out` must be 0.
  - Once `bpm_valid` becomes HIGH, it remains HIGH until the next reset.

  INPUT GUARANTEES:
  - Each asserted `peak_in` represents exactly one heartbeat event.
  - The testbench will not present two heartbeat events closer than
    4 clock cycles apart.

  RESET:
  - `rst` is synchronous and active-high.
  - On reset, clear all stored history, restart the window-fill process,
    drive `bpm_out` to 0, and deassert `bpm_valid`.

interface:
  module_name: "bpm_calculator"
  clocked: true
  ports:
    - name: "clk"
      type: "input"
      width: "1"
      description: "Clock signal; each cycle represents one 50 ms sample period"
    - name: "rst"
      type: "input"
      width: "1"
      description: "Synchronous active-high reset"
    - name: "peak_in"
      type: "input"
      width: "1"
      description: "One-cycle pulse indicating a detected heartbeat event"
    - name: "bpm_valid"
      type: "output"
      width: "1"
      description: "High when a full 100-sample window has been observed since reset"
    - name: "bpm_out"
      type: "output"
      width: "9"
      description: "Unsigned BPM estimate for the current 100-sample window"

target_platform:
  device_family: "AMD Xilinx Zynq-7000"

tasks:
  - name: "Area-Efficient Sliding-Window BPM Estimator"
    constraints:
      max_lut: 120
      max_ff: 140
      max_bram: 0
      max_dsp: 0
      min_frequency: 150
    objective:
      goal: "minimise"
      target: "LUT"
