[
  {
    "slug": "af-pdm-rx",
    "name": "af-pdm-rx",
    "shortDescription": "Portable Verilog-2001 raw PDM receiver IP core for FPGA audio pipelines.",
    "longDescription": "af-pdm-rx generates a microphone clock, samples one or more raw 1-bit PDM input lanes, packs accepted bits into fixed-width words and exposes a valid/ready stream for downstream FPGA logic.",
    "category": "audio_signal_processing",
    "tags": [
      "pdm",
      "audio",
      "fpga",
      "verilog",
      "streaming",
      "valid-ready"
    ],
    "domain": "audio",
    "status": "simulation_tested",
    "publicReleaseStatus": "board-build-ready",
    "verificationLevel": "simulation_tested",
    "license": "AccelFury Source Available License v1.0. Closed-source or proprietary use requires a separate commercial license.",
    "commercialSupport": true,
    "repositoryUrl": "https://github.com/AccelFury/af-pdm-rx",
    "pageUrl": "/ip-cores/af-pdm-rx",
    "packageUrl": "",
    "lastUpdated": "2026-04-30",
    "supportedBoards": [
      {
        "name": "Sipeed Tang Primer 20K Dock",
        "family": "Gowin GW2A",
        "status": "build_evidenced",
        "notes": "Board wrappers, constraints, OSS Gowin-compatible build evidence and JTAG programming evidence are public. Measured PDM clock, loopback and microphone evidence remain pending."
      },
      {
        "name": "Sipeed Tang Nano 20K",
        "family": "Gowin GW2AR",
        "status": "wrapper_only",
        "notes": "Board wrapper exists in the public repo, but constraints and measured hardware evidence are fail-closed."
      },
      {
        "name": "Sipeed Tang Mega 138K Dock",
        "family": "Gowin GW5A",
        "status": "wrapper_only",
        "notes": "Board wrapper exists in the public repo, but constraints and measured hardware evidence are fail-closed."
      }
    ],
    "supportedToolchains": [
      {
        "name": "Icarus Verilog",
        "status": "simulation_tested",
        "notes": "The public mandatory simulation path uses iverilog and vvp."
      },
      {
        "name": "OSS CAD Suite / Gowin-compatible flow",
        "status": "build_evidenced",
        "notes": "Archived build evidence exists for selected Tang Primer 20K Dock top modules."
      }
    ],
    "interfaces": [
      {
        "name": "valid_ready_stream",
        "type": "valid/ready",
        "direction": "output",
        "signals": "out_valid_o, out_ready_i, out_data_o, out_lane_o, out_slot_o, out_seq_o",
        "description": "Packed raw PDM words are emitted over a stable valid/ready stream."
      },
      {
        "name": "pdm_microphone",
        "type": "PDM",
        "direction": "external",
        "signals": "pdm_clk_o, pdm_dat_i",
        "description": "External microphone clock output and one or more raw PDM data inputs."
      },
      {
        "name": "control_status",
        "type": "simple wires",
        "direction": "mixed",
        "signals": "enable_i, clear_i, overflow_o, stat_bits_o, stat_words_o, stat_drops_o",
        "description": "Control and status wires for enable, synchronous clear, overflow and counters."
      }
    ],
    "parameters": [
      [
        "LANES",
        "1",
        "Number of PDM data pins."
      ],
      [
        "SLOTS_PER_LANE",
        "1",
        "One microphone per line or phase-separated slots."
      ],
      [
        "WORD_BITS",
        "64",
        "Packed raw PDM word width."
      ],
      [
        "FIFO_ADDR_BITS",
        "4",
        "FIFO depth is 2 ** FIFO_ADDR_BITS."
      ],
      [
        "HALF_PERIOD_CYCLES",
        "8",
        "clk_i cycles per half PDM clock period."
      ],
      [
        "SAMPLE_DELAY_CYCLES",
        "4",
        "Delay from PDM clock transition to sample enable."
      ],
      [
        "LANE_ID_BITS",
        "1",
        "Width of out_lane_o; set manually for LANES > 2."
      ],
      [
        "SEQ_BITS",
        "32",
        "Width of output sequence counter."
      ]
    ],
    "ports": [
      [
        "clk_i",
        "input",
        "Only internal logic clock."
      ],
      [
        "rst_ni",
        "input",
        "Asynchronous active-low reset."
      ],
      [
        "enable_i",
        "input",
        "Enables PDM clocking and capture."
      ],
      [
        "clear_i",
        "input",
        "Synchronous one-cycle clear for counters, FIFO, packer and sequence state."
      ],
      [
        "pdm_clk_o",
        "output",
        "External PDM microphone clock."
      ],
      [
        "pdm_dat_i",
        "input",
        "Raw PDM data lines."
      ],
      [
        "out_valid_o",
        "output",
        "Packed word is available."
      ],
      [
        "out_ready_i",
        "input",
        "Downstream accepts the current word."
      ],
      [
        "out_data_o",
        "output",
        "Packed raw PDM bits."
      ],
      [
        "out_lane_o",
        "output",
        "Lane ID for the word."
      ],
      [
        "out_slot_o",
        "output",
        "Slot ID for the word."
      ],
      [
        "out_seq_o",
        "output",
        "Sequence value for the current output word."
      ],
      [
        "overflow_o",
        "output",
        "Sticky overflow/drop indicator until reset or clear_i."
      ],
      [
        "stat_bits_o",
        "output",
        "Count of raw bits accepted by the packer."
      ],
      [
        "stat_words_o",
        "output",
        "Count of output handshakes."
      ],
      [
        "stat_drops_o",
        "output",
        "Count of completed words dropped because FIFO was full."
      ]
    ],
    "clocks": [
      {
        "name": "clk_i",
        "role": "single internal clock domain",
        "notes": "All internal state is clocked by clk_i."
      },
      {
        "name": "pdm_clk_o",
        "role": "external microphone clock output",
        "notes": "pdm_clk_o is generated for the microphone and is not used as an internal logic clock."
      }
    ],
    "resets": [
      {
        "name": "rst_ni",
        "polarity": "active-low",
        "type": "asynchronous",
        "notes": "Primary reset for all state."
      },
      {
        "name": "clear_i",
        "polarity": "active-high",
        "type": "synchronous one-cycle clear",
        "notes": "Clears counters, FIFO, packer and sequence state."
      }
    ],
    "resourceUsage": [],
    "benchmarks": [
      {
        "name": "Public speed/power benchmark",
        "status": "benchmark_pending",
        "notes": "No public speedup or power-ratio benchmark is claimed. Resource and fmax numbers should be treated as target-dependent until measured."
      }
    ],
    "verification": {
      "simulationStatus": "13 Icarus Verilog test targets are documented as passing.",
      "testbenchStatus": "Public testbenches cover clock generation, sampling, packing, FIFO behavior, slots, lanes, backpressure, overflow, reset and randomized ready stalls.",
      "formalStatus": "Formal checks are not published.",
      "boardValidation": "Tang Primer 20K Dock build and JTAG programming evidence are public. Measured PDM clock, GPIO loopback and microphone evidence remain pending.",
      "knownGaps": [
        "No public real microphone capture yet.",
        "No public long-run hardware validation yet.",
        "No public fmax/resource table committed as measured data yet."
      ]
    },
    "whatItDoes": [
      "Generates a PDM microphone clock.",
      "Samples one or more raw PDM data lanes.",
      "Packs raw PDM bits into fixed-width words.",
      "Emits words through a valid/ready stream."
    ],
    "whatItDoesNotDo": [
      "Does not convert PDM to PCM.",
      "Does not include CIC, FIR or audio filtering.",
      "Does not publish a hardware-ready or production-ready claim."
    ],
    "typicalUseCases": [
      "Raw microphone capture experiments.",
      "FPGA audio front-end prototypes.",
      "Integration test source for streaming and backpressure paths."
    ],
    "integration": {
      "topLevelWrapper": "af_pdm_rx",
      "connectionNotes": "Connect clk_i, rst_ni, enable_i, clear_i, PDM pins and downstream valid/ready signals. Keep board-local PLLs and constraints outside the reusable RTL core.",
      "timingAssumptions": "pdm_clk_o frequency = clk_i frequency / (2 * HALF_PERIOD_CYCLES). Use a board-level PLL or external clock selection when an exact PDM rate is required.",
      "clockDomains": "Single internal clk_i domain. pdm_clk_o is an external output and not an internal clock.",
      "boardConstraints": "Board constraints are evidence-gated. A wrapper does not imply measured hardware support."
    },
    "limitations": [
      "Raw PDM only: no PDM-to-PCM conversion, no CIC/FIR and no audio processing.",
      "Current public release label is board-build-ready, not hardware-ready or production-ready.",
      "Measured pdm_clk_o, GPIO loopback and real microphone evidence are still pending.",
      "Board support is evidence-gated. Presence of a wrapper does not equal measured board support."
    ],
    "publicFacts": [
      "Portable Verilog-2001 core with default_nettype none.",
      "Single internal clock domain clocked by clk_i.",
      "Raw bit packing into a valid/ready stream.",
      "Tang Primer 20K Dock is the first documented hardware target."
    ],
    "aiSummary": {
      "facts": [
        "af-pdm-rx is a public AccelFury Verilog raw PDM receiver IP core.",
        "The public verification level is simulation-tested.",
        "The public release label is board-build-ready, with hardware measurement gaps still open."
      ],
      "doNotOverclaim": [
        "Do not claim PDM-to-PCM conversion.",
        "Do not claim production readiness.",
        "Do not claim measured board validation until the pending evidence is public."
      ]
    }
  }
]
