Skip to content

Latest commit

 

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📷 Zybo Z7 NPU 가속기 : 이벤트 카메라 기반 저지연 팬틸트 추적 시스템

Low-Latency Pan-Tilt Tracking System Based on an Event Camera (Team of 3)





Zybo Z7-20과 이벤트 카메라 기반 팬틸트 추적 시스템

이벤트 카메라에서 발생한 좌표·극성 정보를 64×64×2 Event Tensor로 누적하고, FPGA에 구현한 Dense INT8 Tiny CNN이 표적 위치를 추론하는 Zynq-7000 기반 객체 추적 SoC입니다. NPU가 출력한 좌표는 카메라용 Pan/Tilt와 레이저용 Pan/Tilt 제어기로 전달되며, Dead Zone·Slew Limit·Safe Limit·Watchdog·Emergency Stop을 포함한 안전 제어 경로를 거칩니다.

ARM Cortex-A9 Processing System은 AXI4-Lite로 NPU 입력과 설정 레지스터를 관리하고, Programmable Logic은 이벤트 전처리·Tensor 생성·CNN 추론·좌표 복원·서보 및 레이저 인터록을 하드웨어로 수행합니다. Python Integer Golden Model, Verilog self-checking testbench, PS 드라이버 호스트 시험, Vivado 배치·배선 결과를 하나의 재현 흐름으로 구성했습니다.

대상 소자는 Xilinx Zynq-7000 xc7z020clg400-1이며, 전체 설계는 100 MHz 단일 PL 클럭 도메인에서 동작합니다. 최종 모델의 기준 결과는 target_x=36, target_y=28, target_score=43, 추론 지연은 125,845 cycles입니다.


0. 목차

  1. 동작 시나리오
  2. 핵심 기술 요약
  3. 프로젝트 개요
  4. 주요 기능
  5. 시스템 구성
  6. 아키텍처
  7. Tensor와 CNN 데이터 형식
  8. AXI4-Lite 인터페이스
  9. 추적·서보·안전 제어
  10. 처리 순서와 상태 전이
  11. 실행 구조와 소스 구성
  12. 핵심 설계 포인트
  13. Troubleshooting
  14. 검증 및 성능 분석
  15. 빌드와 소프트웨어 연동

1. 동작 시나리오

단계 입력과 처리 출력
Event 수신 원본 좌표·극성·Window 경계를 표준 Event Stream으로 변환 64×64 좌표, Positive/Negative polarity
Tensor 생성 동일 픽셀 이벤트를 포화 누적하고 Ping-Pong 버퍼로 Window를 분리 8,192-byte CHW Tensor
NPU 추론 Conv1~Conv4, Requantize, Activation, Argmax 실행 8×8 Heatmap과 최대 응답 cell
좌표 복원 Heatmap cell을 원본 64×64 좌표 중심으로 변환 target_valid, target_x/y, target_score
카메라 추적 중심 오차에 비례한 이동량을 Dead Zone과 Slew Limit로 제한 PT#1 Pan/Tilt position
레이저 정렬 카메라 위치와 잔여 좌표 오차, 보정값을 결합 PT#2 Pan/Tilt position
안전 출력 Arm, E-stop, score, 위치, freshness, lock 연속성을 검사 Servo PWM 4채널, fail-closed laser_en

Event Window 하나가 확정되면 해당 버퍼를 NPU 입력으로 전송하면서 동시에 초기화합니다. 반대쪽 버퍼는 다음 Window를 누적하므로 입력 수집과 이전 Tensor 전달을 분리할 수 있습니다.


2. 핵심 기술 요약

분류 핵심 기술
Event 전처리 원본 센서 좌표 → 64×64 spatial binning, 범위 검사, polarity 보존
Tensor 64×64×2 CHW, Positive/Negative 채널, INT8 0~127 포화 누적
Buffer 8 KiB × 2 Ping-Pong BRAM, 연속 주소 전송과 동시 clear
CNN Conv1~Conv3 3×3 stride 2, Conv4 1×1, 8×8 Heatmap
NPU 8개 PE, output-stationary, INT8 곱셈, INT32 누산
Quantization 채널별 multiplier, ties-away-from-zero rounding, INT8 clamp
Result Signed INT8 Heatmap, raster first-max Argmax, 64×64 좌표 복원
SoC Zynq PS7, M_AXI_GP0, AXI SmartConnect, 32-bit AXI4-Lite
Control P Control, Dead Zone, Slew Limit, 카메라/레이저 Dual Pan-Tilt
Safety Safe/Lock Zone, score 검사, E-stop, freshness watchdog, 수동 재무장
검증 Python Integer Golden, Verilog self-checking XSim, C host mock
구현 Vivado 2024.2 synthesis·implementation·bitstream·XSA 자동 생성

3. 프로젝트 개요

항목 내용
프로젝트명 Project06_EventCamera
대상 보드 Digilent Zybo Z7-20
SoC Zynq-7000 XC7Z020-1CLG400C
CPU Dual-core ARM Cortex-A9 Processing System
목적 Event Tensor 기반 표적 좌표 추론과 Pan/Tilt 추적 제어
NPU 입력 2×64×64 INT8 Event Tensor, 8,192 bytes
NPU 출력 1×8×8 signed INT8 Heatmap
추론 결과 target_valid, 6-bit X/Y, signed INT8 score
연산 구조 Dense INT8 CNN, 8 PE, output-stationary
기준 클럭 100 MHz
PS/PL 연결 32-bit AXI4-Lite, base 0x4000_0000, range 4 KiB
개발 도구 Vivado 2024.2, XSim, Vitis, Python 3

PL 데이터 경로는 CPU 개입 없이 Event Window부터 NPU Direct START와 추적 제어까지 연결됩니다. PS는 같은 입력 버퍼를 AXI로 적재하는 시험 경로와 하드웨어 Event 경로를 선택할 수 있으며, 결과·상태·서보 위치·안전 상태를 레지스터로 조회합니다.


4. 주요 기능

  • Spatial Binning : 센서 좌표를 나눗셈 없는 역수 곱셈 방식으로 64×64 좌표에 대응시킵니다.
  • Event Window : 내부 주기 또는 외부 Window pulse를 이벤트와 동일한 파이프라인 깊이로 정렬합니다.
  • 포화 누적 : 동일 좌표의 이벤트를 127까지 누적하고 overflow wrap을 방지합니다.
  • Ping-Pong Tensor : 다음 Window를 수집하는 동안 직전 8,192-byte Tensor를 NPU로 전달합니다.
  • Dense INT8 CNN : 4개 Convolution 계층을 8개 PE로 수행하고 Golden Model과 bit-exact 결과를 생성합니다.
  • AXI 입력 선택 : PS 입력과 Event 하드웨어 입력을 하나의 NPU input buffer 경계에서 선택합니다.
  • Direct START : Tensor 전송 완료 pulse가 NPU 추론을 직접 시작하며 PS START와의 충돌을 중재합니다.
  • 좌표 복원 : 8×8 Heatmap의 first-max cell을 64×64 공간의 cell center 좌표로 변환합니다.
  • Dual Pan-Tilt : 카메라 헤드와 레이저 헤드를 독립적으로 제어하고 위치를 AXI에서 관측합니다.
  • Fail-Closed Interlock : 안전 조건 하나라도 해제되면 레이저 출력을 즉시 차단합니다.
  • 상태 진단 : busy/done/error, event count, overrun, servo position, control state와 IRQ를 제공합니다.

5. 시스템 구성

flowchart LR
    SENSOR["Event Camera<br/>x · y · polarity · window"]
    subgraph PL["Zynq-7000 Programmable Logic"]
        ADAPTER["Event Adapter<br/>Spatial Binning"]
        ACC["Event Accumulator<br/>64×64×2 Ping-Pong"]
        MUX["Input Source MUX<br/>Event HW / PS AXI"]
        NPU["Dense INT8 NPU<br/>Conv1 → Conv4"]
        RESULT["Argmax Decoder<br/>target x · y · score"]
        TRACK["Tracking Controller<br/>PT#1 Camera"]
        AIM["Laser Head Controller<br/>PT#2 Laser"]
        SAFE["Laser Interlock<br/>Fail-Closed Safety"]
        AXI["NPU AXI4-Lite<br/>Register Bridge"]
    end
    subgraph PS["ARM Cortex-A9 Processing System"]
        APP["Bare-Metal Software<br/>Configure · Start · Monitor"]
    end
    SERVO["Servo PWM ×4"]
    LASER["Laser Enable"]

    SENSOR --> ADAPTER --> ACC --> MUX --> NPU --> RESULT
    RESULT --> TRACK --> AIM
    TRACK --> SERVO
    AIM --> SERVO
    RESULT --> SAFE
    TRACK --> SAFE
    AIM --> SAFE --> LASER
    APP <-->|"M_AXI_GP0 / AXI4-Lite"| AXI
    AXI --> MUX
    AXI <--> NPU
    AXI <--> TRACK
    AXI <--> AIM
    AXI <--> SAFE
Loading

Event 데이터와 NPU, 제어기는 FCLK_CLK0=100 MHz를 공유합니다. PS/PL AXI와 NPU 내부 클럭이 같으므로 데이터 경계에 별도 CDC가 없으며, npu_axi가 software-visible 상태를 sticky bit와 IRQ로 변환합니다.


6. 아키텍처

6-1. Zynq PS/PL SoC 구조

아래 이미지는 top_system_c를 포함한 A+C 전체 구성을 Vivado IP Integrator에서 직접 연 실제 Block Design입니다. ZYNQ7 Processing System의 M_AXI_GP0가 AXI SmartConnect를 거쳐 npu_0의 AXI4-Lite slave에 연결되고, FCLK_CLK0와 Processor System Reset이 전체 PL 데이터 경로의 100 MHz clock/reset을 공급합니다. 이미지를 클릭하면 원본 크기로 확인할 수 있습니다.

Vivado Zynq EventCamera NPU 실제 Block Design

Block Design 오른쪽의 npu_0는 Event Adapter·Tensor Accumulator·Dense INT8 NPU·Dual Pan-Tilt·Laser Interlock을 포함한 top_system_c Module Reference입니다. 외부에는 Servo PWM 4채널, Laser Enable, Status LED, Hardware Arm과 Emergency Stop이 연결됩니다.

flowchart TB
    DDR["DDR3"] <--> PS7["ZYNQ7 Processing System<br/>ARM Cortex-A9"]
    FIXED["MIO · Clock · Reset"] <--> PS7
    PS7 -->|"FCLK_CLK0 100 MHz"| RST["Processor System Reset"]
    PS7 <-->|"M_AXI_GP0"| SC["AXI SmartConnect"]
    SC <-->|"0x4000_0000 / 4 KiB"| TOP["top_system_c"]
    TOP -->|irq| PS7
    TOP --> LED["Status LED"]
    TOP --> PWM["Servo PWM ×4"]
    TOP --> LSR["Laser Enable"]
    ARM["Hardware Arm"] --> TOP
    ESTOP["Emergency Stop"] --> TOP
Loading

top_system_c 안에는 AXI bridge, NPU core, Event pipeline, Dual Pan-Tilt controller와 Laser interlock이 모두 포함됩니다. AXI 주소 공간은 하나의 4 KiB segment로 고정하고, 세부 기능은 32-bit register offset으로 구분합니다.

6-2. Event 입력과 Tensor 생성

flowchart LR
    RAW["Raw Event<br/>x[10:0] · y[10:0] · pol"]
    BIN["2-stage Binning<br/>64×64"]
    WIN["Window Boundary<br/>Event-aligned"]
    RMW["Saturating RMW<br/>Forwarding"]
    B0["Tensor Buffer 0<br/>8 KiB"]
    B1["Tensor Buffer 1<br/>8 KiB"]
    XFER["Sequential Transfer<br/>1 byte / cycle"]
    START["tensor_start<br/>1-cycle pulse"]

    RAW --> BIN --> WIN --> RMW
    RMW --> B0
    RMW --> B1
    B0 --> XFER
    B1 --> XFER
    XFER --> START
Loading

연속된 동일 주소 이벤트는 BRAM write 결과를 한 단계 forwarding해 누적 손실을 막습니다. Window 종료 시 RMW pipeline을 비운 뒤 버퍼 역할을 교대하고, 전송 대상 버퍼는 0번부터 8,191번까지 순차 출력하면서 동시에 clear합니다.

6-3. Dense INT8 NPU 데이터 경로

flowchart LR
    INPUT["Event Tensor<br/>2×64×64"]
    C1["Conv1<br/>8×32×32<br/>3×3 / S2 / P1"]
    C2["Conv2<br/>16×16×16<br/>3×3 / S2 / P1"]
    C3["Conv3<br/>32×8×8<br/>3×3 / S2 / P1"]
    C4["Conv4<br/>1×8×8<br/>1×1 / S1"]
    ARG["Signed Argmax<br/>Raster First-Max"]
    XY["Cell Center Mapping<br/>x,y = index×8+4"]

    INPUT --> C1 --> C2 --> C3 --> C4 --> ARG --> XY
Loading

각 convolution은 output-stationary 방식으로 INT32 partial sum을 유지합니다. 연산이 끝난 값은 채널별 requantization multiplier와 고정 rounding 규칙을 거쳐 다음 INT8 activation buffer로 전달됩니다. Conv4 출력은 signed Heatmap으로 유지하고 raster 순서의 첫 최대값을 선택합니다.

6-4. 추적 및 안전 제어 경로

flowchart LR
    TARGET["target_valid<br/>x · y · score"]
    PCTRL["P Control<br/>Dead Zone · Slew Limit"]
    PT1["PT#1 Camera Position"]
    RESIDUAL["Camera Pose + Residual Error<br/>Calibration Offset"]
    PT2["PT#2 Laser Position"]
    QUAL["Lock Qualification<br/>3 consecutive updates"]
    WATCH["Freshness Watchdog<br/>Max-on Timer"]
    INTERLOCK["Fail-Closed Interlock"]

    TARGET --> PCTRL --> PT1 --> RESIDUAL --> PT2
    TARGET --> QUAL
    PT1 --> QUAL
    PT2 --> QUAL
    QUAL --> WATCH --> INTERLOCK
Loading

카메라 헤드는 화면 중심 (32,32)과의 오차를 줄이는 방향으로 이동합니다. 레이저 헤드는 카메라의 현재 자세와 남은 화면 오차, 보정 offset을 결합해 별도로 정렬합니다. 레이저 출력은 추적 결과뿐 아니라 물리 Arm, E-stop, Safe Limit, aim 상태와 watchdog을 모두 통과해야 활성화됩니다.


7. Tensor와 CNN 데이터 형식

7-1. Event Tensor

항목
Shape 2×64×64
데이터 형식 signed INT8 저장, 유효 누적 범위 0~127
Channel 0 Positive event
Channel 1 Negative event
Memory order CHW
주소식 (polarity << 12) | (y << 6) | x
총 크기 8,192 bytes

원본 좌표는 floor(raw × 64 / sensor_size)와 동일한 결과를 내도록 고정소수점 역수 곱셈으로 변환합니다. 좌표 범위를 벗어난 이벤트는 설정된 OOR 정책에 따라 drop 또는 clamp됩니다.

7-2. Tiny CNN 계층

Layer Kernel / Stride / Padding 입력 출력 출력 크기
Conv1 3×3 / 2 / 1 2×64×64 8×32×32 8,192 B
Conv2 3×3 / 2 / 1 8×32×32 16×16×16 4,096 B
Conv3 3×3 / 2 / 1 16×16×16 32×8×8 2,048 B
Conv4 1×1 / 1 / 0 32×8×8 1×8×8 64 B

Weight는 OIHW 순서의 signed INT8이며 8개 bank에 output_channel % 8 기준으로 배치합니다. Bias는 사용하지 않고, Conv1~3은 requantization 이후 ReLU/INT8 clamp를 거칩니다.

7-3. Argmax와 좌표 Mapping

heatmap_addr = y_cell * 8 + x_cell
target_x     = x_cell * 8 + 4
target_y     = y_cell * 8 + 4
target_valid = target_score > SCORE_TH

동일한 최대 score가 여러 cell에 존재하면 raster scan에서 먼저 나타난 cell을 선택합니다. RTL 비교 연산은 strict >를 사용하므로 Python numpy.argmax()의 flatten first-max 규칙과 일치합니다.


8. AXI4-Lite 인터페이스

8-1. SoC 메모리 맵

주소 범위 대상
0x4000_0000 ~ 0x4000_0FFF NPU·Event·Control 통합 AXI4-Lite register

AXI 데이터 폭은 32-bit이고 register는 4-byte 정렬입니다. AW와 W 채널을 독립적으로 수신하며, response는 master가 handshake할 때까지 유지합니다.

8-2. Register Map

Offset 이름 접근 기능
0x00 CTRL RW / Pulse START, SOFT_RESET, INPUT_SRC, IRQ_EN, HW_START_EN
0x04 STATUS RO / W1C DONE sticky, BUSY, ERROR sticky, TARGET_VALID
0x08 EVENT_CFG RW Event enable, polarity와 입력 설정
0x0C INPUT_STAT RO accumulator ready, tensor ready, overrun, event/drop count
0x10 CYCLE_CNT RO 마지막 NPU 추론 cycle 수
0x14 RESULT_X RO target X coordinate
0x18 RESULT_Y RO target Y coordinate
0x1C RESULT_SCORE RW / RO signed score threshold와 결과 score
0x20 PAN_CMD RW PT#1 카메라 Pan 설정
0x24 TILT_CMD RW PT#1 카메라 Tilt 설정
0x28 LASER_CTRL RW software arm 및 레이저 제어 설정
0x2C SAFE_LIMIT RW PT#1 runtime safe limit
0x30 TRACK_ERR_X RW X축 추적 보정 설정
0x34 TRACK_ERR_Y RW Y축 추적 보정 설정
0x38 VERSION RO IP version 0x4E50_0101
0x3C INBUF_ADDR RW PS Tensor write pointer
0x40 INBUF_DATA WO 32-bit write → INT8 4-byte 순차 확장
0x44 SCRATCH RW AXI 연결 점검 register
0x48 PAN2_CMD RW PT#2 레이저 Pan 설정
0x4C TILT2_CMD RW PT#2 레이저 Tilt 설정
0x50 SAFE_LIMIT2 RW PT#2 runtime safe limit
0x54 LASER_CAL RW 레이저 헤드 calibration offset
0x58 SERVO_POS_STAT RO {tilt2, pan2, tilt1, pan1}
0x5C CONTROL_STAT RO arm, E-stop, lock, watchdog, laser 상태

8-3. 입력 소스와 START 중재

모드 INPUT_SRC HW_START_EN 추론 시작
PS Tensor 시험 0 0 PS가 INBUF_DATA 적재 후 CTRL.START
Event + PS 관리 1 0 Tensor ready 확인 후 PS가 CTRL.START
Event Direct 1 1 tensor_start가 직접 NPU START

PS START와 hardware START가 같은 cycle에 요청되더라도 한 번의 pulse만 NPU에 전달합니다. 소유권이 충돌하거나 busy/reset 중 요청이 발생하면 ERROR sticky bit로 기록하므로 frame loss를 software에서 확인할 수 있습니다.


9. 추적·서보·안전 제어

9-1. 카메라 추적

error_x = target_x - 32
error_y = target_y - 32
step    = clamp((abs(error) × P_GAIN) >> P_GAIN_SHIFT, 1, SLEW_LIMIT)

기본 Dead Zone은 중심 기준 ±4이고, 위치는 50 Hz servo frame tick에서만 변경됩니다. target_valid=0이면 현재 위치를 유지하며, 모든 position command는 설정된 최소·최대 범위로 clamp됩니다.

9-2. Servo PWM

항목 기본값
PWM frame 20 ms / 50 Hz
Position range 0~255 command
Neutral 128
Safe position 32~224
Pulse range 1,125~1,875 μs

4개 출력은 카메라 Pan/Tilt와 레이저 Pan/Tilt에 각각 대응합니다. 두 헤드는 독립 position을 갖고 동일한 PWM frame 기준으로 출력됩니다.

9-3. Fail-Closed Laser Interlock

레이저 출력은 다음 조건이 모두 참일 때만 허용됩니다.

  • Software Arm과 Hardware Arm 활성
  • Emergency Stop 해제 및 수동 재무장 완료
  • 유효한 target과 score threshold 만족
  • Target Safe Zone 및 Lock Zone 만족
  • PT#1·PT#2 위치가 각각 Safe Limit 내부
  • 레이저 헤드가 목표 위치에 도달
  • 연속 3회 lock 확인 및 target freshness 유지
  • Watchdog와 최대 연속 출력 시간 조건 만족

전원 인가, E-stop, target loss, 위치 범위 이탈 또는 freshness timeout에서는 laser_en이 0으로 유지됩니다.


10. 처리 순서와 상태 전이

10-1. Event-to-Inference 순서

sequenceDiagram
    participant CAM as Event Source
    participant EVT as Event Pipeline
    participant NPU as INT8 NPU
    participant AXI as AXI Register
    participant CTRL as Tracking / Safety

    CAM->>EVT: x, y, polarity events
    CAM->>EVT: window_end
    EVT->>EVT: pipeline drain and buffer swap
    EVT->>NPU: 8,192-byte Tensor transfer
    EVT->>NPU: tensor_start pulse
    NPU->>NPU: Conv1 → Conv2 → Conv3 → Conv4 → Argmax
    NPU->>AXI: done, cycle count, target x/y/score
    NPU->>CTRL: target_valid, target x/y/score
    CTRL->>CTRL: Pan/Tilt update and safety qualification
Loading

10-2. NPU Controller

stateDiagram-v2
    [*] --> IDLE
    IDLE --> CONV1 : start
    CONV1 --> CONV2 : layer_done
    CONV2 --> CONV3 : layer_done
    CONV3 --> CONV4 : layer_done
    CONV4 --> ARGMAX : layer_done
    ARGMAX --> DONE : scan_complete
    DONE --> IDLE : done pulse
Loading

Activation buffer는 계층마다 source/destination 역할을 교대합니다. cycle_cnt는 start부터 최종 done까지 측정하고, 결과 register와 target_valid는 다음 실행 전까지 유지됩니다.


11. 실행 구조와 소스 구성

11-1. 주요 RTL 모듈

영역 모듈 역할
NPU npu_pe INT8 multiply와 INT32 accumulate
NPU npu_requant 고정소수점 requantization과 rounding
NPU npu_conv_dense Dense convolution address·PE 제어
NPU npu_act_buf Ping-Pong activation memory
NPU npu_weight_rom 8-bank INT8 weight memory
NPU npu_controller Conv1~4 layer sequence
NPU argmax_decoder 8×8 Heatmap first-max 좌표 복원
NPU npu_core NPU top-level과 외부 input write port
Event event_adapter 좌표 binning과 Window 정렬
Event event_accumulator 포화 누적, Ping-Pong Tensor 생성
Control tracking_controller 카메라 Pan/Tilt 추적
Control laser_head_controller 레이저 Pan/Tilt 보정·정렬
Control servo_pwm 4채널 servo pulse 생성
Control laser_interlock fail-closed 안전 조건 검사
Integration npu_axi AXI4-Lite register bridge와 START 중재
Integration top_system_c Event·NPU·Control 전체 통합 Top

11-2. 저장소 구조

Project06_EventCamera/
├── README.md
├── ai/                       # Dataset, training, quantization, Integer Golden
├── constraints/              # Zybo Z7-20 XDC와 OOC timing constraint
├── docs/                     # 최종 규격, 인터페이스, 검증·운용 문서
├── handoff/                  # 통합에 사용한 최종 전달 문서
├── rtl/
│   ├── npu/                  # Dense INT8 NPU
│   ├── event/                # Event adapter와 accumulator
│   ├── control/              # Tracking, dual head, servo, interlock
│   └── integration/          # AXI bridge와 system top
├── tb/                       # Verilog self-checking testbench
├── test_vectors/             # case00/01/02 Integer Golden tensors
├── weights/                  # 최종 INT8 weight와 requant parameter
├── sw/                       # Cortex-A9 driver, self-test, host mock
├── sim/                      # XSim·Vivado build script
├── tools/                    # Weight pack, vector 생성, waveform capture
├── results/                  # Bitstream, XSA, ELF, timing·utilization report
└── NPU_Pr_vivado/            # Vivado GUI project

12. 핵심 설계 포인트

12-1. Golden Model과 RTL의 Bit-Exact 계약

Tensor 순서, padding, weight layout, signedness, rounding, clamp와 Argmax tie-break를 명시적으로 고정했습니다. 각 계층의 전체 output byte를 Python Integer Golden dump와 비교하여 최종 좌표만 같은 경우가 아니라 중간 연산까지 일치하는지 검사합니다.

12-2. 연속 이벤트의 Read-Modify-Write Forwarding

BRAM 기반 누적기는 read latency 때문에 같은 주소 이벤트가 연속으로 들어오면 갱신 전 값을 다시 읽을 수 있습니다. 직전 write 주소와 값을 forwarding해 동일 픽셀의 연속 이벤트도 한 건씩 정확하게 누적합니다.

12-3. Ping-Pong Buffer와 Window 격리

Window 종료 순간 pipeline에 남아 있는 이벤트까지 원래 버퍼 선택 정보를 함께 전달합니다. pipeline drain 이후 역할을 바꾸므로 직전 Window의 마지막 이벤트가 다음 Window로 넘어가지 않습니다.

12-4. PS 관리와 PL 실시간 경로의 공존

AXI 입력 경로는 test vector·software bring-up에 사용하고, Event Direct 경로는 Tensor 완료 즉시 추론을 시작합니다. 두 경로는 같은 input buffer와 NPU를 공유하지만 source selection과 START arbitration으로 동시에 구동되지 않습니다.

12-5. 제어 출력의 Fail-Closed 원칙

레이저 enable은 여러 안전 조건의 AND 결과로만 생성됩니다. 모호하거나 오래된 target, 범위 밖 position, E-stop, Arm 절차 위반이 발생하면 기본 출력은 OFF이며, fault 이후에는 명시적 재무장 절차를 거칩니다.


13. Troubleshooting

13-1. Golden 결과와 첫 Convolution부터 다름

  • 확인 : input_event.hex가 CHW 순서인지, weight가 OIHW인지, weights/w_bank*.mem을 다시 pack했는지 확인합니다.
  • 해결 : tools/pack_weights.py와 vector 생성 도구를 순서대로 실행한 뒤 tb_npu_conv_dense부터 비교합니다.

13-2. START 직후 DONE으로 오판함

  • 원인 : START 다음 cycle까지 BUSY가 반영되는 동안 software가 BUSY만 polling할 수 있습니다.
  • 해결 : STATUS.DONE sticky bit를 기준으로 npu_wait_done()을 사용합니다.

13-3. Event Tensor가 NPU에 기록되지 않음

  • 확인 : CTRL.INPUT_SRC, EVENT_CFG.ENABLE, accumulator ready와 npu_busy를 확인합니다.
  • 해결 : PS 입력은 INPUT_SRC=0, hardware Event 입력은 INPUT_SRC=1로 선택하고 한 번에 한 START 소유자만 활성화합니다.

13-4. Servo는 움직이지만 레이저 출력이 켜지지 않음

  • 확인 : CONTROL_STAT의 Hardware Arm, Software Arm, E-stop, aim, freshness, safe/lock 상태를 확인합니다.
  • 해결 : Arm을 LOW로 내려 재무장 latch를 해제한 뒤 안전 조건과 calibration 범위를 다시 설정합니다.

13-5. Vivado에서 Board Part를 찾지 못함

  • 확인 : Zybo Z7-20 board part digilentinc.com:zybo-z7-20:part0:1.2가 XHub board store에 설치되어 있는지 확인합니다.
  • 해결 : Vivado 2024.2의 board repository 경로를 등록한 뒤 GUI project setup script를 다시 실행합니다.

14. 검증 및 성능 분석

Vivado 2024.2 XSim self-checking simulation과 배치·배선 보고서를 함께 사용했습니다. NPU 단독 결과와 Event·Control을 포함한 전체 PL top, Zynq Block Design 결과를 구분해 기록합니다.

14-1. Self-checking RTL Simulation

자동 회귀 결과는 16 / 16 testbench PASS입니다. 동일한 test suite를 case00, case01, case02 Golden vector에 적용한 A+C 통합 회귀도 48 / 48 PASS입니다.

검증 그룹 Testbench 핵심 검증
NPU 수치 tb_npu_requant, tb_npu_pe 3,150 requant case, 300 MAC case
NPU 계층 tb_npu_conv_dense, tb_npu_full Conv1 8,192 B, Conv1~4 전체 Golden
AXI / SoC tb_npu_axi, tb_top_system 120 AXI checks, PS/PL end-to-end
Event tb_event_adapter, tb_event_accumulator, tb_event_pipeline 좌표 전수 binning, 8,192 B Tensor, Ping-Pong
Servo / Tracking tb_servo_pwm, tb_tracking_controller, tb_laser_head_controller PWM, P control, limit, calibration
Safety tb_laser_interlock, tb_dual_head_control, tb_c_event_control_top E-stop, rearm, watchdog, dual head
전체 통합 tb_top_system_c 3개 연속 frame, 37 checks, fail-closed 출력

PS driver는 동일한 AXI 동작을 복제한 host mock에서 76 / 76 checks PASS하며, input byte ordering, DONE sticky, START arbitration과 두 Pan/Tilt head register 독립성을 검사합니다.

14-1-1. 주요 시뮬레이션 파형

아래 이미지는 합성된 그림이 아니라 Vivado XSim에서 self-checking testbench를 실행한 WDB를 직접 열어 캡처한 실제 파형입니다. 이미지를 클릭하면 원본 크기로 확인할 수 있습니다.

(1) NPU Conv1~Conv4 전체 추론

NPU Conv1부터 Conv4와 Argmax까지의 XSim 실제 파형

  • busy 구간에서 controller state와 layer가 Conv1 → Conv2 → Conv3 → Conv4 순서로 전환됩니다.
  • 계층 완료마다 conv_done이 발생하고 activation buffer 선택이 교대합니다.
  • 125,845 cycles 뒤 done=1, target_valid=1이 되며 최종 결과는 X=36, Y=28, score=43입니다.

(2) Event 입력부터 NPU·제어까지 End-to-End

Event Tensor와 NPU 및 제어 통합 XSim 실제 파형

  • 3개 Event Window에서 window_end, 8,192-byte evt_we, tensor_start, npu_busy, done의 반복 순서를 확인합니다.
  • 각 frame 결과가 X=36, Y=28, score=43으로 일치하고 IRQ·상태 register까지 전달됩니다.
  • Hardware Arm이 비활성인 시험 조건에서 laser_en은 전체 구간 0을 유지해 fail-closed 동작을 검증합니다.

14-2. Timing·자원·성능 분석

14-2-1. 자원 사용률

100 MHz 제약으로 route까지 완료한 Vivado Report Utilization 결과입니다.

Vivado Implementation 실제 Utilization 화면

위 화면은 npu_bd_wrapper routed design에서 직접 연 Utilization 보고서입니다. 상단 Hierarchy 표에서 Slice LUT 2,324, Slice Register 2,188, Block RAM Tile 12, DSP 18을 확인할 수 있습니다.

구현 범위 LUT FF BRAM Tile DSP
NPU Core OOC 573 / 53,200 278 / 106,400 8 / 140 12 / 220
Event+NPU+Control Top OOC 1,975 / 53,200 1,693 / 106,400 12 / 140 18 / 220
Zynq A+C Full Block Design 2,324 / 53,200 2,188 / 106,400 12 / 140 18 / 220

전체 Block Design 기준 사용률은 LUT 4.37%, FF 2.06%, BRAM 8.57%, DSP 8.18% 입니다. NPU activation memory와 Event Ping-Pong Tensor가 BRAM을 사용하고, PE multiplier와 spatial binning 연산이 DSP에 매핑됩니다.

14-2-2. Setup / Hold Timing

Vivado Implementation 실제 Design Timing Summary 화면

위 화면은 같은 routed design의 Design Timing Summary입니다. Setup WNS +0.618 ns, Hold WHS +0.043 ns, Pulse Width WPWS +4.020 ns와 각 항목의 failing endpoint 0을 Vivado 화면에서 직접 확인할 수 있습니다.

구현 범위 Clock WNS WHS 실패 Endpoint
NPU Core OOC 100 MHz +0.752 ns +0.122 ns 0
Event+NPU+Control Top OOC 100 MHz +0.197 ns +0.106 ns 0
Zynq A+C Full Block Design 100 MHz +0.618 ns +0.043 ns 0

세 구현 범위 모두 setup·hold·pulse-width 조건을 만족합니다. 전체 Block Design의 TNS와 THS는 0.000 ns이며, 6,182개 timing endpoint에서 실패가 없습니다.

14-2-3. NPU 추론 성능

항목
기준 클럭 100 MHz / 10 ns
PE 수 8
전체 추론 125,845 cycles
추론 시간 1.258 ms
이론적 단일 추론 상한 794 inference/s
Event Tensor 전송 8,192 cycles / 81.92 μs
최종 Heatmap 8×8 signed INT8

단일 추론 상한은 NPU core의 연속 실행 지연만으로 계산한 값입니다. 실제 시스템 update rate는 Event Window, Tensor 준비, 서보 frame과 입력 source의 event rate를 함께 따릅니다.

14-3. 정적·구조 검증

확인 항목 결과
Setup failing endpoint 0
Hold failing endpoint 0
Pulse-width failing endpoint 0
Combinational latch loop 0
Tensor 주소 순서 위반 0
NPU busy 중 Event write 0
Event accumulator overrun 0
전체 통합 laser fail-closed 위반 0

RTL simulation은 protocol assertion 성격의 self-check와 전체 byte compare를 함께 사용합니다. Implementation 결과는 synthesis 추정치가 아니라 route 완료 후 생성한 timing/utilization report를 기준으로 합니다.

14-4. 생성 산출물과 재현 방법

산출물 용도
npu_soc_cfull.bit Event·NPU·Control 전체 Bitstream
npu_soc_cfull.xsa Vitis Hardware Platform
npu_test.elf PS hardware self-test
live_tracker.elf Live tracking application
bd_timing_cfull.rpt 전체 Block Design timing
bd_util_cfull.rpt 전체 Block Design utilization
portfolio_waveforms 실제 XSim waveform capture
# Verilog self-checking testbench 16종
./sim/run_sim.sh

# 대표 파형 WDB 생성 및 캡처
./sim/run_wave.sh tb_npu_full
./tools/capture_portfolio_waves.sh full topc

# NPU Core / 전체 통합 Top 배치·배선
(cd build && vivado -mode batch -source ../sim/run_impl.tcl)
(cd build && vivado -mode batch -source ../sim/run_impl_cfull.tcl)

# Zynq A+C 전체 Block Design, Bitstream, XSA
(cd build && vivado -mode batch -source ../sim/run_bd.tcl -tclargs -cfull)

15. 빌드와 소프트웨어 연동

15-1. Vivado GUI 프로젝트

저장소 루트에서 GUI project를 동기화한 뒤 엽니다.

vivado -mode batch -source sim/setup_gui_project.tcl
vivado NPU_Pr_vivado/NPU_Pr_vivado.xpr

Simulation Sources의 기본 top은 tb_npu_full입니다. 전체 통합 파형은 tb_top_system_c를 Set as Top으로 지정하고 Run Behavioral Simulation을 실행합니다.

15-2. AI / Integer Golden 재현

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt

PYTHONPATH=ai ./.venv/bin/python ai/train.py --mode self-test
PYTHONPATH=ai ./.venv/bin/python ai/test_v04_retrain_pipeline.py
PYTHONPATH=ai ./.venv/bin/python ai/test_v06_pipeline.py

최종 적용 모델은 model_v04_demo_masked_radius1_x1, 실행 profile은 DEMO_BLUE_01입니다. Weight, requantization parameter와 case00/01/02 Golden Tensor는 weights/test_vectors/에 함께 저장됩니다.

15-3. PS 소프트웨어 시험

# Host mock 기반 driver·CPU baseline·protocol test
make -C sw all

# Cortex-A9 cross build
make -C sw arm

# Vitis hardware application
vitis -s sw/build_vitis_unified.py

# Live tracking application
NPU_APP=live_tracker vitis -s sw/build_vitis_unified.py

15-4. 실행 순서

  1. results/npu_soc_cfull.bit를 Zynq PL에 program합니다.
  2. results/npu_test.elf를 실행해 VERSION, AXI scratch, input buffer, NPU 결과와 IRQ를 검사합니다.
  3. 결과가 valid=1, X=36, Y=28, score=43, cycle=125845인지 확인합니다.
  4. Live 동작에서는 동일 Bitstream에 results/live_tracker.elf를 실행합니다.
  5. Servo·레이저 구동 전에 Hardware Arm과 Emergency Stop 입력을 확인합니다.

상세 software register 사용법과 실행 절차는 sw/README.md, 전체 규격과 산출물 색인은 docs/00_DOCUMENT_INDEX.md에서 확인할 수 있습니다.


Project06_EventCamera는 Event 입력부터 INT8 CNN 추론, 좌표 복원, Dual Pan-Tilt 추적과 fail-closed 레이저 제어까지 하나의 Zynq PS/PL SoC로 통합한 FPGA 객체 추적 프로젝트입니다.

About

Zybo Z7 NPU Accelerator : Event Camera-Based Low-Latency Pan-Tilt Tracking System

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages