name: "Fixed-Point PID Robot Position Controller"
category: "Embedded Control & I/O"
complexity: "Medium"
description: >
  Implement a discrete PID controller for position control with single-cycle update latency.
  
  The controller computes a control output based on the error between a
  setpoint and the current position. The internal arithmetic uses scaled fixed-point
  values to maintain precision and avoid premature saturation.

  PID LOGIC:
    1. Error Calculation:
       error = setpoint - position (Handle 17-bit overflow)

    2. PID Terms (All arithmetic is fixed-point, result scaled by >>> 8):
       P_term = (error * Kp) >>> 8
       D_term = ((error - prev_error) * Kd) >>> 8
       
       // Integral Term: Accumulate the SCALED error term
       // integral_next = clamp(integral + ((error * Ki) >>> 8))
       I_term = integral_next

    3. Output:
       output = clamp(P_term + I_term + D_term)

    4. State Update:
       Update integral and prev_error on clock edge.
       Output is registered.
  
  CONSTRAINTS & GENERATION DETAILS:
  - Latency: Single-cycle. Logic from inputs to registers must complete in one cycle. 
    (No multi-stage pipelining).
  - Accumulator: The integral term MUST accumulate the weighted error ((error*Ki)>>8).
    Do NOT accumulate the raw error or the integrator will saturate prematurely.
  - Clamping: Both the integral state and the final output must be clamped to
    the 16-bit signed range [-32768, +32767].

  FIXED-POINT FORMAT:
  - Position/Setpoint/Output: 16-bit signed (Q8.8)
  - Gains (Kp, Ki, Kd): 8-bit unsigned (Q0.8)
  
  REQUIREMENTS:
  - Updates occur on rising edge of `clk` when `enable` is high.
  - `rst` clears all internal state and output.

interface:
  module_name: "robot_controller"
  clocked: true
  ports:
    - name: "clk"
      type: "input"
      width: "1"
      description: "Clock signal"
    - name: "rst"
      type: "input"
      width: "1"
      description: "Synchronous reset, active high"
    - name: "enable"
      type: "input"
      width: "1"
      description: "Enable PID computation (process when high)"
    - name: "setpoint"
      type: "input"
      width: "16"
      description: "Desired position, signed Q8.8 fixed-point"
    - name: "position"
      type: "input"
      width: "16"
      description: "Current position, signed Q8.8 fixed-point"
    - name: "kp"
      type: "input"
      width: "8"
      description: "Proportional gain, unsigned Q0.8 fixed-point"
    - name: "ki"
      type: "input"
      width: "8"
      description: "Integral gain, unsigned Q0.8 fixed-point"
    - name: "kd"
      type: "input"
      width: "8"
      description: "Derivative gain, unsigned Q0.8 fixed-point"
    - name: "control_out"
      type: "output"
      width: "16"
      description: "PID control output, signed Q8.8 fixed-point (saturated)"

target_platform:
  device_family: "AMD Xilinx Zynq-7000"

tasks:
  - name: "Area-Efficient PID Controller"
    constraints:
      max_lut: 200
      max_ff: 100
      max_bram: 0
      max_dsp: 2
      min_frequency: 50
    objective:
      goal: "minimise"
      target: "LUT"
