① PS(C코드): 멀티톤 신호 합성
↓
② PS: DDR에 입력 배열 저장
↓
③ DMA MM2S: DDR → AXI-Stream → FIR S_AXIS (입력)
↓
④ FIR IP: 필터링 + 데시메이션 (M=2)
↓
⑤ DMA S2MM: FIR M_AXIS → AXI-Stream → DDR (출력 배열 저장)
↓
⑥ PS(C코드): DDR에서 결과 읽기 → UART 출력
DMA는 채널이 2개
bd_fir_dma: custom fir ip와 PS ip, DMA ip를 붙인 block design
Block Design: bd_fir_dma
├── ZYNQ7 Processing System ← IP 1
├── AXI DMA ← IP 2
└── fir_decimator_n43_axis ← IP 3 (우리 것)
| # | IP 이름 | 출처 | 역할 |
|---|---|---|---|
| 1 | ZYNQ7 Processing System | Xilinx 기본 제공 | ARM 코어 + DDR + HP0 포트 |
| 2 | AXI Direct Memory Access | Xilinx 기본 제공 | DDR ↔ AXI-Stream 브리지 |
| 3 | fir_decimator_n43_axis | 우리가 만든 RTL | FIR 필터 + 데시메이터 |
Vivado가 "Run Connection Automation" 시 자동으로 추가하는 IP 2개:
| # | IP 이름 | 역할 |
|---|---|---|
| 4 | Processor System Reset | PS 리셋 신호 동기화 |
| 5 | AXI SmartConnect | PS GP0 → DMA AXI-Lite 연결 중계 |
GUI에서 IP들을 배치하고 연결하는 것:
fir_decimator_n43_axis) — 커스텀 IP로 패키징해서 삽입연결:
AXI DMA MM2S → (AXI-Stream) → FIR S_AXIS (입력)
AXI DMA S2MM ← (AXI-Stream) ← FIR M_AXIS (출력)
AXI DMA ↔ PS7 HP0 (DDR 직접 접근)
Block Design → Synthesize → Implement → Generate Bitstream → Export Hardware (.xsa)
진행 순서
1. 새 프로젝트 생성 (Board: Zybo Z7-20)
2. Create Block Design
3. IP 추가: ZYNQ7 Processing System
4. IP 추가: AXI DMA
5. IP 추가: 우리 FIR (커스텀 IP 패키징 먼저 필요)
6. Create HDL Wrapper
7. Generate Bitstream
8. Export Hardware
Create Project 클릭fir_decimator_trans_n43원하는 경로 설정
rtl/transposed_form/n43/fir_decimator_n43_axis.v ← 최상위 toprtl/transposed_form/decimator_m2_phase0.vrtl/transposed_form/n43/fir_decimator_n43.vrtl/transposed_form/n43/fir_n43.v

Zybo Z7-20 선택

Module Reference 방식
Vivado 좌측 Flow Navigator에서:
IP INTEGRATOR → Create Block Design 클릭bd_fir_dma
Add IP → 검색창에 zynq 입력 → ZYNQ7 Processing System 더블클릭

1. 포트 활성화
PS-PL Configuration → HP Slave AXI Interface → S AXI HP0 Interface 체크

2. 클럭 확인
Clock Configuration → PL Fabric Clocks → FCLK_CLK0 가 100MHz인지 확인

Add IP → 검색창에 axi dma 입력 → AXI Direct Memory Access 더블클릭
블록 더블클릭 이후 확인/수정할 항목 확인

상단
| 항목 | 값 | 설명 |
|---|---|---|
| Enable Scatter Gather Engine | 해제 ✓ | Simple DMA 모드. 디스크립터 체인 불필요 |
| Enable Micro DMA | 해제 | 기능 제한된 경량 DMA. 해당 없음 |
| Enable Multi Channel Support | 비활성 | 해당 없음 |
| Enable Control/Status Stream | 비활성 | 해당 없음 |
| Width of Buffer Length Register | 14 bits | 최대 전송 크기 2¹⁴ = 16KB. 4117샘플 × 2bytes ≈ 8KB이므로 충분 |
| Address Width | 32 bits | Zynq-7000은 32비트 주소 체계. 맞음 |
Read Channel (MM2S) — DDR → FIR 방향
| 항목 | 값 | 설명 |
|---|---|---|
| Number of Channels | 1 | 채널 하나면 충분 |
| Memory Map Data Width | 32 | DDR(HP0) 쪽 버스 폭. 32비트 표준 |
| Stream Data Width | 16 ✓ | FIR s_axis_tdata 폭과 일치 |
| Max Burst Size | 16 | DDR 읽기 시 한 번에 16 beat. 기본값으로 충분 |
| Allow Unaligned Transfers | 해제 | 16비트 샘플은 정렬 보장됨 |
Write Channel (S2MM) — FIR → DDR 방향
| 항목 | 값 | 설명 |
|---|---|---|
| Number of Channels | 1 | 채널 하나면 충분 |
| Memory Map Data Width | 32 (AUTO) | DDR 쪽 버스 폭. 동일 |
| Stream Data Width | 16 (MANUAL) ✓ | FIR m_axis_tdata 폭과 일치 |
| Max Burst Size | 16 | DDR 쓰기 시 한 번에 16 beat |
| Allow Unaligned Transfers | 해제 | 정렬 보장됨 |
하단
| 항목 | 값 | 설명 |
|---|---|---|
| Enable Single AXI4 Data Interface | AUTO/해제 | MM2S와 S2MM이 DDR 포트를 각각 따로 씀. 동시 읽기+쓰기 가능 |
캔버스 우클릭 → Add Module → fir_decimator_n43_axis 선택

캔버스 상단 초록색 배너 "Run Connection Automation" 클릭

모든 항목 체크 : Vivado가 SmartConnect, Processor System Reset을 자동 생성하고 연결합니다


"Run Connection Automation"으로 자동 생성된 AXI Direct Memory Access 더블클릭

포트 연결 요약:
PS GP0 → SmartConnect → DMA S_AXI_LITE (PS가 DMA 제어)
DMA M_AXI_MM2S → PS HP0 (DMA가 DDR 읽기)
DMA M_AXI_S2MM → PS HP0 (DMA가 DDR 쓰기)
DMA M_AXIS_MM2S → FIR S_AXIS (DDR → FIR)
FIR M_AXIS → DMA S_AXIS_S2MM (FIR → DDR)
첫 번째: aclk 연결
FIR 블록의 aclk 포트 → PS 블록의 FCLK_CLK0 포트로 드래그

두 번째: aresetn 연결
FIR 블록의 aresetn 포트 → rst_ps7_0_100M 블록의 peripheral_aresetn 포트로 드래그

aresetn : FIR IP의 active-low 리셋 포트
세 번째: DMA → FIR 입력 연결
axi_dma_0 블록의 M_AXIS_MM2S 포트 → FIR 블록의 s_axis 포트로 드래그

네 번째: FIR → DMA 출력 연결
FIR 블록의 m_axis 포트 → axi_dma_0 블록의 S_AXIS_S2MM 포트로 드래그

다섯 번째: Run Block Automation 클릭
상단 녹색 배너의 Run Block Automation 클릭


여섯 번째: 검증하기
단축키 F6를 눌러 Validate Design 진행

Digilent 보드 파일을 쓰는 Zybo 설계에서는 항상 뜨는 경고라고 합니다. 실제 DDR 동작에 문제 없다고 합니다.
Sources 탭에서 Block Design 파일(bd_fir_dma) 우클릭 → Create HDL Wrapper → Let Vivado manage wrapper and auto-update 선택

Synthesis → Implementation → Generate Bitstream
비트스트림 생성 실패
로그 첫 줄:synth_design -top fir_decimator_n43_axis
두 가지 문제가 동시에 존재했다.
문제 1: 합성 Top 모듈 오설정
합성 Top 모듈이 bd_fir_dma_wrapper가 아닌 fir_decimator_n43_axis로 설정되어 있었다.
이는 Block Design 생성 이전에 FIR IP 단독 검증을 위해 fir_decimator_n43_axis를 Top으로 설정해 두었던 상태가 그대로 남아 있었기 때문이다. Block Design Wrapper가 아닌 FIR 모듈 단독으로 합성을 시도하니 DMA, PS 등 나머지 연결이 전혀 없는 불완전한 설계가 합성 대상이 되었다.
→ Sources 패널에서 bd_fir_dma_wrapper를 우클릭 → Set as Top으로 변경
문제 2: 불필요한 XDC 파일 활성화
로그에서 zybo_n43.xdc가 포함되어 있었다. 이 XDC 파일은 FIR IP를 단독으로 합성할 때 사용하던 핀 제약 파일로, fir_decimator_n43_axis의 포트를 물리 핀에 직접 매핑하는 내용이 담겨
있었다. Block Design 기반 설계에서는 FIR 포트가 내부적으로 DMA에 연결되므로 물리 핀 매핑이 필요 없는데, 이 XDC가 여전히 활성화되어 있어 잘못된 핀 제약이 적용되고 있었다.
→ Sources 패널 → Constraints 폴더 → zybo_n43.xdc 우클릭 → Disable File
두 문제를 모두 수정한 뒤 다시 시도했다.
드디어 성공

IMPLEMENTATION → Open Implemented Design → Report Timing Summary

File → Export → Export Hardware → Include bitstream 체크
지정한 디렉토리에 xsa 파일을 export하는 과정입니다.
XSA (Xilinx Support Archive):
Vivado가 만드는 하드웨어 설명 패키지 파일


Block Design은 Vivado 프로젝트 파일(.xpr) 안에만 존재합니다. 프로젝트가 유실되거나 다른 환경에서 재현해야 할 때를 대비해 write_bd_tcl로 Block Design 전체를 TCL 파일로 추출해 레포에 보관합니다.
Block Design이 열린 상태에서 Vivado TCL Console에서 실행:
write_bd_tcl -force /home/young/dev/10_zynq-fir-decimation-ip/vivado/bd_fir_dma.tcl
추출 결과: /home/young/dev/10_zynq-fir-decimation-ip/vivado 디렉토리안에 bd_fir_dma.tcl 스크립트 저장
write_bd_tcl이 추출하는 정보:
processing_system7:5.5, axi_dma:7.1 등)assign_bd_address)validate_bd_design 자동 호출다른 머신에서 Block Design을 재현하려면:
source vivado/bd_fir_dma.tcl
RTL 소스 없이 sourcing하면 fir_decimator_n43_axis 모듈을 찾지 못해 실패한다.
합성 Top 오설정 + XDC 충돌 — 합성 Top이 bd_fir_dma_wrapper가 아닌 fir_decimator_n43_axis로 남아 있었고, 단독 합성용 zybo_n43.xdc가 활성화되어 잘못된 핀 제약이 적용됨 → Top 모듈 변경 및 XDC 비활성화
Validate Design 성공과 비트스트림 생성 성공은 다르다는 걸 이번 작업에서 체감했습니다. Vivado가 "연결에 문제없다"고 판정해도, 합성 Top이 잘못 설정되어 있거나 프로젝트 초기에 넣어둔 XDC 파일이 남아있으면 비트스트림 단계에서 막힙니다. 에러 메세지를 읽고 원인을 역추적하는 과정이 번거롭긴 했지만, 덕분에 Block Design의 외부 포트 개념과 Vivado 프로젝트 상태 관리 방식을 제대로 이해하게 됐습니다. 다음 단계는 생성된 .xsa를 Vitis에서 열어 DMA를 제어하는 C 코드를 작성하는 것입니다.