SEMICONDUCTOR DESIGN VERIFICATION · EMBEDDED SYSTEMS

최민영 Choi Minyoung
설계와 검증에서
온디바이스 AI로
확장하는 엔지니어

RTL 설계와 SystemVerilog/UVM 기반 검증을 중심으로, FPGA 시스템 구현과 온디바이스 AI까지 경험의 범위를 넓혀가고 있습니다.

최민영
ABOUT

소개

광운대학교 전자공학과 졸업 · 인공지능반도체연계전공 이수
연계전공 필수과목인 인공지능반도체설계프로젝트 A+

RTL 설계뿐만 아니라 설계한 하드웨어가 의도한 대로 동작하는지를 검증하는 과정에 관심이 있습니다. SystemVerilog/UVM 기반 Testbench를 구성하고, Scoreboard와 Functional Coverage를 활용해 기능을 검증하며 FPGA 보드에서 실제 동작까지 확인하는 프로젝트를 수행해왔습니다.

디지털 설계·검증 경험을 기반으로 임베디드 시스템과 온디바이스 AI까지 이해의 범위를 넓혀가며, 시스템 전체를 이해하는 Design Verification 엔지니어를 목표로 하고 있습니다.

SKILLS

기술 스택

설계 · 검증

  • Verilog / SystemVerilog
  • UVM / Functional Verification
  • Testbench / Scoreboard / Functional Coverage
  • RTL Simulation / Waveform Debugging

FPGA · Embedded Systems

  • FPGA / Basys3
  • MicroBlaze / AXI4-Lite
  • Embedded C / Bare-metal
  • ARM Cortex-M4 / STM32
  • I2C / SPI / UART / PWM

Tools · Platforms

  • Vivado / Vivado Simulator
  • Quartus Prime
  • Vitis
  • VCS / Verdi
  • Git / GitHub
  • GNU Make / GCC
  • Logic Analyzer
PROJECTS

프로젝트

프로젝트를 클릭하면 상세 내용을 볼 수 있습니다.

위 탭을 클릭하면 상세 내용이 팝업으로 열립니다.
위 탭을 클릭하면 상세 내용이 팝업으로 열립니다.
FPGA 기반 Adaptive Cruise Control(ACC) 시스템
2025.03 - 2025.06

ToF 센서(VL53L1X)로 앞차와의 거리를, 로터리 엔코더(AS5600)로 속도를 측정하고, PID 제어로 DC 모터 출력을 조절해 목표 거리(30cm ± 5cm)를 유지하는 ACC 시스템을 DE10-Standard(Cyclone V SoC) 보드로 구현한 4인 팀 프로젝트.

완성된 RC카 로터리 엔코더 포함 RC카
FPGA Verilog PID Control I2C AXI Bridge Team Project
Overview

앞차와의 거리를 자동으로 유지하며 속도를 조절하는 Adaptive Cruise Control(ACC)을, 실제 차량이 아닌 RC카 + FPGA 조합으로 구현한 4인 팀 프로젝트입니다. DE10-Standard 보드(Cyclone V SoC)의 HPS(ARM 리눅스)와 FPGA 로직을 함께 활용해, 센서 처리는 HPS가, 실시간 PWM 제어는 FPGA가 담당하는 역할 분리 구조로 설계했습니다. HPS와 FPGA라는 이질적인 두 영역을 I2C와 AXI라는 서로 다른 버스로 엮어낸 것이 이 프로젝트의 핵심입니다.

정량적 / 기능적 목표

정량적 목표

  • 선행 차량과의 목표 거리 30cm ± 허용 오차 5cm 유지
  • 센서 측정 주기 최소 50Hz 이상
  • 모터 제어 주기 10ms 단위 제어 루프 구현
  • PID 제어 응답 시간: 목표 거리 도달까지 2초 이내 안정화
  • 실내 평탄한 환경 기준 1분 이상 안정적 주행 유지

기능적 목표

  • VL53L1X ToF 센서 기반 실시간 거리 측정, AS5600 엔코더 기반 속도 측정, PID 제어로 목표 거리 유지 및 부드러운 속도 변화 구현
  • 기존 GHRD 예제에 HPS I2C2 인터페이스를 추가 구성하고, HPS-FPGA 간 Lightweight AXI Bridge를 활성화해 센서 데이터를 실시간 전달
  • FPGA 내부에 센서 처리 FSM 및 모터 제어 FSM 설계, 7-Segment로 거리 실시간 출력, LED로 에러 상태 표시
  • RC카 플랫폼에 통합 적용 후 실제 주행 환경에서 ACC 기능 및 Fail-safe 동작 검증
System Architecture

ToF 센서(VL53L1X)가 측정한 거리와 로터리 엔코더(AS5600)가 측정한 속도는 HPS의 I2C2 인터페이스를 통해 HPS로 전달되고, HPS는 이 값을 AXI(Advanced eXtensible Interface) 기반 Lightweight AXI Bridge를 통해 FPGA 내부 레지스터에 write합니다. 즉 센서 쪽은 I2C, HPS-FPGA 경계는 AXI로 나뉘는 2단 버스 구조입니다. FPGA 내부에서는 Sensor Interface FSM → PID Controller FSM → PWM Generator 순서로 데이터가 흘러가며, 최종 PWM 신호가 모터드라이버(DRV8833)를 거쳐 DC 모터 속도를 제어하는 피드백 루프를 구성합니다. 제어 주기는 10ms입니다.

기존 GHRD 예제 대비 확장한 부분

DE10-Standard(Cyclone V SoC)가 기본 제공하는 GHRD(Golden Hardware Reference Design)는 단순 입출력 테스트 수준이라 센서 제어나 실시간 제어 로직이 전혀 없었습니다. 이를 기반으로 Platform Designer에서 HPS I2C2 인터페이스를 추가 구성하고, Lightweight AXI Bridge를 활성화해 센서 데이터를 HPS→FPGA로 실시간 전달할 수 있는 경로를 새로 만들었습니다. 여기에 FPGA 내부 FSM 3종(Sensor Interface / PID Controller / PWM Generator)을 신규 설계해, 단순 데모 수준이던 GHRD를 실제 센서 기반 실시간 제어 시스템으로 확장했습니다.

트러블슈팅: 센서 통신 오류 자동 복구

개발 중 I2C로 연결된 VL53L1X 센서가 VL53L1_ERROR_CONTROL_INTERFACE, VL53L1_ERROR_TIME_OUT 같은 오류를 내며 거리값이 0으로 고정되는 문제를 겪었습니다. 브레드보드 접촉 불량이 원인 중 하나였고, 근본적으로는 소프트웨어 차원의 복구 로직이 없었던 게 문제였습니다. 이를 해결하기 위해 오류 감지 시 센서를 PlatformDeInit → 200ms 대기 → PlatformInit 순서로 재초기화하는 루틴을 넣어, 사용자 개입 없이도 약 200ms 이내에 자동 복구되도록 만들었습니다.

Sensor Auto-Recovery (C)// I2C 타임아웃/통신 오류 감지 시 자동 재초기화 if (status == VL53L1_ERROR_CONTROL_INTERFACE || status == VL53L1_ERROR_TIME_OUT) { VL53L1_PlatformDeInit(dev); usleep(200000); VL53L1_PlatformInit(dev); VL53L1_StartMeasurement(dev); continue; }
HPS ↔ FPGA 데이터 전달 (AXI)

거리값과 에러코드를 32비트 하나에 패킹해서(상위 16비트 에러코드, 하위 16비트 거리) /dev/mem 기반 mmap으로, Lightweight AXI Bridge가 매핑한 FPGA 주소 공간(0x00040000)에 직접 write하는 방식을 택했습니다. FPGA 쪽에서는 이 32비트 값을 다시 상/하위로 분리해 거리는 7-Segment에 표시하고, 에러코드는 LED 상태 표시나 에러 핸들링에 사용하도록 구성했습니다.

Sensor Data Decode (Verilog)// HPS가 AXI Bridge로 보낸 32bit 데이터에서 거리/에러코드 분리 wire [15:0] distance = sensor_data[15:0]; wire [15:0] error_code = sensor_data[31:16]; wire [3:0] d0 = distance % 10; wire [3:0] d1 = (distance / 10) % 10; wire [3:0] d2 = (distance / 100) % 10; wire [3:0] d3 = (distance / 1000) % 10; seg7_decoder u0 (.bin(d0), .seg(HEX0)); seg7_decoder u1 (.bin(d1), .seg(HEX1)); seg7_decoder u2 (.bin(d2), .seg(HEX2)); seg7_decoder u3 (.bin(d3), .seg(HEX3));
하드웨어 선정: 모터드라이버 교체

처음엔 흔히 쓰이는 L298N을 사용했지만, BJT 기반이라 전압 강하가 커서 채널당 최대 피크 전류를 안정적으로 보장하기 어려웠습니다. RC카 구동에 필요한 전류(정격 700~900mA, 급가속 시 최대 2.3A)를 계산해보니 L298N으로는 부족할 수 있다고 판단해, MOSFET 기반이라 전력 손실이 적고 채널당 2.4A까지 지원하는 DRV8833로 교체했습니다.

부팅 자동화

senser 제어 소프트웨어를 매번 수동 실행하지 않도록 systemd 서비스로 등록해, 보드 전원이 켜지면 센서 측정 프로그램이 자동으로 실행되고 곧바로 FPGA로 데이터가 흘러가도록 구성했습니다.

  • 목표: 선행 차량과의 거리 30cm ± 5cm 유지, 센서 측정 주기 50Hz 이상, 모터 제어 주기 10ms
  • HPS-FPGA 연동, 센서 자동 복구, PID 제어, 부팅 자동화까지 포함한 통합 임베디드 시스템 설계 경험
※ 팀 프로젝트로, 팀원 개인정보 보호를 위해 팀원 이름은 표기하지 않았습니다.
FPGA 기반 실시간 영상 처리 및 인터랙티브 편집 — 4컷 포토부스 시스템
2026.08.31 - 2026.09.08

FPGA(Basys-3) 한 대로 완결되는 셀프 네컷사진 부스입니다. OV7670 카메라로 촬영한 영상을 보드 내부에서 실시간으로 필터링·마커 인식·스티커/드로잉 편집까지 처리하고, 완성된 사진을 UART로 PC에 전송해 Python UI에서 QR코드로 다운로드할 수 있게 만들었습니다. 7명 팀 프로젝트이며, 저는 Edit Engine(편집 엔진)을 권동오 님과 함께 설계·구현했습니다.

SystemVerilog FPGA OV7670 VGA UART Real-time Image Processing Team Project
Overview
플랫폼Digilent Basys-3 (FPGA)
카메라OV7670 (320×240, I2C 레지스터 설정)
출력VGA Monitor (640×480), UART → PC(Python)
UART 속도1 Mbps, 8N1
편집 기능필터 4종, 스티커, Drawing/Mosaic, Color Picker
PC UIPython 기반 촬영 가이드 / 필터·프레임 선택 / QR코드 생성
System Block Diagram

버튼·스위치 입력을 동기화해 System Controller로 전달하고, System Controller가 상태에 따라 각 모듈의 동작을 제어합니다. OV7670의 픽셀 데이터는 Camera Interface로 수신된 뒤 Down Scaler와 Filter를 거쳐 Capture&Filter 블록에 저장되고, Marker 좌표를 기반으로 편집한 결과를 VGA Monitor에 실시간 출력하는 동시에 UART로 Python UI에 전송합니다.

System Block Diagram
System Block Diagram — Capture&Filter / Edit Engine / UART 3개 블록으로 구성
실제 동작 결과

카메라로 촬영 → 보드에서 실시간 필터 적용 및 편집 → 완성된 4컷 사진까지 이어지는 전체 플로우입니다. Python UI는 촬영 가이드부터 필터/스티커 선택, 최종 사진 확인, QR코드 다운로드까지의 흐름을 담당합니다.

Photo Capture to Result Flow
OV7670 카메라 → Basys-3 FPGA → 완성된 4컷 사진
Python UI Result Screens
Python PC UI — 촬영 가이드 → 필터 선택 → 촬영 → 스티커 편집 → 색상/도구 선택 → 최종 사진 + QR코드
담당 역할 (팀 프로젝트, 7인)
담당역할
최민영Edit Engine(편집 엔진) 설계 및 구현 — Memory/Memory Writer/Memory Address Generator/Marker Overlay/Image Export 통합, VGA 출력 경로와 UART 전송 경로의 픽셀 데이터 흐름 설계, Critical Path Timing Closure(파이프라인 레지스터 삽입)
공동System Controller, Camera Interface & Marker Detector, Capture & Filter, UART Interface, Python PC UI 등 나머지 모듈
※ 팀 프로젝트로, 본인 담당 외 팀원 이름은 표기하지 않았습니다.
Edit Engine — 담당 파트

Edit Engine은 VGA Controller가 생성하는 좌표(VGA Cntl)와 Capture&Filter에서 넘어온 촬영 이미지(Memory), Marker Detection이 넘겨주는 마커 좌표(Marker Overlay)를 하나로 합쳐 최종 픽셀 데이터를 만들고, 이를 Monitor와 UART(Python 전송용) 양쪽으로 동시에 출력하는 블록입니다. Down Scaler로 축소한 프리뷰 영상과 Capture로 저장된 원본 이미지를 pixel mux로 전환하고, Memory Address Generator가 계산한 주소로 Memory에서 픽셀을 읽어 Marker Overlay에서 스티커·드로잉·컬러피커 결과를 덮어씌운 뒤 MEM Writer로 다시 저장합니다.

Edit Engine Block Diagram
Edit Engine 내부 구조 — Memory / Memory Writer / Memory Address Generator / Marker Overlay / Image Export
Marker Overlay Pixel Selection Logic
Marker Overlay 픽셀 선택 로직
Memory Writer Operation Flow
Memory Writer 동작 흐름

Sticker는 Marker 좌표 근처에 저장된 스티커 이미지를 그대로 덮어쓰고, Drawing은 Marker 궤적을 따라 지정 색상을 기록하며, Color Picker는 Marker 좌표의 Memory 값을 읽어와(Memory Read) 해당 색상을 UI에 반영합니다. 이 세 경로 모두 최종적으로 Memory Write 단계로 모여 하나의 프레임 버퍼에 반영됩니다. VGA 좌표와 Marker 좌표를 비교해 겹치는 위치인지 판단한 뒤, 겹치면 Control Signal에 따라 오버레이 색상으로 덮어쓰고 겹치지 않으면 메모리 원본 값을 그대로 출력합니다.

Image Export — UART 전송 경로

System Controller의 전송 요청을 받으면 (0,0)부터 (639,479)까지 좌표를 순차 생성하며 Memory Read → UART 전달(valid/ready 핸드셰이크)을 반복하고, 전체 프레임 전송이 끝나면 System Controller에 완료 신호를 보냅니다.

Image Export Operation Flow
Image Export 동작 흐름
System Controller (7-state FSM)

OPEN(시작 대기) → SHOOT(프리뷰·필터 선택) → CAPTURE(4장 순차 촬영) → STICKER(스티커 편집) → DRAW(그리기·모자이크) → FINAL_EXPORT(이미지·UART 전송 완료 대기) → RESULT(결과 표시) 순서로 전이하며, 이미지 송신 완료 후 20초 경과 또는 외부 버튼 입력 시 자동으로 OPEN 상태로 복귀합니다. 현재 상태와 설정값을 32bit Status Data로 구성해 UART로 Python UI에 함께 전달합니다.

System Controller FSM
System Controller 7-state FSM
System Controller Top Block Diagram
System Controller Top — 버튼/스위치 동기화 + FSM + Status 생성
Status Data Bit Field
32bit Status Data 비트 필드
Camera Interface & Marker Detector

Cam_IF는 top_setup(I2C 기반 OV7670 레지스터 초기화)과 ov7670_mem_controller(픽셀 카운터 기반 좌표 생성)로 구성됩니다. Marker Detector는 색상 LUT(target_lut) 기반으로 목표 색상을 판별한 뒤, Line 단위가 아닌 Blob(덩어리) 단위 검출을 채택했습니다 — 시뮬레이션 결과 Line 방식이 첫 출력까지 32.2μs로 더 빨랐지만 valid 횟수가 10회로 출력이 불안정했던 반면, Blob 방식은 160.2μs로 약 128μs 느린 대신 valid 1회로 좌표가 안정적이어서, 사용자 체감에 미치는 영향이 적은 응답속도보다 좌표 안정성을 우선해 Blob 방식을 채택했습니다.

Cam_IF Block Diagram
Cam_IF — top_setup(I2C 레지스터 설정) + ov7670_mem_controller(픽셀 좌표 생성)
System Controller Module Signal Diagram
System Controller 모듈 간 연결 신호
Capture & Filter

Capture_Controller는 IDLE → WAIT_FRAME_START → CAPTURE → CAPTURE_DONE → CAPTURE_WAIT → ALL_DONE 상태를 거치며 프레임 시작 시점(x=0, y=0)부터 마지막 픽셀(x=159, y=119)까지 다운스케일된 이미지를 순차로 Memory에 기록하고, 4장 촬영이 끝나면(cap_count==3) ALL_DONE으로 전이합니다. Filter_top은 Grayscale/Sepia/Softfocus/Filmlook 4개 필터를 병렬로 두고 i_filter_sel로 mux 선택하는 구조이며, 필름룩 필터는 채널별 게인 조정(R×1.12, G×1.043, B×0.88)을 Q8 고정소수점(256배 정수화)으로 구현했습니다.

Capture Top Block Diagram
Capture_top — DownScaler + filter_top + Capture_Controller
Capture Controller FSM
Capture_Controller FSM
Filter Top Block Diagram
Filter_top — 4개 필터 병렬 배치 + Mux 선택 구조
Capture Timing Diagram
Capture 요청-완료 핸드셰이크 타이밍
UART Interface

Send Control이 System Controller의 32bit Status Data와 Edit Engine의 픽셀 데이터를 Byte 단위로 분할해 UART TX로 전달하고, Baud Generator가 1Mbps 기준 타이밍을 생성합니다. UART TX는 8N1 방식으로 IDLE → START → DATA(LSB부터 8bit) → STOP 순서로 직렬 전송하며, PC(Python)에서 수신 데이터를 재조립해 상태 확인 및 최종 이미지를 복원합니다.

UART Interface Block Diagram
UART Interface — Send Control + Baud Generator + UART TX
UART TX ASM Chart
UART TX ASM Chart
Send Control ASM Chart
Send Control ASM Chart — Status/Pixel 전송 모드 분기
Trouble Shooting
문제원인해결
Vivado Timing Analysis에서 Negative Slack 대량 발생 (WNS -5.156ns, TNS -2616.955ns, Failing Endpoint 648개, Timing constraints 불충족) 화면 좌표를 메모리 주소로 변환하는 곱셈 계산 경로(mem_addr_gen의 VGA 픽셀 주소 계산, mem_writer의 Sticker/Color Picker Write 주소 계산)에서 좌표 변환과 곱셈·덧셈 연산이 한 사이클에 몰려 조합 논리 경로 지연이 크게 증가 Critical Path에 파이프라인 레지스터를 2단계로 삽입 — 1단계: 다운스케일 적용된 x_pixel/y_pixel을 레지스터에 저장, 2단계: 저장된 좌표로 주소 계산(곱셈) 수행 후 결과를 다시 출력 레지스터에 저장. 주소 계산 경로를 분리해 조합 논리 지연을 줄인 결과 WNS -5.156ns → +0.463ns, TNS 0ns, Failing Endpoint 0개로 Timing Constraint를 충족
Vivado Timing Analysis Negative Slack
문제 상황 — Critical Path에서 Negative Slack 발생 (WNS -5.156ns)
Pipeline Register Timing Fix
해결 방안 — 파이프라인 레지스터 2단계 삽입 (WNS +0.463ns)
검증

Edit Engine을 대상으로 NONE passthrough, STICKER(하트 4×4 아이콘 투명/채움 경계), DRAW(3×3 박스 그리기 및 영역 밖 미변경), Color Picker(5×5 블록 코너·중심 픽셀) 4가지 시나리오를 SystemVerilog Testbench로 검증했으며, 총 16개 항목 모두 PASS(ALL TESTS PASSED)를 확인했습니다. UART 경로에서는 32bit Status Data(0x12345678 → 78→56→34→12 LSB Byte First 순서)와 RGB444 Pixel(0xABC → BC→0A) 분할 전송이 설계한 순서대로 정상 동작함을 시뮬레이션으로 확인했습니다.

Design Environment
  • FPGA Board: Digilent Basys-3
  • Camera: OV7670 (I2C 설정, 320×240)
  • Tool: Vivado / Vivado Simulator
  • Language: SystemVerilog
  • Display: VGA (640×480)
  • PC 통신: UART (1Mbps, 8N1) + Python
※ 팀 프로젝트 결과물로, GitHub 공개 저장소 링크는 별도로 두지 않았습니다.
AXI4-Lite / APB UVM VIP 설계 및 RV32I 5-Stage Pipeline CPU 검증
2026.08.17 - 2026.08.28

AXI4-Lite와 APB 프로토콜의 UVM VIP(Verification IP)를 재사용 가능한 구조로 직접 설계하고, 이를 이용해 RV32I 5단 파이프라인 CPU와 AXI-APB 프로토콜 변환 브리지까지 검증한 개인 프로젝트입니다. 팹리스 SoC 설계/검증 직무 포트폴리오로 진행했으며, VIP 설계(Phase 1) → CPU 설계·검증(Phase 2) → 프로토콜 변환 브리지 검증(Phase 3) 순서로 난이도를 확장해 나갔습니다.

SystemVerilog UVM AXI4-Lite APB RV32I Synopsys VCS/Verdi
Overview
검증 방법론UVM (Universal Verification Methodology)
시뮬레이터 / 디버거Synopsys VCS / Synopsys Verdi
언어SystemVerilog, UVM 1.1d
진행 단계Phase 1(AXI4 VIP) · Phase 2(RV32I 5-stage CPU) · Phase 3(APB VIP + AXI-APB 브리지) 전체 완료
Verification Flow
AXI4 UVM Verification Flow
AXI4 UVM Verification Flow — Sequence/Driver/Monitor/Scoreboard/Coverage 전체 구조
Phase 1 — AXI4-Lite UVM VIP

재사용 가능한 AXI4-Lite UVM VIP(interface, transaction, sequence, sequencer, driver, monitor, agent, scoreboard, coverage)를 직접 설계하고, 예제 AXI4-Lite 레지스터 슬레이브 DUT를 대상으로 write-read 데이터 무결성을 검증했습니다.

항목결과
총 트랜잭션write 13 / read 13 (랜덤 5쌍 + directed 8쌍)
ScoreboardPASS 13 / FAIL 0
Functional Coverage100%
UVM_ERROR / UVM_FATAL0 / 0

Coverage 항목: write/read 여부(cp_rw), 레지스터별 접근(cp_addr), 데이터 패턴(cp_data: zero/all_one/others), 레지스터×R/W cross coverage(cx_addr_rw).

Phase 1 구성 파일
파일설명
vip/axi4/axi4_interface.svAXI4-Lite Interface 정의
vip/axi4/axi4_transaction.svTransaction (uvm_sequence_item)
vip/axi4/axi4_sequencer.sv / axi4_sequence.svSequencer / Sequence
vip/axi4/axi4_driver.svReset 대기, AW/W 병렬 handshake, timeout 처리
vip/axi4/axi4_monitor.svAW/W 병렬 캡처
vip/axi4/axi4_agent.sv / axi4_coverage.svAgent / Functional Coverage
rtl/example_dut/axi_lite_reg_slave.sv검증 대상 예제 DUT
tb/vip_standalone_tb/axi4_scoreboard.svWrite-Read 데이터 무결성 Scoreboard
Phase 1 Trouble Shooting
문제원인해결
AXI AW/W 채널 독립 handshake 문제 — W가 AW보다 먼저 handshake되면 driver/monitor가 이를 놓치고 무한 대기 Driver/Monitor가 AW handshake를 먼저 확인한 뒤 W를 확인하는 순차 구조였는데, AXI 스펙상 AW/W는 완전히 독립된 채널 fork...join 기반으로 AW watch와 W watch를 병렬 프로세스로 분리해 각자 독립적으로 handshake를 감지하도록 수정
Reset/Timeout 처리 부재 — DUT 이상 시 시뮬레이션이 무한 대기할 수 있는 구조 리셋 해제 대기 로직과 handshake timeout이 없었음 wait (vif.rst_n === 1'b1)로 리셋 대기 추가, 각 채널 handshake에 1000사이클 timeout 카운터 추가 후 초과 시 uvm_fatal로 명확히 실패 처리
Coverage Closure — 완전 랜덤 시퀀스만으로는 Functional Coverage 62.5%에 그침 32비트 완전 랜덤 값이 정확히 0x00000000/0xFFFFFFFF로 나올 확률이 극히 낮고, 5쌍으로는 레지스터×R/W 8개 조합을 다 채우지 못함 4개 레지스터를 순회하며 데이터 zero/all_one으로 write+read하는 directed 시퀀스를 추가해 Coverage 100% 달성
Phase 2 — RV32I 5-Stage Pipeline CPU Verification

싱글사이클 RV32I CPU 설계를 기반으로 IF-ID-EX-MEM-WB 5단 파이프라인 CPU를 새로 설계하고, Forwarding/Hazard 처리와 Golden Model(싱글사이클 CPU 재사용) 기반 Scoreboard로 명령어 실행 결과를 검증했습니다.

항목결과
검증 방식Golden Model(싱글사이클 CPU) vs DUT(5-stage 파이프라인) 레지스터 write 이벤트 순서 비교
총 비교 이벤트532건
ScoreboardPASS 532 / FAIL 0
발견 후 수정한 버그2건
Phase 2 구성 파일
파일설명
rtl/cpu/if_stage.sv ~ wb_stage.svIF/ID/EX/MEM/WB 5단 파이프라인 스테이지
rtl/cpu/forwarding_unit.svEX/MEM, MEM/WB 단계 Data Forwarding
rtl/cpu/hazard_unit.svLoad-use Hazard Stall, Control Hazard Flush
rtl/cpu/register_file.sv파이프라인용 Register File (write-through bypass 포함)
rtl/cpu/golden_register_file.sv / golden_datapath.sv / golden_top.svGolden Model 전용 싱글사이클 CPU (bypass 없음)
rtl/cpu/rv32i_pipeline_top.sv파이프라인 CPU 최상위
tb/cpu_pipeline_tb/cpu_scoreboard.svGolden Model vs DUT 레지스터 write 이벤트 비교
Phase 2 Trouble Shooting
문제원인해결
Load-use Hazard Load 명령어 바로 다음 명령어가 그 결과를 쓰려는 경우, Load 데이터는 MEM 단계가 끝나야 나오는데 Forwarding은 EX 단계 시작 시점에 필요해 Forwarding만으로 해결 불가 hazard_unit이 EX 단계 명령어가 Load인지, 그 목적 레지스터가 ID 단계 명령어의 소스 레지스터와 같은지 감지해 PC/IF-ID 레지스터를 1사이클 정지시키고 ID/EX에 Bubble 삽입
Control Hazard Branch/Jump 여부가 EX 단계에서야 확정되는데, 그 사이 IF/ID 단계에 이미 Wrong-path 명령어 2개가 들어와 있음 EX 단계의 pc_sel(Branch taken 또는 Jump)이 뜨면 같은 사이클에 IF/ID, ID/EX 레지스터를 동시에 Flush해 Wrong-path 명령어 제거
[버그] Golden Model 조합논리 무한루프로 시뮬레이션 Hang — heartbeat조차 한 번도 안 찍힘 파이프라인용 Register File에 추가한 Write-through Bypass 로직을 Golden Model(싱글사이클)에도 그대로 재사용 — 파이프라인은 Read/Write 사이에 레지스터가 여러 개 껴 있어 안전하지만, 싱글사이클은 Read/Write가 같은 사이클에 조합적으로 연결돼 진짜 Combinational Loop 발생 heartbeat 신호와 단독 모듈 테스트로 원인을 좁힌 뒤, Bypass 로직이 없는 Golden Model 전용 Register File을 별도로 분리해 해결
[버그] EX/MEM 단계 Forwarding이 LUI/AUIPC/JAL/JALR 값을 잘못 전달 — 532건 중 1건 실패(LUI x15,... ; ADDI x15,x15,... 패턴에서 x15 값이 틀림) EX 단계 Forwarding 로직이 EX/MEM 단계(1칸 Forwarding)에서 무조건 mem_alu_result(ALU 결과)만 전달 — 그러나 LUI/AUIPC/JAL/JALR의 실제 Write-back 값은 ALU 결과가 아니라 각각 immediate 원본/pc+imm/pc+4 WB 단계와 동일한 5-way Mux(mem_fwd_value)를 EX 단계에도 추가해 mem_rf_src_sel에 따라 올바른 값을 선택하도록 수정
Phase 3 — APB UVM VIP + AXI-APB Bridge

AXI4-Lite VIP와 구조는 같지만 프로토콜은 더 단순한(SETUP→ACCESS 2단계, 단일 채널) APB UVM VIP를 새로 만들고, AXI4-Lite ↔ APB 프로토콜 변환 브리지를 설계해서 Phase 1의 AXI4 VIP로 브리지 너머의 APB 슬레이브까지 End-to-End로 검증했습니다.

항목결과
APB VIP 단독 검증PASS 13 / FAIL 0, Coverage 100%
AXI-APB 브리지 통합 검증 (AXI4 VIP → 브리지 → APB 슬레이브)PASS 13 / FAIL 0, Coverage 100%, UVM_ERROR/FATAL 0
Phase 3 구성 파일 & 검증 전략
파일설명
vip/apb/apb_driver.svSETUP→ACCESS, PREADY 대기, Timeout 처리
vip/apb/apb_monitor.sv / apb_agent.sv / apb_coverage.svAPB Monitor / Agent / Functional Coverage
rtl/example_dut/apb_reg_slave.svAPB VIP 단독 검증용 예제 슬레이브
rtl/bridge/axi_apb_bridge.svAXI4-Lite 슬레이브 ↔ APB 마스터 변환 FSM
tb/axi_apb_bridge_tb/axi_apb_bridge_test.svAXI4 VIP(Phase 1) → 브리지 → apb_reg_slave 통합 검증

APB VIP를 Phase 1 AXI4 VIP와 동일한 구조(Driver/Monitor/Agent/Sequence/Scoreboard/Coverage)로 구축해 예제 APB 슬레이브로 단독 검증한 뒤, AXI4-Lite ↔ APB 변환 브리지를 별도 RTL로 설계했습니다(AXI4-Lite 슬레이브 포트로 AW/W를 캡처해 APB 마스터 포트의 SETUP→ACCESS 시퀀스로 변환하는 FSM 구조). 최종적으로는 Phase 1의 AXI4 VIP·Sequence·Scoreboard를 그대로 재사용해 "AXI4 VIP → 브리지 → 실제 APB 슬레이브"까지 한 번에 검증했습니다 — 이 단계에서는 APB VIP(Driver/Monitor)를 쓰지 않고 브리지 자체가 APB 마스터 역할을 합니다.

Phase 3 Trouble Shooting
문제원인해결
VS Code `timescale 지시어와 UVM 패키지 파싱 충돌 — Error-[ITSFM] Illegal `timescale for module 발생 후 뒤이은 파일 파싱까지 연쇄적으로 깨짐 VCS가 UVM 패키지(`timescale 없음)를 먼저 파싱하는데, 그 뒤에 `timescale이 있는 UVM 클래스 파일이 나오면 timescale 사용 여부 불일치로 에러 발생 UVM 클래스를 담은 파일에서는 `timescale을 전부 제거하고, 순수 RTL 모듈에만 유지하는 것으로 통일
UVM 클래스(uvm_sequence_item 등) 인식 불가 -ntb_opts uvm 옵션은 UVM 패키지 자체를 컴파일에 포함시켜주지만, 각 소스 파일에서 실제로 쓰려면 import uvm_pkg::*;와 `include "uvm_macros.svh"를 파일마다 명시적으로 선언해야 함 UVM 클래스를 쓰는 모든 파일 맨 위에 두 줄을 명시적으로 추가
Tools
  • Synopsys VCS (시뮬레이션)
  • Synopsys Verdi (파형 디버깅)
  • UVM 1.1d
On-Device AI 기반 차량 내 잔류 탑승자 위험 감지 및 능동 안전 시스템
2026.08.05 - 2026.08.19

NVIDIA Jetson Orin Nano 위에서 Webcam 3대 입력을 실시간으로 처리해, 운전자 졸음, 차량 내 잔류 아동/반려동물, 차량 주변 비인가 접근을 하나의 On-Device AI 파이프라인으로 감지하는 3인 팀 프로젝트입니다. 모든 추론과 위험 판단을 외부 서버 없이 Jetson 내부에서 수행하고, 최종 상태와 이벤트 정보만 Web UI/Telegram으로 전달합니다. 저는 이 중 운전자 졸음 감지(System1)를 전담 설계·구현했고, 잔류 탑승자 감지(System2)의 Jetson 전력 소비 측정 및 분석을 함께 담당했습니다.

Jetson Orin Nano PyTorch TensorRT On-Device AI Multi-task Learning Grad-CAM YOLO11 Team Project
Overview
핵심 플랫폼NVIDIA Jetson Orin Nano Developer Kit (Ampere GPU, 최대 67 INT8 TOPS)
입력USB Webcam × 3 (운전자 / 뒷좌석 / 차량 주변)
OS / SDKJetPack 6.2.2 (Jetson Linux), CUDA 12.6
AI FrameworkPyTorch, TensorRT FP16, TorchScript
모델 학습 환경Google Colab (Tesla T4 GPU)
결과 전달Web UI (FastAPI / Flask), Telegram Bot Alert
서브시스템System1 졸음 감지 · System2 잔류 탑승자 감지 · Security System 보안카메라
전체 시스템 구조

3대의 Webcam(운전자·뒷좌석·차량 주변)이 Jetson Orin Nano에 각각 연결되고, Jetson 내부에서 3개 서브시스템이 각자의 AI 파이프라인으로 실시간 추론을 수행합니다. 최종 상태와 이벤트 정보만 Web UI와 Telegram Bot으로 전달되어, 영상 데이터 자체는 외부로 나가지 않습니다.

On-Device AI Vehicle Safety System Overview
3-Webcam 입력 → Jetson Orin Nano On-Device AI → Web UI / Telegram 출력 구조
서브시스템감지 대상적용 모델최종 출력
System1 (졸음 감지)눈 감김 · 하품 · 고개 자세MobileViT-XXS 기반 Multi-taskNORMAL / WARNING / DANGER
System2 (잔류 탑승자 감지)7세 이하 아동 · 반려동물 잔류Fine-tuned YOLO11n + MiVOLO V2CHILD / ADULT / ANIMAL, Stage 0~3
Security System (보안카메라)등록/미등록 사용자, 위조 얼굴YuNet + MiniFASNetV2 + SFaceOWNER / GUEST / UNKNOWN / SPOOF
담당 역할 (팀 프로젝트)
담당역할
최민영System1(졸음 감지) 개발 및 성능 분석 전담 — Eye/Yawn/Head Pose 데이터셋 구축, ResNet18·MobileNetV2·MobileViT-XXS 학습 및 성능(정확도·모델크기·Jetson Latency) 비교, Grad-CAM 기반 판단 근거 분석, System2용 YOLO11n/s/m Jetson 전력 소비(Energy/Frame) 측정 및 분석, System1 최종보고서·발표자료 작성, 최종 발표 진행
팀원System2(잔류 탑승자 감지) 개발 — YOLO11 정확도 평가, Fine-tuning, Pipeline Latency/FPS 분석
팀원Security System(보안카메라) 구현, System1 데이터셋 학습 보조
※ 팀 프로젝트로, 본인 담당 외 팀원 이름은 표기하지 않았습니다.
System1 — 운전자 졸음 모니터링 (담당 파트)

운전자의 눈 감김(Eye), 하품(Yawn), 고개 자세(Head Pose)를 하나의 Multi-task 모델로 동시에 추론하고, 단일 Frame이 아닌 시간에 따른 상태 변화를 누적해 졸음 위험도(Risk Score)를 실시간으로 판단합니다. ResNet18 / MobileNetV2 / MobileViT-XXS 3종 Backbone을 직접 학습·비교하고, Jetson Orin Nano 실측 성능과 Grad-CAM 분석까지 거쳐 최종 모델을 선정했습니다.

System1 Drowsiness Detection Flow
Webcam → Eye/Face ROI → Multi-task 추론 → Sliding Window Risk Score → NORMAL/WARNING/DANGER

Shared Backbone에서 추출한 특징을 Eye Head(2-class), Yawn Head(2-class), Pose Head(3축 회귀)로 분기하는 구조이며, Eye/Yawn/Head Pose 데이터셋마다 라벨이 달라 Batch마다 해당 Task의 Loss만 계산하되 Shared Backbone은 항상 업데이트하는 Partial-label Multi-task Learning으로 학습했습니다. 최근 3초 구간의 Eye Closed Ratio, 60초 구간의 Yawn Score, 3초 구간의 Head-down Ratio를 가중합해 Risk Score를 산출합니다.

Risk Score 계산식// Sliding Window 기반 가중합 Risk Score = 0.45 × Closed Ratio + 0.25 × Yawn Score + 0.30 × Head-down Ratio if (Risk Score < 0.40) state = NORMAL; else if (Risk Score < 0.70) state = WARNING; else state = DANGER;
3종 Backbone 정량 비교

단일 Task 기준으로는 ResNet18이 가장 높은 정확도(96.83%)를 보였지만, Multi-task 학습 결과에서는 가장 가벼운 MobileViT-XXS가 Eye Accuracy(97.31%)·Pose MAE(10.44°) 모두에서 가장 우수했습니다. Latency는 7.13ms로 세 모델 중 가장 길었지만, 30FPS 영상의 Frame당 처리 제한시간(약 33.3ms) 대비 충분히 짧아 실시간 처리에 문제가 없다고 판단했습니다.

Model Comparison Bar Chart
Accuracy vs Latency Trade-off
Accuracy vs Latency Trade-off
Model Comprehensive Efficiency Radar Chart
모델 종합 효율성 비교 (Radar Chart)
모델Eye AccuracyPose MAEParametersONNX 크기Jetson Latency
ResNet1893.09%11.94°11.18M42.65MB5.72ms
MobileNetV293.78%10.73°2.23M8.54MB5.90ms
MobileViT-XXS ✅97.31%10.44°0.95M4.08MB7.13ms
Grad-CAM 기반 판단 근거 분석

수치 비교만으로 설명하기 어려운 정확도 차이를 보완하기 위해, Eye Task의 OPEN/CLOSED 판단 근거를 Grad-CAM으로 시각화했습니다. CLOSED 샘플은 세 모델 모두 정확히 분류했으나, OPEN 샘플에서는 MobileViT-XXS가 8/10으로 가장 우수했습니다. Heatmap 비교 결과 MobileNetV2는 눈 전체와 주변까지 넓게 활성화된 반면, MobileViT-XXS는 동공·눈꺼풀 중심의 좁은 영역에 집중되어 Eye 상태 판단과 직접 관련된 특징에 더 집중하는 경향을 확인했습니다.

Grad-CAM Closed Eye Samples
CLOSED 샘플 Grad-CAM (10/10 정확)
Grad-CAM Open Eye Samples
OPEN 샘플 Grad-CAM (MobileViT-XXS 8/10)

졸음 판단의 핵심 지표인 Eye Accuracy, 가장 작은 모델 크기(Jetson에서 여러 모델을 동시 실행해야 하는 메모리 제약), Grad-CAM으로 확인한 판단 근거의 타당성을 종합해 MobileViT-XXS를 System1의 최종 모델로 선정했습니다.

System2 — 잔류 탑승자 감지 (전력 측정 담당)

System2는 YOLO11(Person/Cat/Dog 검출) + MiVOLO V2(연령 추정)의 2-Stage Pipeline으로 7세 이하 아동·반려동물 잔류를 감지하고, 잔류 지속시간에 따라 Stage 0~3 단계별로 경고합니다. 저는 이 중 YOLO11n/s/m의 Jetson 실측 전력 소비(Average Power, Energy/Frame) 측정 및 분석을 담당했습니다.

System2 Residual Occupant Detection Flow
YOLO11(Person/Cat/Dog) → Person Tracking → MiVOLO V2(연령 추정) → Stage 판단 → Alert Server

측정 초기에는 1회 단발 측정으로 인해 YOLO11s가 YOLO11m보다 전력이 높게 나오는 비정상적인 결과가 나왔는데, 모델당 30초씩 3회 반복 실행 + 실행 사이 5초 대기시간을 Shell Script로 자동화하고 평균·표준편차를 계산해 YOLO11n < YOLO11s < YOLO11m의 정상 경향을 재현성 있게 확인했습니다(다만 차이는 약 67mW로 미미). 또한 MiVOLO V2가 측정 시점에 ONNX CPU Provider로 실행되어 최종 시스템(TorchScript GPU)과 조건이 달랐던 것을 발견해 GPU 실행으로 통일 후 재측정했습니다.

Security System — 차량 보안카메라

팀원이 구현한 서브시스템으로, YuNet(얼굴 검출) → MiniFASNetV2(Anti-Spoofing) → SFace(얼굴 인식) 3-Stage Pipeline으로 OWNER/GUEST/UNKNOWN/SPOOF를 판정합니다. UNKNOWN/SPOOF를 단일 Frame에서 즉시 경고하지 않고, Capture Timer와 Presence Timer를 분리 운영해 순간적 오검출과 실제 장시간 비인가 접근을 구분하는 지속시간 기반 보안 정책이 특징입니다.

Security System Flow
YuNet → MiniFASNetV2(Anti-Spoofing) → SFace → 지속시간 기반 Security Policy
Trouble Shooting (System1)
문제원인해결
초기 전체 영상 기반 졸음 분류 시 학습-실행 환경 간 배경/조명 차이로 예측 불안정 전체 Frame을 입력하면 졸음 판단과 무관한 배경·조명 특징까지 함께 학습되어, 촬영 환경이 바뀌면 예측이 흔들림 졸음 여부를 하나의 Class로 직접 분류하지 않고 Eye/Yawn/Head Pose 3개 Task로 분리, 얼굴 검출 기반 ROI만 입력하도록 구조 변경. 각 Task 결과를 시간축으로 누적해 Risk Score를 계산하는 구조로 확장
단일 Task 평가와 Multi-task 평가에서 모델 순위가 정반대로 나타남 단일 Task에서는 ResNet18이 최고, MobileViT-XXS가 최저였으나 Multi-task 결과에서는 정반대로 MobileViT-XXS가 최고 성능 — 두 구조와 데이터 구성이 달라 직접 비교가 어려움 실제 사용하는 Multi-task 결과를 모델 선정의 우선 기준으로 설정하고, 정량 수치만으로 원인을 단정하지 않기 위해 Grad-CAM으로 각 모델의 판단 근거를 추가 검증
이론적으로 가장 경량인 MobileViT-XXS의 실제 Jetson Latency가 가장 길게 측정됨 ResNet18/MobileNetV2는 Convolution 중심 구조로 TensorRT 최적화 Kernel을 효과적으로 활용하지만, MobileViT-XXS의 Transformer/Attention 연산은 동일 수준의 최적화 효과를 얻지 못함 GFLOPs만으로 실행 속도를 판단하지 않고 실제 Jetson Latency/FPS를 최종 평가 항목에 포함, 7.13ms가 30FPS 처리 요구조건(약 33.3ms)을 충분히 만족하는지 확인 후 채택
Design Environment
  • Hardware: NVIDIA Jetson Orin Nano Developer Kit, USB Webcam × 3
  • OS / SDK: JetPack 6.2.2 (Jetson Linux), CUDA 12.6
  • Language: Python
  • AI Framework: PyTorch, timm, TensorRT FP16, TorchScript
  • Model Training: Google Colab (Tesla T4 GPU)
  • User Interface: Web UI (FastAPI / Flask), Telegram Bot Alert
ARM-Cortex_M4 기반 Bare-metal 스마트 도어락 시스템
2026.07.23 - 2026.07.27

HAL 없이 레지스터를 직접 제어하는 방식으로 4x4 키패드 인증, I2C LCD, 8x8 도트매트릭스, 서보 PWM을 통합한 상태 머신 기반 도어락 시스템.

ARM-Cortex_M4 STM32F411RE Bare-metal I2C PWM
Overview

STM32F411RE(Cortex-M4) 위에서 HAL 라이브러리를 쓰지 않고 레지스터를 직접 제어하는 방식으로 만든 도어락 시스템입니다. 4x4 키패드로 비밀번호를 입력받아 I2C LCD에 표시하고, 인증에 성공하면 서보모터로 잠금을 해제, 실패가 누적되면 일정 시간 입력을 막는 Lockout 상태로 전환됩니다. HAL 없이 직접 레지스터를 건드린 이유는 각 페리퍼럴이 실제로 어떻게 동작하는지 이해하고 싶었기 때문입니다.

인증 상태 머신

IDLE → INPUT → CHECK → UNLOCK/LOCKOUT의 4단계 상태 머신으로 인증 로직을 설계했습니다. 비밀번호가 일치하면 UNLOCK 상태로 전환되어 서보모터가 문을 열고, 불일치 시 다시 IDLE로 돌아가되 실패 횟수를 누적합니다. 3회 연속 오답 시 10초간 LOCKOUT 상태로 전환되어 입력 자체를 막는 방식으로 무차별 대입 시도를 방지했습니다.

Auth State Machine// 3회 실패 시 10초 Lockout으로 전환되는 인증 상태 머신 [IDLE] --key--> [INPUT] --'#'--> [CHECK] | match ----+---- mismatch | | [UNLOCK] fail count < 3 : back to IDLE (servo open) fail count == 3 : [LOCKOUT] (10s)
I2C 레지스터 레벨 제어

LCD 통신에 쓰인 I2C1 페리퍼럴을 HAL 없이 START/ACK/STOP 시퀀스부터 직접 구현했습니다. 레지스터를 직접 다루다 보니 타이밍 이슈나 ACK 누락 같은 문제를 초반에 자주 만났고, 이 과정에서 I2C 프로토콜의 신호 레벨 동작을 훨씬 깊이 이해하게 됐습니다.

타이머 리소스 분리

TIM2/TIM3/TIM4/TIM5 네 개의 타이머를 각각 서보 PWM 제어, LCD 화면 갱신, Lockout 카운트다운, 범용 딜레이 용도로 나눠 배치했습니다. 하나의 타이머를 여러 용도로 겸용하면 인터럽트 우선순위 충돌이나 타이밍 꼬임이 생기기 쉬워서, 기능별로 완전히 분리하는 쪽을 택했습니다.

디버깅: 하드웨어 vs 소프트웨어 이슈 구분

개발 중 배선 불량, 접촉 불량 같은 하드웨어 문제와 실제 로직 버그가 뒤섞여 원인 파악이 어려운 경우가 많았습니다. 이를 해결하기 위해 각 페리퍼럴 상태를 실시간으로 출력하는 진단용 펌웨어를 별도로 만들어, 문제가 하드웨어 쪽인지 소프트웨어 쪽인지 먼저 구분한 뒤 접근하는 방식으로 디버깅 시간을 줄였습니다.

Custom AXI I2C Master IP + MicroBlaze SoC (Reaction Test)
2026.06.22 - 2026.06.29

MicroBlaze를 AXI Master로 사용하고, 직접 설계한 Custom AXI I2C Master IP를 포함한 GPIO/Timer Peripheral을 AXI4-Lite로 통합한 SoC. LCD/FND/LED/Button 기반 반응속도 측정(Reaction Test) 앱을 HW/SW Co-Design으로 구현하고 UVM으로 검증.

SystemVerilog UVM AXI4-Lite MicroBlaze Vitis
Overview
ProcessorMicroBlaze
Bus ProtocolAXI4-Lite (32-bit, Memory-Mapped)
FPGA BoardDigilent Basys3
Custom PeripheralAXI I2C Master, AXI GPIO, AXI Timer
Application FSMIDLE → WAIT(2~5s 랜덤) → GO → RESULT
VerificationVivado Simulation, Logic Analyzer, UVM, Functional Coverage(29/29 Bin, 100%)
System Architecture

Button → Custom AXI GPIO → MicroBlaze Application → Reaction Test FSM → Timer(1ms Tick) → FND/LED → Custom AXI I2C Master → PCF8574 LCD 순서로 데이터가 흐릅니다.

System Block Diagram
System Block Diagram — MicroBlaze SoC 전체 데이터 흐름
AXI4-Lite Register Interface

유지형 Control Bit(intr_en)와 Pulse형 Command(cmd_start/stop/write/read)를 분리 설계했습니다. Command bit는 1클럭 펄스 후 하드웨어가 자동 클리어되며, done은 SR을 읽으면 자동 클리어(rc_r)되어 intr_en과 AND되어 인터럽트를 발생시킵니다.

Offset이름설명
0x00CRcmd_read/write/stop/start (Pulse, W), intr_en (R/W)
0x04DRTX/RX data (R/W)
0x08ADDRslave_addr (R/W) — LCD(0x27), Slave(0x41)
0x0CSRack_out(R), done(rc_r), busy(R) — Read Only
I2C Register Map
AXI I2C Master Register Map
Reaction Test FSM

IDLE → WAIT(랜덤 2~5s) → GO → RESULT → IDLE 상태로 구성되며, WAIT 상태에서 너무 빨리 버튼을 누르면(Too Early) 결과를 9999로 처리합니다. Timer Interrupt 기반 1ms Tick과 FND Multiplexing으로 반응시간을 논블로킹으로 측정하도록 설계했습니다.

Reaction Test FSM
Reaction Test Application FSM
검증 결과

Custom AXI GPIO IP에 대해 Write/Readback/WSTRB/Corner Pattern 등 5개 UVM 테스트를 수행해 Functional Coverage 29/29 Bin, 100%를 달성했습니다. AXI Simulation, I2C FSM 신호, Logic Analyzer 실측까지 전부 정상 확인했습니다.

UVM Coverage Result
UVM Functional Coverage 결과 (29/29 Bin, 100%)
Trouble Shooting
문제원인해결
FND와 LCD가 서로 다른 반응시간 값을 표시 FND는 GO 상태에서 10ms마다 갱신한 마지막 값을, LCD는 Button 이벤트 시점에 새로 계산한 값을 사용 — 서로 다른 시점의 값 Button Push Event 감지 순간 결과값을 한 번만 계산(Capture)해 FND/LCD/I2C Slave에 동일한 전역값을 사용하도록 수정
Custom I2C Master의 Command가 여러 번 반복 실행될 위험 AXI Register의 START/WRITE/READ가 level 신호로 유지되면 반복 실행 가능 Command를 1-clock Pulse로 변환해 한 번의 Write마다 한 번만 동작하도록 구성
Master/Slave가 SDA 라인을 동시에 구동할 위험 I2C는 여러 장치가 하나의 데이터선을 공유하는 오픈 드레인 버스 SDA를 Open-Drain(tri-state)으로 설계해 충돌 없이 공유
UVM 기반 SPI/I2C Functional Verification
2026.06.11 - 2026.06.18

SPI와 I2C Master/Slave RTL을 각각 설계하고, UVM(sequence → driver → monitor → scoreboard/coverage) 기반 검증 환경으로 기능 검증. Verdi 시뮬레이션·Functional Coverage뿐 아니라 Logic Analyzer로 FPGA 실측 파형까지 확인해 simulation과 hardware의 정합성을 검증한 개인 프로젝트.

SystemVerilog UVM SPI I2C Functional Coverage Logic Analyzer
Overview
항목내용
언어SystemVerilog, Verilog HDL
검증 방법론UVM
SimulatorVCS / Verdi
FPGA BoardDigilent Basys3 (Vivado)
측정 장비Saleae Logic Analyzer
SPI 주요 신호SCLK, MOSI, MISO, SS_N (Mode 0: CPOL=0, CPHA=0)
I2C 주요 신호SCL, SDA (Open-Drain)
최종 결과SPI/I2C Scoreboard 전부 PASS, Functional Coverage 100%
Architecture — UVM Verification Flow

sequence → agent(sequencer/driver/monitor) → scoreboard/coverage 구조이며, Interface를 경계로 위쪽은 Software(UVM), 아래쪽은 Hardware(DUT)로 분리했습니다.

UVM Block Diagram
UVM Verification Flow — sequence/agent/scoreboard/coverage와 Interface 경계
SPI / I2C Board 구조

Master 보드(button_debounce + Master Controller + Master + 7-seg)와 Slave 보드(Slave + Slave Controller + 7-seg)로 나눈 실제 FPGA 2-Board 구성입니다.

I2C Block Diagram
I2C Master/Slave Board 구조
SPI Block Diagram
SPI Master/Slave Board 구조
Protocol Timing — I2C

START/STOP 조건과 ACK/NACK 응답이 I2C 프로토콜의 핵심입니다. 실제 파형으로 두 상황을 비교 분석했습니다.

I2C Start Stop
I2C START/STOP 조건 파형
I2C ACK vs NACK
ACK vs NACK 응답 비교
Scoreboard: 시나리오별 자동 판정

단순 데이터 비교가 아니라 I2C 프로토콜 규칙 자체를 판정 로직에 반영했습니다. 트랜잭션 완료 여부(타임아웃), NACK 테스트인지 ACK 테스트인지, 그리고 실제 데이터 일치 여부를 순서대로 검사해서 각각 다른 사유로 PASS/FAIL을 기록합니다. 의도적으로 잘못된 주소를 보내 NACK을 유도하는 테스트에서는 NACK이 오는 것이 오히려 정상 동작이므로, sequence item에 expect_nack 필드를 추가하고 uvm_config_db로 scoreboard까지 전달해 정상/의도된 NACK 시나리오를 모두 정확히 판정하도록 만들었습니다.

i2c_scoreboard.sv — write()// NACK 테스트인지 여부에 따라 판정 기준이 달라짐 if (exp_nack) begin if (!tr.ack_ok) pass_count++; // 의도된 NACK 확인 → PASS else fail_count++; // NACK이어야 하는데 ACK → FAIL end else if (!tr.ack_ok) begin fail_count++; // 정상 통신인데 NACK → FAIL end else if (tr.rx_data === tr.tx_data) begin pass_count++; // 데이터 일치 → PASS end else begin fail_count++; // 데이터 불일치 → FAIL end
검증 결과 — Waveform & Coverage
I2C UVM Waveform
I2C Master/Slave 상태 정렬 Waveform
I2C UVM Coverage
Functional Coverage 100% 달성
I2C NACK Cross Coverage
NACK 시나리오까지 반영된 Cross Coverage — data × ack_fail/ack_ok 전 조합 hit
Trouble Shooting
문제원인해결
I2C transaction이 계속 NACK 응답, ADDR_ACK에서 멈춤 Master Controller의 SLAVE_ADDR와 Slave의 my_addr 파라미터 불일치 인스턴스화 시 두 파라미터를 일치하도록 수정
expect_nack 플래그가 scoreboard에 전달되지 않아 NACK 테스트가 FAIL로 오판정 UVM monitor는 관찰 결과로 새 transaction item을 생성하므로 sequence item 값이 monitor item으로 자동 전달되지 않음 uvm_config_db로 expect_nack 값을 scoreboard까지 전달, 이 값 기준으로 판정 분기
I2C 0xFF 데이터가 coverage에 반영되지 않아 100% 미달성 마지막 transaction이 monitor/coverage collector에 전달되기 전에 simulation 종료 sequence 종료 후 delay를 추가해 마지막 transaction 전달 시간 확보
SPI monitor의 tx_data 캡처 타이밍 오류로 scoreboard mismatch Loopback 구조에서 현재 rx_data는 이전 transaction의 tx_data와 대응되는데, monitor가 같은 transaction으로 묶음 monitor capture timing 조정 + scoreboard가 prev_tx를 expected value로 사용하도록 수정
RV32I Single Cycle CPU (SystemVerilog)
2026.05.19 - 2026.05.27

RV32I 명령어 서브셋을 지원하는 Single Cycle CPU를 SystemVerilog로 설계하고, R/I/IL/S/B/U/J 각 명령어 타입별 datapath·control path를 시뮬레이션으로 검증. C 코드 기반 누적합(sum)·버블 정렬 프로그램 실행까지 검증.

SystemVerilog CPU Design RISC-V
Overview
CPU 구조RV32I Single Cycle CPU
Register File32 registers, x0 write protection 적용
지원 명령어 타입R, I, IL(Load), S, B, U, J
ALU 기능ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, branch compare
Load / StoreLB/LH/LW/LBU/LHU, SB/SH/SW
Branch / JumpBEQ/BNE/BLT/BGE/BLTU/BGEU, JAL/JALR, LUI/AUIPC
Base Architecture

Program Counter → Instruction Memory → Control Unit(opcode/funct3/funct7 decode) → Register File(rs1/rs2 read) → Immediate Generator → ALU → Data Memory → Write-back MUX → Register File(write-back) 순서로 데이터가 흐르며, branch/jump 여부에 따라 next PC가 결정됩니다.

RV32I Single Cycle Architecture
RV32I Single Cycle CPU 전체 구조
명령어 타입별 Datapath

R-type은 rf_we=1, alusrc_sel=0으로 rs1/rs2가 ALU를 거쳐 곧바로 write-back되고, I/IL-type은 alusrc_sel=1로 immediate를 ALU 입력으로 사용합니다. 같은 immediate 기반 연산이라도 I-type은 ALU 결과를, IL-type(Load)은 Data Memory 출력을 write-back한다는 점이 구분 포인트였습니다. B-type은 Register File write 없이 branch 조건만으로 PC를 갱신하고, JAL/JALR은 PC+4를 link register(rd)에 저장합니다.

R-type Data Flow
R-type 명령어 Datapath 예시 — rs1/rs2 → ALU → rd write-back
검증: 명령어 타입별 + C 프로그램 레벨

R-type부터 J-type까지 7개 타입 모두 opcode decode → control signal → datapath 연산 → write-back까지 단계별로 검증했습니다. 여기서 그치지 않고, 누적합(loop, function call, stack frame 포함)과 버블 정렬(배열 접근, swap, branch) C 프로그램을 instruction memory에 올려 실제 프로그램 흐름 레벨까지 검증했습니다.

  • R/I/IL/S/B/U/J 7개 타입 전부 예상값과 일치 확인
  • C 누적합 프로그램: 1~10 합산 loop + function call → data_ram[58]=55 확인
  • C 버블 정렬 프로그램: 배열 정렬 후 1,3,5,7,9 순서 확인
Trouble Shooting
문제원인해결
x0 레지스터 값이 0으로 유지되지 않고 변경됨 write-back 조건이 waddr에 상관없이 write를 수행 — 특히 JAL/JALR에서 rd=x0로 지정된 경우 PC+4가 x0에 write-back됨 write-back 조건에 waddr != 5'd0을 추가해 x0에 대한 write를 항상 차단
I-type과 IL-type의 write-back 결과가 섞일 위험 둘 다 immediate 기반 ALU 연산을 하지만 최종 저장값의 출처가 다름(ALU result vs Load data) rf_src_sel을 I-type=ALU result, IL-type=Data Memory output으로 분리
ADD/SUB, SRL/SRA처럼 funct3가 동일한 명령어 구분 funct3만으로는 두 연산을 구분할 수 없음 funct7[5] 비트를 함께 확인하는 ALU control mapping 적용
UART + FIFO + ASCII Decoder Verification
2026.05.12 - 2026.05.15

UART RX/TX, FIFO, ASCII Decoder를 하나의 DUT로 통합하고, SystemVerilog 기반 class-based testbench(Generator → Driver → Monitor → Scoreboard)로 End-to-End 기능 검증을 수행한 개인 프로젝트입니다. Directed test와 Constraint Random test를 함께 적용해 각 블록 단위 검증과 통합 경로 검증을 모두 수행했습니다.

SystemVerilog Testbench Functional Verification Constraint Random
Overview
UART9600bps, 16x Oversampling, 1 Start + 8 Data + 1 Stop bit, LSB First
FIFO8-bit 폭, 16-depth, Register File 기반 Circular Buffer
ASCII Decoder입력 R/L/U/D/M/S → one-hot 출력
Testbench 구조Class-based (Transaction/Generator/Driver/Monitor/Scoreboard), Interface + Virtual Interface
반복 검증UART Random Test 200회, FIFO Random Test 100회
Features
  • Class 기반 Testbench: Transaction class로 자극(stimulus)을 정의하고 Generator/Driver/Monitor/Scoreboard를 독립 class로 분리해 재사용성 확보
  • Directed + Constraint Random 혼합 검증: 기본 동작은 Directed test로, 경계·조합 케이스는 Constraint Random으로 커버
  • UART End-to-End 경로 검증: TX → RX loopback 및 RX → FIFO → ASCII Decoder까지 이어지는 전체 데이터 흐름을 하나의 Scoreboard로 판정
  • FIFO 동시 Push/Pop 검증: 실제 DUT의 조합/순차 로직 특성을 반영한 reference model로 정확한 비교 수행
  • fork~join 기반 병렬 검증: Driver/Monitor를 병렬 thread로 구동해 실시간 검증 환경 구성
Architecture

UART RX → FIFO → ASCII Decoder 전체 경로를 하나의 top 모듈로 통합했습니다. Generator가 transaction을 생성하면 Driver가 interface를 통해 DUT에 입력하고, Monitor가 출력을 관찰해 Scoreboard로 전달, Scoreboard가 내부 reference queue와 비교해 PASS/FAIL을 판정하는 구조입니다.

Top UART FIFO Decoder
UART + FIFO + Decoder 통합 구조
UART Verification Environment
UART 검증 환경
FIFO Verification Environment
FIFO 검증 환경
구성 파일
파일설명
uart_top.vUART RX/TX + FIFO + ASCII Decoder 통합 DUT
uart_if.svDUT ↔ Testbench 연결 Interface
uart_transaction.svUART 자극(stimulus) 데이터 정의 (Transaction class)
uart_generator.svDirected/Random transaction 생성
uart_driver.svTransaction → interface 신호로 변환해 DUT에 인가
uart_monitor.svDUT 출력 관찰 및 transaction 재구성
uart_scoreboard.svReference queue 기반 PASS/FAIL 판정
uart_env.svGenerator/Driver/Monitor/Scoreboard 연결 환경
uart_test.sv시나리오별 테스트 (Reset/Directed/Random)
검증 시나리오
모듈시나리오결과
UARTReset 상태 확인✅ PASS
TX only (Directed)✅ PASS
RX only (Directed)✅ PASS
Random TX (Constraint Random 200회)✅ PASS
FIFOReset 상태 확인✅ PASS
Push only / Pop only (Directed)✅ PASS
Push/Pop 동시 동작 (Constraint Random 100회)✅ PASS
통합UART RX → FIFO → ASCII Decoder End-to-End✅ PASS
Trouble Shooting
문제원인해결
FIFO Random test에서 push+pop 동시 발생 시 fail 다수 Scoreboard 모델은 push→pop 순서로 비교했지만, 실제 DUT는 pop_data가 조합 논리(현재 rptr 기준)이고 write는 posedge에서 반영되어 pop→push 순서로 동작 Scoreboard의 처리 순서를 DUT와 동일하게 pop 먼저 → push 나중으로 수정
fork ~ join_any + disable fork 종료 구조에 대한 피드백 병렬 thread 중 하나만 끝나도 다음 코드로 진행되어, Scoreboard 비교가 끝나기 전에 강제 종료될 가능성 transaction count 기반으로 모든 비교 완료 후 종료하는 구조로 개선 필요성 정리
담당

Testbench 아키텍처 설계(Generator/Driver/Monitor/Scoreboard), Interface 정의, Directed/Constraint Random 시나리오 작성, 통합 경로 Scoreboard 판정 로직 구현까지 전 과정을 직접 담당했습니다.

UART + FIFO + SENSOR + Stopwatch/Watch
2026.05.01 - 2026.05.06

FPGA(Basys-3) 기반 UART 통신 + FIFO 버퍼링 + SR04/DHT11 센서 + Stopwatch/Watch를 하나의 시스템으로 통합한 프로젝트입니다. 물리 버튼과 UART 명령을 공통 제어 경로로 통합하고, 시간 데이터·센서 데이터를 FND와 UART 양쪽에 동시에 출력하도록 설계했습니다. 4인 팀 프로젝트.

Verilog FIFO Sensor Interface Team Project
Overview
동작 클럭100MHz (System Clock)
UART 통신 속도9600 bps (16x Oversampling)
UART 프레임1 Start bit + 8 Data bit + 1 Stop bit
FIFORX FIFO(수신 버퍼) / TX FIFO(송신 버퍼), Circular Buffer 구조
시간 해상도msec(0-99) · sec(0-59) · min(0-59) · hour(0-23)
SR04Trig/Echo 기반 거리 측정, 3-digit 출력
DHT11단일 데이터라인, 40bit 수신 + checksum 검증, 4-digit 출력
입력버튼(btnR/L/U/D), Switch, UART 명령(R/L/U/D/M/S)
출력4-digit FND(Main/Sensor 공용), LED, UART ASCII 상태 출력
Features
  • UART 명령 제어: R/L/U/D/M/S 문자 명령을 ASCII Decoder가 버튼 입력과 동일한 제어 신호로 변환 → 보드 버튼 없이도 원격 제어 가능
  • UART 상태 송신: 현재 모드(Watch/Stopwatch/SR04/DHT11)의 데이터를 ASCII Sender가 문자열로 변환해 UART TX로 송신, PC에서 실시간 확인 가능
  • FIFO 버퍼링: RX/TX 각각 독립 FIFO(Circular Buffer)로 송수신 타이밍 차이에 의한 데이터 손실 방지
  • Stopwatch/Watch: RUN/STOP/CLEAR/Up-Down Count + 시각 자동 증가 및 시/분/초 설정
  • SR04 초음파 센서: Trig pulse 생성 → Echo pulse width 측정(1us tick) → 거리 환산(distance = width/58)
  • DHT11 온습도 센서: tri-state(inout) 제어 + synchronizer로 안정화, 40bit 프레임 수신 후 checksum 검증
  • 공용 FND 출력: 시간 데이터(Main FND)와 센서 데이터(Sensor FND)를 스위치 선택에 따라 하나의 FND 자원에서 Multiplexing 출력
  • Button Debounce: Shift Register + Edge Detection으로 채터링 제거, UART 입력과 동일한 제어 경로 공유
Architecture

top_uart가 UART 명령을 해석해 내부 제어 신호를 만들고 상태를 ASCII로 되돌려보내는 역할을, top_fnd가 Stopwatch/Watch·SR04·DHT11·FND 출력 등 실제 데이터 생성을 담당합니다. Control Unit FSM이 버튼과 UART 입력을 공통 경로로 받아 스위치 조합(sw[3]/sw[1])에 따라 Watch/Stopwatch/SR04/DHT11 모드를 선택해 각 블록에 제어 신호를 분배하고, FND 출력 선택 로직이 sw[3] 기준으로 Main FND(시간)와 Sensor FND(센서) 중 하나만 최종 출력 포트로 전달합니다.

UART FIFO Sensor Architecture
UART + FIFO + SENSOR + Stopwatch/Watch 시스템 구조
구성 파일
파일설명
top_final.v최상위 통합 모듈 (top_uart + top_fnd)
top_uart.vUART 명령 해석 + 상태 ASCII 송신 상위 블록
top_fnd.vStopwatch/Watch + Sensor + FND 출력 상위 블록
uart.vUART Rx/Tx + Baud Tick Generator
fifo.vRX/TX FIFO (Circular Buffer)
ascii_decoder.vUART ASCII 명령 → 내부 제어 신호 변환
ascii_sender.v내부 상태 데이터 → ASCII 문자열 변환 및 송신
control_unit_fsm.v전체 모드 선택 및 제어 신호 생성 (중앙 제어 FSM)
sr04_controller.vSR04 초음파 센서 제어 (Trig/Echo, 거리 계산)
dht11_controller.vDHT11 온습도 센서 제어 (40bit 수신, checksum)
sensor_fnd.vSR04/DHT11 데이터 공용 FND 출력 (Mux + Leading zero 제거)
button_debounce.v버튼 Debounce + Edge Detection
검증 결과
항목목표결과
DHT11 Controller40bit 수신 후 humidity/temperature/checksum 정상 산출✅ 달성 (humidity=60, temperature=25, valid=1)
SR04 ControllerTrig 출력, Echo pulse width 기반 거리 계산✅ 달성 (echo 1160us → distance=20)
top_fnd 모드 선택sw 조합에 따라 Watch/Stopwatch/SR04/DHT11 FND 출력 선택✅ 달성
Watch 설정 모드 전이WATCH→HOUR→MIN→SEC 및 역방향 전이, blink 표시✅ 달성
UART RX 명령 해석R/L/U/D/M/S 문자 → 대응 제어 신호 생성✅ 달성
UART TX 상태 송신select에 따라 watch/stopwatch/SR04/DHT11 데이터를 ASCII로 송신✅ 달성

FPGA(Basys-3) + ComPortMaster 환경에서도 DHT11(temp/humidity:24/51 등)과 SR04(DISTANCE:167 등) 데이터가 FND·UART 양쪽에 정상 반영됨을 확인했습니다.

Trouble Shooting
문제원인해결
SR04 실보드에서 거리값이 갱신되지 않음 사용 중이던 초음파 센서 자체의 하드웨어 불량 RTL/FSM은 정상 확인, 센서 모듈 교체로 해결 — simulation만으로는 판단 불가함을 확인
ASCII Decoder 출력이 한 사이클 늦게 나옴 FSM(순차 논리)으로 설계되어 즉시성이 떨어짐 조합 논리 디코더로 변경하여 입력 즉시 one-hot 출력되도록 수정
FIFO_TX에서 empty 상태 pop 오동작, 포인터 미복구 데이터 폭([31:0])과 FIFO 접근 범위([20:0])가 불일치 전송 완료 후 포인터 reset 조건 추가, 데이터 폭과 접근 범위 일치시킴
ASCII_SENDER에서 multiple driven net 발생 문자열 생성과 송신 제어가 한 블록에 혼재 문자열 생성부와 송신 제어부를 분리, 준비-송신 타이밍을 단계적으로 구분
DHT11 FPGA-센서 간 출력 충돌 가능성 단일 데이터선(inout)에서 FPGA와 센서가 동시에 구동 tri-state 구조로 출력 구간 분리
DHT11 응답 신호 비동기 입력 metastability 우려 system clock과 비동기 관계 2-stage synchronizer 추가로 FSM에는 동기화된 신호만 전달
Stopwatch/Watch + Sensor 통합 시 FSM 상태 전이 복잡도 증가 기존 FSM이 Stopwatch/Watch 중심 구조 SR04/DHT11 상태를 추가하고 sw 조합 기준으로 상태 전이를 재정리
담당 역할 (팀 프로젝트)
담당역할
최민영DHT11 Sensor 설계, Watch/Stopwatch 설계, FND Controller 설계
공동Testbench 및 Simulation, 시스템 통합 및 디버깅
※ 팀 프로젝트로, 본인 담당 외 팀원 이름은 표기하지 않았습니다.
UART Loopback (FPGA, Verilog)
2026.04.22 - 2026.04.27

FPGA(Basys-3) 상에서 UART(Universal Asynchronous Receiver/Transmitter) 송수신 구조를 구현하고, Loopback(수신 데이터를 그대로 재전송) 방식을 통해 송수신 기능의 정확성을 검증한 프로젝트입니다. Tx/Rx를 FSM 기반으로 분리 설계하고, 16배 Oversampling으로 수신 안정성을 확보했습니다.

Verilog UART FPGA Basys-3
Overview
동작 주파수100MHz (System Clock)
Baud Rate9600 bps
Oversampling16x (b_tick 기준)
데이터 프레임1 Start bit + 8 Data bits + 1 Stop bit
전송 방식Serial, LSB-first
FPGA / ToolBasys-3 / Vivado, Vivado Simulator, ComPortMaster
Features
  • UART Transmitter / Receiver: FSM 기반(IDLE → START → DATA → STOP) 상태 제어로 송수신 동작 정의
  • Baud Tick Generator: 100MHz 시스템 클럭을 분주해 9600bps 기준 Tick(b_tick) 생성, Tx/Rx가 공통으로 사용
  • 16x Oversampling: 비트 중앙(mid-point)에서 샘플링하여 노이즈·타이밍 오차에 대한 수신 안정성 확보
  • Loopback 구조: rx_done을 tx_start에 직접 연결해 수신 완료 즉시 동일 데이터를 자동 재전송
  • Shift Register 기반 직렬-병렬 변환: LSB-first 방식으로 데이터 조립/분해
Architecture

UART Receiver(Rx)는 rx 신호의 High→Low 전이로 Start bit를 감지한 뒤 b_tick 기반 카운터로 mid-point에서 샘플링하고, 8bit 수신이 완료되면 rx_done(1-cycle pulse)을 발생시킵니다. UART Transmitter(Tx)는 tx_start 신호로 동작을 시작해 Start bit(0) → 8bit 데이터(LSB-first, shift register) → Stop bit(1) 순서로 출력하며, 전송 중에는 tx_busy가 High를 유지합니다. Baud Tick Generator는 시스템 클럭을 분주하여 Tx/Rx가 공유하는 공통 타이밍 기준(9600bps × 16)을 생성하고, Loopback 구조는 rx_done → tx_start를 직접 연결해 별도 제어 로직 없이 수신 즉시 재전송되도록 합니다.

UART Loopback Architecture
UART Tx/Rx + Loopback 구조
구성 파일
파일설명
uart.vUART Top module — uart_tx, uart_rx, baud_tick_gen 통합
uart_loopback.vLoopback 구조 최상위 모듈 (rx_done → tx_start 연결)
검증 결과
항목목표결과
UART Loopback 동작입력 데이터(8'h30)와 동일한 값이 출력됨✅ 달성
Tx FSM 상태 전이IDLE → START → DATA → STOP → IDLE 순서 전이✅ 달성
Tx 데이터 전송 순서LSB-first(bit0→bit7) 방식으로 출력✅ 달성
tx_busy 신호START~STOP 구간 동안 High 유지, 종료 후 Low✅ 달성
Rx FSM 상태 전이IDLE → START → DATA → STOP → IDLE 순서 전이✅ 달성
Rx 데이터 샘플링b_tick 기준 각 bit 구간에서 안정적 샘플링✅ 달성
rx_done 신호수신 완료 시 1-cycle pulse 발생✅ 달성

FPGA(Basys-3) + PC 시리얼 통신(ComPortMaster) 환경에서도 PC에서 입력한 문자열이 동일하게 되돌아오는 것을 확인했으며, 반복 실험에서도 데이터 손실·순서 오류 없이 안정적으로 동작함을 검증했습니다.

Trouble Shooting
문제원인해결
DATA bit 전송 순서가 직관적으로 이해 안 됨 LSB-first 전송 방식 data_reg를 right shift하는 구조로 이해/구현
bit 전송 타이밍이 일정하지 않음 타이밍 기준 미정립 b_tick 기준 16 tick마다 1bit 전송하는 카운터 구조 추가
Start bit 검출 후 샘플링 시점 불명확 노이즈·전이 구간 영향 16x oversampling 중 8번째 tick(mid-point)에서 샘플링
rx_done → tx_start 직접 연결 시 Tx 동작 불안정 rx_done이 1-cycle pulse인지 불명확 Tx FSM이 IDLE 상태에서만 tx_start를 인식하도록 제한
STOP 상태에서도 tx_busy가 계속 유지됨(오동작으로 오인) STOP 상태가 실제 Stop bit를 출력 중인 구간이라 정상 동작 파형 분석으로 정상 동작임을 확인, tx_busy는 전송 완료 시점과 정확히 일치
담당

UART Tx/Rx FSM 설계, Testbench 작성 및 시뮬레이션 검증, Loopback 구조 System Integration, FPGA Bitstream 생성 및 보드 동작 확인까지 전 과정을 직접 담당했습니다.

Stopwatch & Watch (FPGA, Verilog)
2026.04.16 - 2026.04.20

FPGA(Basys-3)에서 Stopwatch와 Digital Watch를 하나의 시스템으로 통합 구현. Control Unit(FSM)과 Datapath를 분리한 모듈화 구조, Debounce + Edge Detection 기반 버튼 입력 처리, 계층적 Tick 카운터 구조 적용.

Verilog FPGA / Basys-3 FSM
Architecture

Control Unit(FSM)이 상태 전이와 제어 신호 생성을 담당하고(Stopwatch: STOP→RUN→STOP / STOP→CLEAR / STOP→MODE→STOP, Watch: WATCH→HOUR_SET→MIN_SET→WATCH), Datapath가 그 신호를 받아 실제 시간 데이터를 연산합니다. msec→sec→min→hour로 overflow/underflow(carry/borrow)가 전파되는 계층적 Tick 카운터 구조를 적용했습니다.

Stopwatch Watch Architecture
Stopwatch & Watch 아키텍처
담당 부분

2인 팀 프로젝트였고, 저는 Testbench 작성 및 시뮬레이션 검증, 모듈 통합(System Integration), FPGA Implementation을 담당했습니다.

Trouble Shooting
문제원인해결
버튼 하나 입력이 여러 번 인식됨 기계식 버튼의 Bouncing 현상 Debounce + Rising Edge Detection으로 1-cycle pulse 생성
minute↔hour 연동이 안 됨 carry/borrow 신호가 상위 카운터로 제대로 전달되지 않음 overflow/underflow 시 tick 전달 경로 수정
설정 모드에서 값이 여러 단계 튐 버튼을 level 신호로 처리해 눌려있는 동안 계속 반영됨 edge 기반(pulse) 입력으로 변경
※ 팀 프로젝트로, 본인 담당 외 팀원 이름은 표기하지 않았습니다.
CONTACT

연락처

최민영
Choi Minyoung
Design Verification · Embedded · On-Device AI

생년월일2003.03.20
학교 / 전공광운대학교 전자공학과
(인공지능반도체연계전공)
재학 기간2022.03 - 2026.02
choi_minyoung_scoreboard.sv
class choi_minyoung extends uvm_scoreboard; `uvm_component_utils(choi_minyoung) int pass_count = 0; string role = "Design Verification / Embedded / On-Device AI"; string strength[] = '{ "RTL Design", "UVM Verification", "Embedded Systems", "On-Device AI" }; string github = "github.com/minbeddedsystem"; // Scoreboard : expected와 actual을 비교하여 결과 판정 function void write(challenge_item tr); if (tr.expected == tr.actual) begin pass_count++; `uvm_info( "SCB", $sformatf("PASS : %s", tr.name), UVM_LOW ) end else begin `uvm_error( "SCB", $sformatf("Mismatch detected : %s", tr.name) ) debug(); verify(); end endfunction function void report_phase(uvm_phase phase); `uvm_info( "SCB", $sformatf("PASS : %0d challenges verified.", pass_count), UVM_LOW ) `uvm_info( "MINYOUNG", "Design. Verify. Implement.", UVM_LOW ) endfunction endclass : choi_minyoung