이번에 Zynq 시리즈 FPGA를 이용하면서 알게 된 것들을 정리해보았다. 이쪽 세계는 알아야 하는 게 많지만 그것보다는 컴파일 시간이 너무 오래 걸려서 개발 시간을 다 잡아먹는다… 머리가 좋거나 설계를 처음부터 잘해서 디버깅 할 일을 최대한 줄여야….하는데……… ‘-`)
1. PL에 클럭 물리기
이전에 사용하던 FPGA는 Artix-7 35T가 들어간 CMOD A7이었는데, 얘는 특정 하드웨어 핀에서 클럭을 보내기 때문에 constraint를 통해 내 모듈의 클럭 포트와 대응을 시켜주면 잘 이용할 수 있었다.
그런데 Zynq 시리즈의 FPGA는 PL단에서 클럭을 보내는 하드웨어 핀이 없는 것 같다. 그래서 PS의 클럭을 땡겨와야하는데, 이를 위해 Block Design에서 ZYNQ7 Processing System(PS)을 하나 불러오고, 거기에 있는 FCLK_CLK[n]을 가져다가 내가 만든 RTL 모듈에 연결시켜야 한다.
또한 이 클럭을 활성화시키려면 보드를 켠 이후에 최소한 한 번은 PS가 동작해야한다. 때문에 PS쪽도 더미 프로그램을 만들어 업로드 및 실행시켜줘야 한다.
Bitstream을 만든 후에 Export Hardware를 수행하고 Launch SDK를 눌러 PS용 Eclipse IDE를 실행시킨다. 그 후 새 프로젝트 생성-> Xilinx -> Application Project -> 프로젝트 명 짓고 C 또는 C++ 선택까지 해서 빈 C/C++ 프로그램을 만들어야 한다. 뭐 main문 안에 return 0;만 있는, 비어있는 프로그램이어도 되고 원한다면 다른 일을 해도 된다. 어쨌든 이 프로그램을 PS가 실행하는게 중요하다.
코드를 작성하고 저장할 때마다 자동으로 빌드가 수행되는데, 그게 완료되면 Program FPGA를 수행하고 Run As/Debug As -> System Debugger on Local/GDB를 통해 PS가 프로그램을 실행하도록 하자. 실행이 한 번이라도 되고 나면 그때부터 PS 클럭이 활동하기 시작하므로 FPGA도 활동하기 시작하게 된다.
이 과정을 밟지 않으면 3번에 정리한 디버깅도 할 수 없다. (Labtools 27-3361 에러)
2. GPIO 이용하기
내가 사용하는 Zynq 보드는 PicoZed FMC Carrier V1에 PicoZed 7030이 꽂혀있는 형태의 보드이다. 처음에 봤을땐 CMOD A7처럼 범용적인 목적으로 쓸 수 있는 핀이 없는가 싶었는데 PMOD라는 규격의 포트가 있었다. 이걸 이용해서 PL에선 (3.3V(LVCMOD33)+GND+4개의 GPIO) * 2 세트까지, PS 시점에선 1세트까지 이용할 수 있다.
3.3V와 GND는 GPIO를 이용하기 위해 물려줘야 하는 거라기 보다는 외부 장치 입장에서 전력을 얻는데에 필요한 포트이기 때문에 아두이노 등에서 이 PMOD에 연결할때는 GPIO 포트만 이용하면 된다. 하지만 일부 아두이노를 포함한 보드들은 GPIO의 전압이 3.3V가 아니라 5V인 경우가 있기 때문에 이를 꼭 하드웨어 스펙과 오실로스코프를 통해 확인하고 연결해야 보드를 고장내지 않을 수 있다. 보통 Level Shifter 칩을 이용해서 IO의 전압을 조절하는데, [여기]를 참고해서 회로를 직접 만들수도 있다.
3. 디버깅 준비하기
Vivado에서 Synthesis를 완료한 이후에 Netlist에서 원하는 입출력 인자를 선택하고 Mark Debug를 해준다. FPGA의 디버깅은 모듈의 입출력만 가능하고 내부의 변수는 확인이 불가능한 것 같다.
그런 다음 Set Up Debug를 실행해서 내가 Mark Debug한 입출력들이 실제로 디버깅 될 수 있게 해준다. 이 때 Clock Region이 undefined된 것들이 있다면 직접 선택해서 내가 이용하고 있는 FCLK[n]으로 지정해주면 된다.
그렇게 하고 Bitstream까지 뽑아내고 나면 다시 SDK 쪽에서 Program FPGA 및 Run/Debug As를 실행해서 PS와 PL 프로그램 둘 다 실행되게 하고, Open Hardware Manager를 누르면 디버깅 창이 나온다. Logic Analyzer라고도 하는 것 같다.
해당 창에서 보고싶은 변수들을 + 버튼을 눌러 추가하고, Trigger 조건에 원하는 조건을 설정해두고 ▶ 버튼을 눌러 Idle 상태에서 Waiting For Trigger 상태로 바뀌도록 하면 디버깅 준비가 끝나게 된다. 그런 다음엔 원하는 동작을 하고 나면 트리거의 조건에 맞게 정보들이 나올 것이다.
참고로 디버깅으로 확인할 입출력이 많아질 수록 Implementation 시간이 기하급수적으로 늘어난다. 그러므로 가능하면 적게 확인하고, 가능하면 오실로스코프로 확인하는게 좋을 것 같다.
4. 고찰
ZynQ 보드는 위와 같이 진행하면 디버깅까지 가능한데, Artix 7 35T (혹은 CMOD A7)은 아직도 디버깅하는 방법을 모르겠다. MicroBlaze를 불러와서 위 처럼 하면 될 것 같긴한데… 내가 클럭을 여전히 PL 클럭을 쓰게 해서 안 되었던 걸까…? 다음에 한 번 시도해봐야겠다. 근데 그러면 오실로스코프 없이 Vivado 상에서 디버깅을 하려면 반드시 PS 클럭을 써야하는걸까…?