---
title: "Digital Lock-in Amplifier on FPGA"
url: "https://maker.wiznet.io/irina/projects/digital-lock-in-amplifier-on-fpga/"
markdown_url: "https://maker.wiznet.io/irina/projects/digital-lock-in-amplifier-on-fpga/md"
type: "UCC: User Created Content"
author: "Klontong24"
author_url: "https://github.com/Klontong24/dlia-fpga"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "Klontong24"
original_url: "https://github.com/Klontong24/dlia-fpga"
published: "2026-07-29"
language: "ko"
likes: 0
views: 134
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# Digital Lock-in Amplifier on FPGA

> Cyclone V FPGA에 구현한 2채널 디지털 락인 증폭기. 잡음 속 미약 신호의 크기·위상차를 실시간 측정해 W5500 TCP로 호스트 PC에 스트리밍합니다.

Original author: Klontong24 (source: https://github.com/Klontong24/dlia-fpga)

## Article

## 프로젝트가 하는 일

**락인 증폭기(Lock-in Amplifier)** 는 잡음에 파묻힌 미약한 신호를, 기준(reference) 주파수에 동기시켜 뽑아내는 계측 기법입니다. 이 프로젝트는 그것을 **FPGA 디지털 로직으로** 구현한 **2채널 DLIA**입니다.

- **측정 대상**: 두 입력 신호 — **body 채널**과 **reference 채널** — 의 **크기(magnitude)** 와 **위상차(phase difference, delta_phase = φ_body − φ_ref)** 를 실시간 측정

- **신호 체인(전부 손으로 짠 Verilog RTL)**:
  1. **NCO**(수치제어발진기, `my_nco.v`) — sin/cos 생성 (32-bit 위상 누산기)
  2. **IQ 믹서**(`nco_mixer_pipe.v`) — 입력을 기준 신호와 곱해 I/Q 분리
  3. **락인 적분기**(`lock_in_accum.v`) — 정수 주기 적분 + 정규화
  4. **CORDIC**(`cordic_iq.v`) — I/Q 쌍에서 크기·위상 산출 (Q1.31)

- **클럭 도메인 교차**: 두 ADC 사이를 **그레이 포인터 비동기 FIFO**(`async_fifo_gray.v`)로 안전하게 건넘

- **검증**: cocotb 골든모델(Python+NumPy 기준값 대조) + Verilog 테스트벤치(ModelSim/Questa)

- **호스트 도구**: Python으로 20바이트 프레임 파싱 → 실시간 Vpp·위상 표시(`dlia_w5500_host.py`), N샘플 CSV 수집(`dlia_w5500_collect.py`), SNR·주파수응답 분석

![](https://maker.wiznet.io/upload/ckeditor5/1047934189%5F1785320307%2Epng)

## COMPONENTS

| Component | Notes | Qty |
| --- | --- | --- |
| Intel Cyclone V SoC 보드 | `5CSEMA4U23C6` (예: DE10-Nano 계열), 최상위 `eit_system_top` | x 1 |
| **WIZnet W5500 이더넷 모듈** | 측정 결과 **TCP 스트리밍** — FPGA가 **순수 RTL**로 직접 구동(SPI) | x 1 |
| 2채널 ADC | body 채널 + reference 채널 입력 (100 kSPS) | x 1 |
| 호스트 PC | Python 수신·분석 도구(실시간 표시·CSV 수집) | x 1 |

## WIZnet이 들어가는 위치![](https://maker.wiznet.io/upload/ckeditor5/1047934189%5F1785320324%2Epng)

이 프로젝트에서 W5500은 **측정 결과를 호스트 PC로 실어 나르는 TCP 스트리밍 인터페이스**이며, 특징적으로 **MCU 없이 순수 Verilog RTL로 W5500을 직접 구동**합니다.

- **역할**: FPGA가 CORDIC로 계산한 결과(**샘플당 20바이트**: mag_body, phase_body, mag_ref, phase_ref, delta_phase)를 **W5500의 TCP 소켓 0**으로 스트리밍합니다.

- **연결**: **SPI (Mode 0)**. 범용 SPI 마스터(`spi_master.v`)가 물리 계층을 담당합니다. SPI·W5500 도메인은 50MHz.

- **순수 RTL W5500 스택 (핵심 차별점)**:
  - `w5500_init.v` — **전원인가 초기화 FSM**: 리셋 → **VERSIONR 읽어 칩 확인** → MAC/IP 설정 → 소켓 open + connect
  - `eit_w5500_streamer.v` — CORDIC 결과를 **TCP로 스트리밍**
  - `w5500_data_link.v` — init FSM + streamer 래퍼
  - `w5500_bringup.v` — 초기 SPI/링크 테스트 루틴

- **핀맵**: W5500 SPI 물리핀은 **Quartus 핀 배정(**`**DAQ1.qsf**`**)·**`**constraints/**` 에 정의됩니다(README에는 미기재 → 소스 확인).

![](https://maker.wiznet.io/upload/ckeditor5/1047934189%5F1785320368%2Epng)

**TOE(하드웨어 TCP/IP)를 실제로 활용합니다.** 이 프로젝트는 W5500의 **하드웨어 TCP 소켓**을 열어 세션을 칩이 처리하게 하고, FPGA는 그 소켓에 측정 데이터만 밀어 넣습니다. 소프트웨어 TCP/IP 스택(lwIP 등)이나 소프트 CPU 없이, **FPGA 로직만으로 100 kSPS 측정 → TCP 전송**을 완결하는 구조라, W5500의 "TCP/IP를 칩에 오프로드" 장점이 극대화됩니다.

## 주요 사양

| 항목 | 값 |
| --- | --- |
| FPGA | Intel Cyclone V SoC `5CSEMA4U23C6` |
| 최상위 엔티티 | `eit_system_top` (Quartus 프로젝트 `DAQ1`) |
| 클럭 | 50MHz 입력 → PLL → **150MHz DSP 클럭** / SPI·W5500 50MHz |
| 샘플레이트 | **100 kSPS** |
| 스트림 페이로드 | **20바이트/샘플**, TCP 소켓 0 |
| CORDIC 위상 | Q1.31 부호, 범위 [−π, +π) |

## 구현 메모

- **툴체인**: Intel Quartus Prime (Cyclone V 지원, 20.1+). `DAQ1.qpf` 열고 컴파일 → `DAQ1.sof` 프로그래밍.

- **저장소명 주의**: 저장소는 `dlia-fpga`이지만 Quartus 프로젝트(`DAQ1`)·최상위 엔티티(`eit_system_top`)는 빌드·테스트 참조 유지를 위해 그대로 둡니다.

- **언어**: Verilog(RTL 중심) + Python(호스트·cocotb).

- **초기 단계**: 커밋 3·스타 0의 개인 프로젝트. `docs/`에 매뉴얼·그림 추가 예정.

## 유사 프로젝트 (maker.wiznet.io)

FPGA가 **W5500을 직접 구동해 계측 데이터를 네트워크로 스트리밍**하는, 성격이 가까운 글들입니다.

1. **FPGA Slow Control Interlock System / SCIS (irina)** — <https://maker.wiznet.io/irina/projects/fpga-slow-control-interlock-system-scis/> FPGA가 W5500(SPI)을 구동해 계측 데이터를 네트워크로 처리. 구조("FPGA 계측 → W5500 스트리밍")가 가장 유사(SCIS는 UDP, 이쪽은 TCP).

2. **FPGA + W5500 Control Unit (mark)** — <https://maker.wiznet.io/mark/projects/fpga-w5500-control-unit/> FPGA가 W5500을 중앙 제어로 쓰는 다채널 계측·제어 시스템.

3. **pComputer (irina)** — <https://maker.wiznet.io/irina/projects/pcomputer-a-minimal-computer-on-fpga/> FPGA 안에 W5500 SPI 마스터를 직접 구현. "순수 로직으로 W5500 구동"이라는 점이 통함.

4. **TCP/IP stack design based on FPGA and W5500 (WIZnet Makers)** — <https://maker.wiznet.io/2019/04/26/tcp-ip-stack-design-based-on-fpga-and-embedded-ethernet-w5500/> FPGA가 W5500을 TCP/IP 서버로 구동하는 기본 예제. dlia-fpga의 TCP 스트리밍과 개념이 같음.

| 항목 | dlia-fpga | SCIS | FPGA+W5500 Control Unit | pComputer |
| --- | --- | --- | --- | --- |
| 성격 | 락인 증폭기(계측) | 계측 집약+인터록 | 다채널 계측·제어 | 자작 RISC-V 컴퓨터 |
| FPGA | Cyclone V | GateMate | Spartan-6 | 다양(Zynq 등) |
| W5500 구동 | 순수 RTL, TCP | 순수 RTL, UDP·듀얼 | 중앙 제어 | RTL SPI 마스터 |
| 전송 | TCP 소켓0 스트림 | UDP 8소켓 | 이더넷 | MMIO 매핑 |

## FAQ

**Q: 이 프로젝트는 무엇인가요?** A: Cyclone V FPGA에 2채널 디지털 락인 증폭기를 구현해, 미약 신호의 크기·위상차를 측정하고 W5500 TCP로 PC에 스트리밍합니다.

**Q: W5500은 어떻게 쓰이나요?** A: FPGA가 순수 RTL로 W5500을 초기화(리셋·VERSIONR·MAC/IP·소켓 open/connect)하고, 측정 결과(20바이트/샘플)를 TCP 소켓 0으로 스트리밍합니다.

**Q: 하드웨어 TCP/IP(TOE)를 쓰나요?** A: 네. W5500의 하드웨어 TCP 소켓을 써서 세션을 칩이 처리하고, FPGA는 소켓에 데이터만 씁니다. 소프트웨어 스택이나 소프트 CPU 없이 동작합니다.

**Q: W5500 핀은 무엇인가요?** A: Quartus 핀 배정 파일 `DAQ1.qsf`·`constraints/`에 정의돼 있습니다. 소스를 확인하세요.

---

## What the Project Does

A **lock-in amplifier** extracts a weak signal buried in noise by synchronizing to a reference frequency. This project implements that as a **two-channel digital lock-in amplifier (DLIA)** in FPGA logic.

- **Measures**: the **magnitude** and **phase difference** (delta_phase = φ_body − φ_ref) between two inputs — a **body** channel and a **reference** channel — in real time

- **Signal chain (all hand-written Verilog RTL)**:
  1. **NCO** (`my_nco.v`) — sin/cos, 32-bit phase accumulator
  2. **IQ mixer** (`nco_mixer_pipe.v`) — multiplies input by the reference to split I/Q
  3. **Lock-in accumulator** (`lock_in_accum.v`) — integer-period integration + normalization
  4. **CORDIC** (`cordic_iq.v`) — magnitude and phase from the I/Q pair (Q1.31)

- **Clock-domain crossing**: a **gray-pointer async FIFO** (`async_fifo_gray.v`) bridges the two ADCs safely

- **Verification**: cocotb golden model (Python/NumPy reference) + Verilog testbenches (ModelSim/Questa)

- **Host tools**: Python parses the 20-byte frames for live Vpp/phase readout, N-sample CSV capture, and SNR/frequency-response analysis

![](https://maker.wiznet.io/upload/ckeditor5/1047934189%5F1785320395%2Epng)

## Where WIZnet Fits

Here the W5500 is the **TCP streaming interface that carries results to the host PC**, and notably the FPGA drives it with **pure Verilog RTL — no MCU**.

![](https://maker.wiznet.io/upload/ckeditor5/1047934189%5F1785320411%2Epng)

- **Role**: the FPGA streams each CORDIC result (**20 bytes/sample**: mag_body, phase_body, mag_ref, phase_ref, delta_phase) to the **W5500 TCP socket 0**.

- **Connection**: **SPI (Mode 0)** via a generic master (`spi_master.v`); the SPI/W5500 domain runs at 50 MHz.

- **Pure-RTL W5500 stack (the key differentiator)**:
  - `w5500_init.v` — power-on init FSM: reset → **read VERSIONR to confirm the chip** → set MAC/IP → socket open + connect
  - `eit_w5500_streamer.v` — streams CORDIC results over TCP
  - `w5500_data_link.v` — wrapper tying init FSM + streamer
  - `w5500_bringup.v` — initial SPI/link bring-up

- **Pin map**: W5500 SPI pins are defined in the Quartus assignments (`DAQ1.qsf`) and `constraints/` (not in the README — check the source).

![](https://maker.wiznet.io/upload/ckeditor5/1047934189%5F1785320423%2Epng)

**It genuinely uses the hardware TCP/IP (TOE).** The design opens a W5500 hardware TCP socket so the chip handles the session, while the FPGA just pushes measurement data into the socket. With no software TCP/IP stack (lwIP) or soft CPU, the whole "100 kSPS measure → TCP send" path is completed in FPGA logic — maximizing the W5500's "offload TCP/IP to the chip" advantage.

## Specifications

| Item | Value |
| --- | --- |
| FPGA | Intel Cyclone V SoC `5CSEMA4U23C6` |
| Top entity | `eit_system_top` (Quartus project `DAQ1`) |
| Clocking | 50 MHz → PLL → **150 MHz DSP**; SPI/W5500 at 50 MHz |
| Sample rate | **100 kSPS** |
| Stream payload | **20 bytes/sample**, TCP socket 0 |
| CORDIC phase | Q1.31 signed, range [−π, +π) |

## Implementation Notes

- **Toolchain**: Intel Quartus Prime (Cyclone V, 20.1+). Open `DAQ1.qpf`, compile → `DAQ1.sof`, program.

- **Naming**: the repo is `dlia-fpga`, but the Quartus project (`DAQ1`) and top entity (`eit_system_top`) are kept as-is to preserve build/testbench references.

- **Languages**: Verilog (RTL) + Python (host, cocotb).

- **Early stage**: 3 commits, 0 stars; manual/figures to be added under `docs/`.

## Similar Projects (maker.wiznet.io)

Projects that, like dlia-fpga, **drive the W5500 from FPGA logic to stream measurement data over the network**.

1. **FPGA Slow Control Interlock System / SCIS (irina)** — <https://maker.wiznet.io/irina/projects/fpga-slow-control-interlock-system-scis/> — FPGA drives W5500 (SPI) to move measurement data; closest structure ("FPGA measure → W5500 stream"; SCIS uses UDP, this uses TCP).

2. **FPGA + W5500 Control Unit (mark)** — <https://maker.wiznet.io/mark/projects/fpga-w5500-control-unit/> — multi-channel measure/control with W5500 as the central interface.

3. **pComputer (irina)** — <https://maker.wiznet.io/irina/projects/pcomputer-a-minimal-computer-on-fpga/> — implements a W5500 SPI master inside the FPGA; shares "drive W5500 from pure logic."

4. **TCP/IP stack design based on FPGA and W5500 (WIZnet Makers)** — <https://maker.wiznet.io/2019/04/26/tcp-ip-stack-design-based-on-fpga-and-embedded-ethernet-w5500/> — an FPGA driving the W5500 as a TCP/IP server; same concept as dlia-fpga's TCP streaming.

| Item | dlia-fpga | SCIS | FPGA+W5500 Control Unit | pComputer |
| --- | --- | --- | --- | --- |
| Nature | Lock-in amplifier (measurement) | Measurement + interlock | Multi-channel measure/control | From-scratch RISC-V computer |
| FPGA | Cyclone V | GateMate | Spartan-6 | Various (Zynq etc.) |
| W5500 drive | Pure RTL, TCP | Pure RTL, UDP·dual | Central interface | RTL SPI master |
| Transport | TCP socket 0 stream | UDP 8 sockets | Ethernet | MMIO-mapped |

## FAQ

**Q: What is this project?** A: A two-channel digital lock-in amplifier on a Cyclone V FPGA that measures magnitude/phase difference of weak signals and streams results to a PC over W5500 TCP.

**Q: How is the W5500 used?** A: The FPGA initializes the W5500 in pure RTL (reset, VERSIONR, MAC/IP, socket open/connect) and streams results (20 bytes/sample) over TCP socket 0.

**Q: Does it use hardware TCP/IP (TOE)?** A: Yes. It uses a W5500 hardware TCP socket so the chip handles the session, while the FPGA only writes data into the socket — no software stack or soft CPU.

**Q: What are the W5500 pins?** A: Defined in the Quartus assignments `DAQ1.qsf` and `constraints/`. Check the source.

---

- **Programming Language:** Verilog (RTL) · Python (host/cocotb)

- **Application:** FPGA · 계측/DSP · 락인 증폭기 · 데이터 획득(DAQ) · 네트워크 스트리밍

- **Tags:** W5500, FPGA, Cyclone-V, lock-in-amplifier, DLIA, NCO, CORDIC, DSP, TCP, SPI, measurement, DAQ, MIT

---

Source: https://maker.wiznet.io/irina/projects/digital-lock-in-amplifier-on-fpga/
