Zynq SoC Training – Memory-mapped I/O

Acknowledgement (Korean)
아래의 글은 Ali Aljaani가 운영하는 블로그인 embedded centric의 “Zynq SoC Training”을 번역한 문서입니다. 한글 번역 및 공개를 허용한 Ali Aljaani에게 감사의 말을 전합니다.

Acknowledgement (English)
This post is a translated version of “Zynq SoC training” in embedded centric. Thank you Ali Aljaani for allowing me to translate nice posts. I’m Taekyung Heo, and I translated this post into Korean.

Contact information (Author)
Ali Aljaani’s blog: http://embeddedcentric.com/
Ali Aljaani’s mail: alialjaani@embeddedcentric.com
Ali Aljaani’s LinkedIn: https://www.linkedin.com/in/ali-aljaani-a7130099
Ali Aljaani’s github: https://github.com/ama142


이번 실습에서는 IP core를 PL에 추가해 PS의 기능을 확장하고자 한다. 이 실습에서는 두 개의 GPIO (General Purpose Input/Output) IP를 추가해 processing system을 확장할 것이다. GPIO를 사용하면 주변 장치에 general purpose input/output 인터페이스를 제공할 수 있다. GPIO를 ZedBoard의 푸쉬 버튼과 LED에 연결할 것이다. PS에서 general purpose master interface (M_AXI_GP0)를 활성화하고, AXI 프로토콜을 사용해 PL의 GPIO 주변 장치들과 연결할 것이다. 첫 번째 실습에서 할 것은 아래와 같다 (클릭하면 커짐).

lab1-design-flow2.jpg

Lab 1 Design Flow

lab1-block-diagram1.jpg

Lab 1 Block Diagram

zedboard_reva_sidea_0_0-1_0.jpg

Lab1 Board Interface

어플리케이션 lab1.c는 PS의 ARM 프로세서에서 실행된다. 이 어플리케이션은 GPIO를 사용해 LED에 이진 카운터를 출력한다. lab1.c는 연속적으로 푸쉬 버튼을 읽고, 버튼 조작에 따라 LED가 반짝이는 속도와 방향을 조작하게 된다.

이 실습에서 배울 것
1. Vivado를 사용해 Zynq SoC, ZedBoard를 다루는 방법.
2. IP integrator를 사용해 embedded processor 프로젝트를 생성하는 방법. IP는 intellectual property의 약자이다. IP integrator는 하드웨어 컴포넌트를 시각적으로 설계할 수 있도록 하는 툴이다.
3. Re-customizing window를 사용해 ZYNQ7 processing system을 설정하는 방법. Re-customizing window에서 다음과 같은 것을 설정할 수 있다. Processing system 컴포넌트들의 클럭, 인터럽트, 리셋, 얼마나 많은 프로세서를 쓸 것인지, 어떤 주변 장치를 쓸 것인지, programmable logic의 필요 여부, 어떤 인터페이스를 쓸 것인지 등.
4. PL에 soft IP를 추가하는 방법. 이번 실습에서는 AXI GPIO를 추가하며 이를 배울 것이다. AXI GPIO는 general purpose input/output 인터페이스를 제공하며, AXI GPIO는 한 개 또는 두 개의 채널로 쓰일 수 있다. 채널의 폭은 독립적으로 설정 가능하다. AXI interconnect 또한 추가할 수 있다. AXI interconnect는 PS의 ARM 프로세서와 AXI GPIO를 연결하기 위해 쓰인다. AXI는 ARM 프로세서와 다른 주변 장치의 통신에 사용되는 프로토콜이다.
5. PL side의 AXI interconnect를 연결하기 위해 PS side의 master AXI 인터페이스를 설정하는 방법.
6. IP들의 reset과 clock을 설정하는 방법.
7. AXI GPIO IP들의 폭과 방향을 설정하는 방법.
8. IP와 PS 사이를 연결하는 방법.
9. Designer Assistance를 사용해 IP 사이 연결을 자동화하는 방법.
10. Zynq chip과 주변 장치를 연결하는 방법.
11. IP에 식별자 (주소)를 할당하고 사용하는 방법
12. 제약 조건을 생성하는 방법. Block design에서의 요소와 실제 개발 보드의 컴포넌트를 연관하는 방법
13. Vivado에서 Block Automation 기능을 사용하는 방법.
14. System validation을 수행해 어떤 설계 오류가 있는지 확인하는 방법.
15. PL side를 프로그램하기 위한 bitstream을 생성하는 방법.
16. Vivado가 어떻게 하드웨어 설정을 수행하는지에 대한 이해. ps7_init.c, ps7_init.h, ps7_init.tcl, and ps7_init.html의 파일이이 어떤 역할을 하는지 이해
17. Xilinx SDK (Software Development Kit)에 대한 소개. Xilinx SDK를 사용하면 Zynq SoC family에 대한 쉽고 확장성 있는 소프트웨어 개발이 가능하다.
18. 운영체제를 사용하지 않은 standalone application을 실행하는 방법에 대한 이해 (bare-metal applications). 이러한 standalone application들은 기본적인 프로세서의 기능인 cache, interrupts, exception 등을 사용할 수 있다. Standard input/output, profiling, abort, exit 등을 지원한다.

실습 단계
A. Vivado에서 프로젝트를 생성하고 target board로 ZedBoard 선택
1. Vivado Design Suite를 실행한다.
2. File -> New Project를 클릭하고, New Project Wizard를 연다. 그리고 Next를 선택한다.

new-project-wizard

New Project Wizard

3. 다음 창에서 Project Name에 “lab1″을 입력한다. 그리고 프로젝트를 생성할 디렉토리를 선택한다. 현재 창에서는 Project Location으로 “c:/embeddedcentric/”를 선택했다. 해당 위치에 lab1 이라는 이름의 프로젝트 디렉토리가 생성된다. Create Project Subdirectory를 선택한다.

projectname2

Project Name and Location

4. 다음으로 프로젝트 타입을 선택한다. RTL Project를 선택하고, Do not specify sources at this time을 체크한다. RTL은 Register Transfer Language의 약자이고, 이 옵션을 선택하면 소스 코드를 나중에 추가할 수 있다.

projecttype

Project Type

5. 다음으로 프로젝트를 실행할 보드를 선택한다. 모든 Zynq SoC Training 실습에서 우리는 ZedBoard Zynq Evaluation and Development Kit version D를 사용할 것이다. Next를 선택하고 완료한다.

default-part

Default Part

New Project 마법사가 닫히고 생성한 프로젝트가 Vivado에서 열릴 것이다. 마법사에서 선택한 보드에 따라 IP integrator의 기능이 다소 달라진다. IP integrator는 선택한 보드를 인지하고 있으며, 이에 따라 보드에 맞게 pin을 자동으로 설정해준다.

vivado-interface

Vivado Interface

B. IP integrator를 사용해 embedded processor 프로젝트 생성
1. Vivado 좌측에 있는 Project ManagerCreate Block Design을 클릭한다.
2. 모듈의 이름을 입력하고 OK를 선택한다. 이 예제에서는 “system”이라는 이름을 사용했다.

create-block-design

Create Block Design

3. OK를 선택한 이후, block diagram 창이 열릴 것이다. Block diagram 창에서 하드웨어 설계를 위한 블록들을 추가하고 연결할 수 있다.
4. Block diagram 창에서 ZYNQ7 processing system 블록을 추가한다. 이 블록을 추가함으로써 ARM Cortex-A9 프로세서 코어를 사용할 수 있다. Add IP 마법사를 사용해 ZYNQ7 processing system을 추가할 수 있다. Block design에 추가할 수 있는 IP 목록을 보여주는 IP catalog 창이 아래처럼 열릴 것이다.

ip-catalog

IP Catalog

IP catalog 창에서 ZYNQ7 processing system을 찾아 스크롤을 내려도 되고, 아니면 탐색창에서 zynq를 입력해도 된다. ZYNQ7 processing system을 선택하면 block diagram 창에 해당 블록이 나타난다. Block diagram에서 보이는 포트들은 개발 보드에 맞춰진 기본 세팅에서 미리 설정된 것이다.

default-ports

Default Ports

C. ZYNQ7 processing system 설정
ZYNQ7 processing system 블록을 사용해 Zynq PS의 클럭 주기, 리셋 극성, 인터럽트, 메모리 인터페이스, 입출력 주변장치 등을 설정할 수 있다. 이번 실습에서는 GPIO를 사용할 수 있도록만 간단히 수정할 것이다.

1. ZYNQ7 processing system 블록을 더블 클릭해 re-customize 창을 연다. Page navigator는 다음과 같은 페이지를 포함하고 있다.

PS-PL Configuration: Processing system(PS)과 programmable logic(PL) 사이의 인터페이스를 설정한다. PS와 PL 사이의 인터페이스 방식에는 네 가지가 있으며, PS와 PL 사이에 전송하려는 데이터의 대역폭과 크기에 따라 인터페이스를 결정한다.

Peripheral I/O Pins and MIO configuration: Zynq-7000 PS는 20개가 넘는 주변 장치 컨트롤러를 갖고 있다. 이러한 주변 장치를 사용하기 위해 dedicated Multiplexed I/O (MIO)를 사용할 수도 있고, Extended Multiplexed I/O (EMIOs)를 사용할 수도 있다. 주변 장치를 활성화하면 Page Navigator의 Zynq Block Design 화면에서 체크 표시가 나타난다.

Clock Configuration: 주변 장치들은 다른 주기의 클럭으로 동작할 수 있다. Clock Configuration 탭에서 장치별 클럭을 설정할 수 있다.

DDR Configuration: 보드에 있는 메인 메모리인 DDR과 관련된 모든 것을 설정할 수 있다.

SMC timing calculation: Static Memory Controller에 대한 설정을 할 수 있다.

Interrupts: PL->PS 인터럽트, PS->PL 인터럽트 모두를 설정할 수 있다.

Note: Customizing 과정에서 실수로 잘못 설정했다면 re-customize IP 창의 왼쪽 상단에 있는 Presets를 선택하고 ZedBoard 템플릿을 선택해 기본 설정으로 되돌릴 수 있다.

2. Page navigator에서 MIO Configuration을 선택한다. I/O peripherals를 확장하고 UART1을 선택한다. ARM processor의 터미널로 UART를 사용할 것이다.

uart1-enabling

Enabling UART1

3. Clock Configuration을 선택한다. PL Fabric Clocks를 확장하고 FCLK_CLK0를 선택한다. Requested Frequency(MHz)에 100을 입력한다. 이 실습에서 PL fabric을 사용할 것이기 때문에, PL fabric에 clock을 주어야 한다.

enabling-pl-fabric-clock

Enabling PL Fabric Clock

4. PS-PL Configuration을 선택한다. AXI Non Secure Enablement를 확장하고, GP Master AXI Interface를 확장한다. M AXI GP0 인터페이스를 선택한다. 이 실습에서 PL을 사용할 것이므로, PS와 PL이 통신하기 위한 채널이 필요하다.

enabling-gp-master-axi-interface

Enabling GP Master AXI Interface

5. PS-PL Configuration에서 General > Enable Clock Resets를 확장하고 FCLK_RESET0_N을 선택한다. 이는 PL 회로의 reset으로 사용될 것이다. OK를 선택해 re-customize IP 창을 닫는다.

enabling-clock-resets

Enabling Clock Reset

Block design의 상단의 Run Block Automation 을 선택한다. Run Block Automation은 개발자가 주변 장치를 연결하는 것을 도와준다. 앞서 설정한 것이 덮어쓰여지지 않도록 Apply Board Preset을 선택 해제해야 한다 (역자 주: 본인의 경우, Apply Board Preset을 선택해야 제대로 동작하는 것을 확인했다.)

generating-external-connections-for-the-uart

Generating External Connections for the UART

위 창에서 OK를 선택하면 아래처럼 Zynq Processing System에 FIXED_IODDR이 연결된 것을 확인할 수 있다. Vivado가 USB-UART 연결을 만들어준 것을 확인할 수 있다 (FIXED_IO). USB-UART chip을 개발 보드의 RX, TX 핀과 연결해준다. 뿐만 아니라 DDR 메모리 주소 버스, 데이터 버스, 제어 버스도 연결해준다. DDR 메모리는 lab1.c 프로그램과 software package를 저장하기 위해 쓰인다.

ps-with-uart-connected-to-external-pins1

PS connected to DDR memory and USB-UART chip available on board

D. PL-side에 IP 추가
1. Add IP 버튼을 선택한다. 탐색 창에서 “gpio”를 입력하면 AXI GPIO를 찾을 수 있다. IP catalog에서 AXI GPIO를 더블 클릭해 이를 block diagram에 추가한다.

addinggpio

Adding GPIO

2. AXI GPIO 블록을 선택하고 속성 탭에서 이름을 led_8bits로 변경한다.

changing-the-gpio-name1

Changing the GPIO name to led_8bits

3. AXI GPIO 블록을 더블 클릭해 customization 창을 연다. Board 탭 아래에서 GPIO에 해당하는 Board Interface로 leds_8bits를 선택한다. OK를 선택해 저장하고 닫는다. 프로젝트 생성 과정에서 ZedBoard를 개발 보드로 선택했기 때문에, leds 8bits를 GPIO에 연결하면 Vivado가 자동으로 IP의 width와 direction을 8 bits에 맞추어 설정해준다.

customizing-gpio-led_8bits

Customizing GPIO led_8bits

4. Block diagram의 좌측 상단에 Designer Assistance를 사용할 수 있음을 확인할 수 있다. Run Connection Automation을 선택하고, GPIOS_AXI를 선택한다. OK를 선택하면 자동으로 GPIO의 slave 인터페이스를 GPIO master 인터페이스에 연결해준다. Designer Assistance 기능은 자동으로 포트를 적합하게 연결해준다.

run-connection-automation

Run Connection Automation

두 개의 블록이 자동으로 추가되었음을 확인할 수 있다. Processor System ResetAXI interconnect가 block diagram에 자동으로 추가되었다.

system-after-adding-the-first-gpio1

System after adding the first GPIO IP

Designer Assistance가 자동으로 PL-side의 GPIO와 PS를 연결하는 것에 필요한 필수적인 하드웨어와 회로를 추가해준다. AXI interconnect는 한 개의 master 장치 (ARM 프로세서)를 두 개의 memory-mapped slave 주변 장치 (GPIO)에 연결하는 것에 필수적이다. Processor System Reset은 이 시스템이 여러 개의 reset 조건을 다루도록 해준다.

5. Add IP 버튼을 눌러 AXI GPIO를 선택한다.
6. IP를 선택하고 block property 창에서 블록의 이름을 “btns_5bits”로 변경한다. 이 시점에서 해당 AXI GPIO를 추가하기 위해 앞에서 한 것과 같이 Designer Assistance를 사용할 수도 있다. 여러가지 목적을 위해 btns_5bits AXI GPIO는 수동으로 추가해보고자 한다.

changing-the-gpio-name-btns_5bits

Changing the GPIO name btns_5bits

E. btns_5bits GPIO를 시스템에 수동으로 추가 (Designer Assistance를 사용하지 않고)
I. 외부 연결
1. btns_5bits AXI IP를 더블 클릭해 customization 창을 연다. IP 설정 창에서 GPIO 폭을 5로 설정한다 (ZedBoard에 푸시 버튼이 5개가 있기 때문이다). All Inputs를 선택한다 (푸시 버튼은 모두 입력 장치이기 때문이다). GPIO는 두 개의 채널을 갖도록 설정할 수 있으나, 이번 실습에서는 한 개의 채널만 있으면 된다. 그리고 인터럽트를 사용하지 않도록 설정한다. OK를 클릭해 설정을 저장한다.

manually-customizing-gpio-btns_5bits

Manually customizing GPIO btns_5bits

2. btns_5bitsGPIO 포트를 우클릭해 메뉴를 띄우고 Make External을 선택한다. 이는 GPIO라는 이름을 갖는 외부 포트를 생성하고 이를 주변 장치에 연결한다.

manually-making-external-connection

Manually making an external connection

3. GPIO 포트를 선택하고 속성 창에서 이름을 btns_5bits로 변경한다.

naming-the-btns_5bits-external-port

Naming the btns_5bits external port

II. 내부 연결
1. AXI Interconnect를 더블 클릭해 re-customize 창을 연다. Number of Master Interfaces를 2로 설정하고 OK를 선택한다.

changing-the-number-of-master-interfaces-of-the-axi-interconnect-to-2

Changing the Number of Master Interfaces of AXI Interconnect to 2

2. btns_5bits 블록의 S_AXI 포트를 클릭하고 포인터를 드래그한다. 이 때 “Found 1 Interface”라는 메시지가 초록색 체크 표시와 함께 뜰 것이다. 포인터를 드래그해서 이 위치에 연결을 생성한다.

connecting-btns_5bits-internally2

Connecting btns_5bits internally

3. 같은 방식으로 다음 신호들을 연결한다.
btns_5bits s_axi_aclk -> Zynq7 Processing System FCLK_CLK0
btns_5bits s_axi_aresetn -> Processor System Reset peripheral_aresetn
AXI Interconnect M01_ACLK -> Zynq7 Processing System FCLK_CLK0
AXI Interconnect M01_ARESETN -> Processor System Reset peripheral_aresetn

이렇게 연결하면 block diagram은 다음과 같을 것이다.

system-after-connecting-gpio-btns_5bits2

System after connecting GPIO btns_5bits

Block diagram viewer toolkit의 Regenerate Layout을 선택해 블록들과 그 연결을 재정렬할 수 있다.

F. Memory-mapped 장치에 주소 할당
IP 안에는 data register와 control register들이 있다. 이를 사용해 프로세서는 IP에 정보를 쓰고, 정보를 읽어낼 수 있다. 따라서 IP들은 프로세서가 접근할 수 있도록 memory-mapped 장치여야 한다. 각각의 memory-mapped 장치 (IP)는 반드시 유일한 식별자를 가져야 한다. 이 유일한 식별자는 base address 또는 장치의 offset address라고 불린다. 이 주소가 해당 장치의 register가 위치하는 메모리 주소이다. Design에서 IP에게 offset address를 할당하기 위해 Address Editor 탭을 선택하고 Auto Assign Address 버튼을 선택한다.

address-editor

Address Editor

Note: led_8bits에 대해서는 Designer Assistance를 사용했기 때문에 이미 offset address가 할당되어 있다.

address-editor-after-auto-assign-address

Address Editor after Auto Assign Address

G. 디자인 검증
이 실습에서 Zynq의 PL side를 쓰고 있으므로, PL을 설정하기 위한 Bitstream 파일을 생성해야 한다. Bitstream을 생성하기 전에 해야 하는 중요한 단계는 디자인 검증이다. 디자인 검증을 통해 디자인 오류를 확인할 수 있다. 예를 들어, clock의 주기가 잘못 설정되어 있을 수 있다. 디자인 검증을 통해 오류를 잡아낼 수 있다.

디자인 검증(Tools -> Validate Design)을 통해 디자인에 오류가 없음을 확인한다.

validate-design

Validate Design

Save 버튼을 클릭해 현재의 block diagram을 저장한다. 그 이후에 Source 창으로 이동해 system.bd를 우클릭한다. Create HDL Wrapper를 선택해 block diagram에 대한 Verilog 파일을 생성한다. Let Vivado manage wrapper and auto-update를 선택한다. system_wrapper.v가 생성된 것을 확인할 수 있다.

create-hdl-wrapper

Create HDL Wrapper

H. Pin 할당 및 설정
E-I-2에서 할당한 외부 포트에는 어느 pin도 할당되어 있지 않다. Pin을 할당하고 설정하기 위해서는 해당 포트를 Zynq chip에 연결해주어야 한다.

1. Flow Navigator에서 Run Synthesis를 클릭한다 (어느 정도 시간이 걸린다). 그리고 합성이 끝나면 Open Synthesized Design을 선택하고 OK를 클릭한다.
2. 상단의 툴바에서 콤보 박스에서 I/O Planning을 선택한다. 이는 chip의 Package view를 보여줄 것이다 (칩의 하단).

io-planning

I/O Planning

bottomside-of-a-chip

Bottomside of a chip

Zynq chip의 하단 어느 부분이 푸시 버튼과 연결되어 있는지 확인해야 한다. 이를 찾기 위해 ZedBoard 매뉴얼을 확인한다. 구글에서 “ZedBoard user manual”을 찾아본다.

finding-zedboard-user-manual

Finding ZedBoard User Manual

PDF 파일을 열고 “User I/O”에 대한 정보를 찾아보면 아래와 같이 나온다.

zedboard-userio-connections

Zedboard UserIO Connections

Signal name은 ZedBoard 상단에 출력된 컴포넌트의 이름과 동일하다. Zynq EPP pin은 해당 컴포넌트가 연결된 핀의 이름을 나타낸다. I/O Ports 창에서 SITE와 I/O를 다음 그림과 같이 매핑한다.

physical-constraints-for-the-zedboard-pushbuttons1

Physical constraints for the Zedboard push buttons

Note: E, F, H 단계를 수행하는 것은 Designer Assistance를 사용하는 것과 같다. Designer Assistance를 사용하지 않은 이유에는 두 가지가 있다. 먼저, 이 방식이 customized IP core를 연결하는 일반적인 방법이다 (3rd party에서 생산한 IP core). Designer Assistance는 3rd party에서 생산한 IP core를 연결하는 것에 사용하지 못하기 때문에 이 방법을 알아둘 필요가 있다. 두 번째로, Designer Assistance가 하는 일이 무엇인지 알아둘 필요가 있기 때문에 이를 소개했다.

I. Bitstream 생성
이 실습에서 Zynq의 PL side를 사용하고 있기 때문에, PL을 프로그래밍하기 위한 Bitstream을 생성해야 한다. Flow NavigatorProgram and Debug 리스트에서 Generate Bitstream을 클릭한다.

generating-bitstream1

Generating Bitstream

수정 사항을 저장할 것인지 묻는 대화 상자가 나오면 Save를 누른다. 합성된 것이 제대로 업데이트 되지 않아, 다시 실행할 것인지 물으면 OK를 선택한다. 그리고 constraints를 저장하라는 창이 뜨면 파일 이름을 system이라 지정하고 OK를 클릭한다.

saving-constraints

Saving Constraints

Bitstream을 생성 과정에서 synthesis와 implementation 단계를 다시 실행하도록 할 수 있다. 이 때 Yes를 클릭하여 synthesis와 implementation이 최신 버전으로 업데이트 되도록 한다. Bitstream 생성이 끝나면 Open Implemented Design을 선택하고 OK를 클릭한다. 이를 통해 PL 자원 사용 현황을 확인할 수 있다.

J. 하드웨어 디자인 SDK로 내보내기
Zynq 플랫폼에서의 소프트웨어 어플리케이션 개발은 독립적인 툴킷인 SDK (Software Development Kit)에서 수행하게 된다. 하드웨어 시스템 설계가 완료되면, 설계한 것을 SDK로 내보낼 수 있다. SDK에서는 이 설계에 기반해 어플리케이션을 개발한다. 다음과 같은 순서로 어플리케이션을 개발할 수 있다.
1. File > Export > Export Hardware를 클릭한다.
2. Export Hardware 대화상자가 열린다. Include Bitstream을 체크하고, OK를 선택해 계속한다.

export-hardware-to-sdk

Export Hardware to SDK

3. File 메뉴로 돌아가서 Launch SDK를 선택한다. Launch SDK 대화 상자에서 기본 설정으로 한 뒤 OK를 클릭한다.

여기까지 한 것이 하드웨어 설계이다. 이제 소프트웨어 부분으로 넘어가서 어플리케이션 개발을 계속하면 된다. Vivado를 닫아도 된다.

K. SDK를 사용해 프로그램 개발하기
이제 SDK를 사용해 소프트웨어를 개발할 수 있다. Vivado가 하드웨어 설계에 대한 대한 Hardware Platform Specification을 SDK에 내보냈다. system.xml 뿐 아니라, SDK에 관련되어 생성된 네 개의 파일이 있다. ps7_init.c, ps7_init.h, ps7_init.tcl, ps7_init.html이다.
system.xml 파일은 SDK가 실행되는 시점에 기본적으로 열리게 된다. 설계한 시스템에 대한 address map이 SDK 창에서 기본적으로 보이게 된다. ps7_init.c와 ps7_init.h는 Zynq Processing System, DDR, 클럭, PLL, MIO에 대한 초기화 코드를 담고 있다. SDK는 이 세팅들을 사용하여 어플리케이션이 processing system이 올라가기 전에 시스템을 초기화한다.

sdk-interface

SDK Interface

1. SDK에서 File > New > Application Project를 선택한다.
2. 다음 창에서 프로젝트 이름으로 lab1을 입력한다. 어플리케이션 저장을 위한 위치에 대해 Use default location을 선택하고, Hardware Platform으로는 system_wrapper_hw_platform_0을 선택한다. system_wrapper_hw_platform_0는 앞서 Vivado에서 우리가 정의한 하드웨어에 대한 정의이다. 그리고 processor로는 ps7_cortexa9_0를 선택한다. 운영체제 기능을 사용하지 않을 것이기 때문에, OS platform으로는 standalone을 선택한다. 이번 실습에서 C언어를 사용해 어플리케이션을 작성할 것이다. lab1_bsp라는 이름으로 새로운 board support package를 생성한다. Next를 클릭하면 많은 템플릿 중에 하나를 선택할 수 있다. Empty Application을 선택하고, Finish를 클릭한다. lab1 어플리케이션 프로젝트와 lab1_bsp BSP 프로젝트가 생성된 것을 확인할 수 있다.

creating-a-standalone-c-application-project

Creating a Standalone C Application Project

3. lab1 디렉토리를 확장하고, src 디렉토리를 우클릭한다. 그리고 New->Source File을 선택한다.

new-c-source-file

New C Source File

4. 다음 창에서 Source file에 lab1.c을 입력하고 Finish를 클릭한다. 이는 src 디렉토리에 빈 C 파일을 생성할 것이다.

create-an-empty-c-source-file-lab1

Create an Empty C Source File lab1.c

5. lab1.c에 코드를 붙여넣는다 (내 Github 페이지에서 확인할 수 있다). 그리고 이를 저장한다. 이렇게 함으로써 lab1 어플리케이션과 BSP 모두 동시에 자동으로 컴파일되고 실행 가능한 .elf 파일이 생성된다 (기본적으로 SDK는 저장과 동시에 컴파일하도록 되어 있다). 이렇게 생성된 실행 파일은 Zynq의 PS side에서 실행된다. lab1.c는 다음과 같은 작업을 수행한다.
a. 푸시 버튼 GPIO와 LED GPIO 모두를 초기화한다.
b. 푸시 버튼 GPIO의 방향을 모두 입력으로 향하게 한다.
c. LED GPIO의 방향을 모두 출력으로 향하게 한다.
d. 무한 루프를 돌면서 푸시 버튼의 상태를 읽고, LED 반짝임의 속도와 방향을 조절한다.
e. LED에 쓰기를 수행한다.
f. software delay를 준다 (반짝이는 것처럼 보이도록 하기 위해서).

GPIO driver에 대한 정보를 확인하기 위해 lab1_bsp의 gpiops.h를 확인할 수 있다.

compile-the-application-and-its-bsp

Compile the Application and its BSP

6. 이 실습에서 우리는 ZedBoard와 호스트 컴퓨터 사이에 Putty를 사용해 시리얼 통신을 수행할 것이다. 설치한 다음에, Putty를 열고 connection type으로 Serial을 선택한다. 장치 관리자에서 USB-UART에 할당된 serial port를 확인하고, 이에 맞추어 Putty의 Serial line을 설정한다 (컴퓨터마다 다를 수 있음). 속도는 115200으로 맞추고 Open을 선택한다.

usbuartport1

Serial line on my machine ( USB-UART port)

putty-settings

Putty Settings

ARM 프로세서의 표준 출력을 출력하는 까만 창이 뜰 것이다. 이 터미널을 통해 ZedBoard에서 어떤 것이 실행되고 있는지를 확인할 수 있다. 추후에 디버깅이 필요하다면 이같은 표준 출력을 통해 디버깅 할수도 있다.

7. 이제 PL-side를 Bitstream으로 프로그래밍하고 lab1 어플리케이션을 ARM 프로세서에서 실행할 준비가 되었다. PS-side의 설정은 SDK에서 생성해준 ps7_init.tcl을 사용해 수행된다. 이는 processing system에 대한 초기화 정보를 담고 있다. 어플리케이션이 다운로드되는 시점에 configuration file이 JTAG을 사용해 실행될 것이다.

L. Bitstream 다운로드하고 프로그램 실행하기
1. Bitstream을 다운로드하기 위해 Xilinx Tools-> Program FPGA 을 선택한다. 기본 옵션으로 두고 Program을 클릭한다 (시간이 걸릴 수 있음).

program-fpga

Downloading Bitstream to the PL

2. lab1 어플리케이션을 ARM 프로세서에서 실행하기 위해 lab1 프로젝트 디렉토리를 선택하고, Run As -> Launch on Hardware (GDB)를 클릭한다.

launch-application

Launch Application

다음과 같은 출력을 Putty에서 확인할 수 있다. 그리고 ZedBoard에 있는 LED가 반짝이는 것도 확인할 수 있다.

puttyoutput1

Putty Output

ZedBoard에 있는 8개의 LED는 “out” 변수를 binary로 출력한다. 예를 들어, 변수 “out”이 26이면 이에 해당하는 2진수 00011010를 출력한다. LED는 다음과 같은 패턴을 출력한다.

leds-output1

LEDs Output

“out”의 값은 0~255의 범위에 제약되어 있다 (8 bits). “out”을 증가시킬 것인지 또는 감소시킬 것인지를 up 또는 down 푸시 버튼을 눌러 조절할 수 있다. LED가 깜빡이는 속도는 푸시 버튼의 왼쪽, 중앙, 오른쪽을 눌러 조절할 수 있다. 왼쪽 푸시 버튼이 가장 느린 속도이고, 오른쪽이 가장 빠른 속도이다. 시연 영상을 아래에서 확인할 수 있다.


이로써 첫 번째 실습인 memory-mapped I/O를 마친다. 이번 실습에 대한 해답은 여기에 있다.


Advertisements
Tagged with: , , , , , , , , , , , , , , , , , , , , , , ,
Posted in FPGA

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Recent Posts
누적 방문자 수
  • 142,141 hits
%d bloggers like this: