소개
FPGA 에 비트스트림(bitstream)을 전송하는 작업은 보통 그래픽 사용자 인터페이스(GUI)를 사용해야 한다. Vivado 의 Hardware Manager 같은 도구가 이 기능을 제공하지만, 이 단순한 작업에 비해 절차가 지나치게 복잡하게 느껴지는 경우가 많다. 특히 하나의 JTAG 케이블로 FPGA 하나만 컴퓨터에 연결되어 있을 때도 마찬가지다. 사용자 인터페이스는 불필요한 단계를 많이 요구한다. FPGA 가 하나뿐인데, 왜 컴퓨터는 이 FPGA 에 비트스트림 파일을 써야 한다는 사실을 스스로 알아내지 못하는 것일까? 도구에게 원하는 작업을 명시적으로 알려주어야 하는 이유가 무엇일까? 실제로 선택지는 하나뿐인데 말이다.
가능한 해결책 중 하나는 이 작업을 한 번에 처리하는 bash 스크립트(script)를 사용하는 것이다. 이 스크립트는 JTAG 케이블을 통해 컴퓨터에 연결된 FPGA 를 찾아서, 그 FPGA 에 비트스트림 파일을 전송한다.
스크립트
다음은 FPGA 에 비트스트림 파일을 전송하는 스크립트이다.
#!/bin/bash
set -e
if [ "$#" -ne 1 ]; then
echo "Usage: $0 bitstream-file.bit"
exit 1
fi
if ! which vivado >/dev/null ; then
echo Vivado is not in the execution path. Please run something like
echo source /path/to/..../Vivado/20nn.n/settings64.sh
exit 1
fi
if [ ! -f "$1" ] ; then
echo \"$1\" file doesn''t exist
exit 1
fi
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" <<"EOF"
# Tcl script begins here.
set bitfile [lindex $argv 0]
open_hw
connect_hw_server
open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost*]] 0]
set thefpga [lindex [get_hw_devices] 0]
set_property PROGRAM.FILE "$bitfile" $thefpga
set_property PROBES.FILE {} $thefpga
current_hw_device $thefpga
refresh_hw_device -update_hw_probes false $thefpga
program_hw_devices $thefpga
# Tcl script ends here
EOF
then
echo -e "\nProgramming successful.\n"
else
echo -e "\nProgramming failed.\n"
fi
이 bash 스크립트에는 Tcl 스크립트가 포함되어 있음에 주의하자. ‘vivado’ 명령에 전달되는 인자 중 하나가 ‘-source /dev/stdin’이다. 그 결과 Vivado 가 표준 입력에서 Tcl 스크립트를 읽는다. 여기서는 잘 알려진 ‘here document’ 방식이 ‘<<’를 이용해 사용되고 있다.
스크립트 사용하기
위에 표시된 스크립트를 파일로 저장하자. 예를 들어 fpga_program 이라는 이름으로 저장한다. 그런 다음 다음과 같은 명령으로 이 파일을 실행 가능하게 만든다:
$ chmod a+x fpga_program
스크립트를 실행하기 전에, 다음 명령과 비슷한 명령으로 환경 변수를 설정하자:
$ source /opt/xilinx/Vivado/2023.1/settings64.sh
이 명령에서 ‘/opt/xilinx/Vivado/2023.1’ 부분은 컴퓨터에서 Vivado 가 설치된 경로(path)에 맞게 바꾸어라.
그런 다음 다음과 같은 명령으로 스크립트를 실행한다:
$ ./fpga_program myproj.bit
물론 ‘myproj.bit’ 부분은 여러분의 비트스트림 파일 이름으로 바꾸면 된다.
이 스크립트가 실행되는 동안 Vivado 가 많은 출력을 내보내지만, 마지막 줄은 ‘Programming successful’ 또는 ‘Programming failed’ 중 하나이다.
스크립트에 대한 몇 가지 참고 사항
이 스크립트는 Vivado 2015.2 및 Vivado 2023.1 에서 테스트되었으므로, 모든 Vivado 버전에서 동작할 가능성이 높다. 다만 최신 Vivado 버전에서는 소프트웨어가 다음과 같은 경고(warning)를 출력한다:
WARNING: 'open_hw' is deprecated, please use 'open_hw_manager' instead.
이 경고가 나와도 스크립트는 정상적으로 동작한다. 하지만 향후 Vivado 버전에서는 ‘open_hw’ 명령을 인식하지 못할 가능성이 있다. 만약 이 명령 때문에 오류가 발생한다면 스크립트에서 해당 명령을 ‘open_hw_manager’로 바꾸면 된다.
스크립트에 적용할 수 있는 또 하나의 변경 사항은 이 스크립트가 생성하는 출력량에 관한 것이다. 텍스트 출력이 많이 필요하지 않다면 출력이 /dev/null 로 향하도록 리디렉션(redirection)을 추가하면 된다.
이렇게 하려면 스크립트에서 다음 행을 찾는다:
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" <<"EOF"
그리고 다음과 같이 바꾼다:
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" > /dev/null <<"EOF"
하드웨어 서버 중지하기
같은 컴퓨터에서 여러 버전의 Vivado 를 사용하면 JTAG 케이블 연결에 문제가 발생할 수 있다. 그 이유는 Vivado 가 하드웨어와 통신하기 위해 TCP/IP 서버를 사용하기 때문이다. 이 서버는 포트 3121 에서 수신 대기한다. Vivado 는 필요할 때 이 서버를 자동으로 시작한다.
그런데 서버가 한 버전의 Vivado 에 의해 시작된 상태에서 다른 버전의 Vivado 가 FPGA 에 연결을 시도하면 통신이 제대로 동작하지 않을 수 있다. 서버의 버전이 서버를 시작한 Vivado 의 버전과 동일하기 때문이다. 이 상황은 Hardware Manager 를 그래픽 사용자 인터페이스(GUI)로 사용할 때도 동일하게 발생한다.
이 문제가 발생하면 다음 명령으로 서버를 중지할 수 있다:
$ killall hw_server
참고로 서버는 일정 시간 동안 사용되지 않으면 스스로 실행을 중지한다.