대학원/대회 준비 관련

[ZCU-104] Ethernet Echo 통신을 이용한 원하는 데이터 수신

오비루 2024. 3. 15. 14:19
728x90
728x90

 

우선 내가 이번 글에서 사용한 Block diagram이다.

내가 이 동작을 하는데 있어서 모르고 있던 부분은 AXI를 이용하는 방법이었다.

그래서 AXI에 대해서 먼저 알아봐야 했다

AXI란?

두 장치간의 데이터 송수신을 위해서 둘 사이의 handshaking이 필요하다.

https://wikidocs.net/135556

 

02) AXI Architecture

[TOC] ## Handshake Process 기본적으로 Source에서 Destination으로 데이터를 잘 전송하려면 둘 간의 핸드쉐이킹이 필요합니다. Destinati…

wikidocs.net

 

 

다음 사진을 예로 보면, Souce에서 Destination으로 데이터를 보낼때는 VALID & INFORMATION을 주고 반대의 경우 READY 신호를 보낸다.

각 데이터에는 역할이 존재하는데,

VALID는

“나 이제 신호 보낸다” 를 의미하고

READY는

“나 데이터 받을 준비 됐어” 를 의미한다.

 

그래서 하단의 사진과 같은 경우처럼 총 3가지가 존재하며, 두 신호 모두 1이 되었을 때의 상태에서 데이터 전송이 이루어진다.


이렇듯 AXI에는 신호를 보내는 입장 & 받는 입장이 존재한다.

이때 데이터를 보내고 받는것에 대한 채널이 각각 5가지로 존재한다.

 

 

각 채널의 역할은 하단의 표와 같다.

 

대략적인 AXI에 대한 구성은 다음과 같으며, 이를 연결할 때에는 직접 연결도 가능하지만 Master & Slave가 존재하는 경우 중간에 Interconnect를 통해서 연결을 합니다.

 

 

 

이 Interconnect는 Master & Slave 간의 M:N의 연결이 가능하도록 만들어준다.


대충 이런식으로 AXI는 동작을 한다.

이제 PS ↔ PL 간의 동작을 설명해보도록 하겠다.

내가 만들고자 하는 디자인은 다음과 같았다.

  • 송신된 숫자 데이터에 대해서 홀 & 짝에 대한 결과물을 다시 PC로 해주는 작업
  • Switch의 on/off에 따른 데이터 송수신 상태 제어
  • led에 송신된 데이터에 대한 불이 들어오기

사실 처음에는 단순하게 Port를 이용해서 데이터를 송수신 할 수 있지 않을까? 라는 막연한 생각을 했었다.

그래서 해당 방법으로 시도해보았으나, 지속적인 오류 발생으로 문제를 파악했고 결국 PL에서 PS로 데이터를 보낼때 AXI를 필히 이용해야 함을 알아냈다.

 

320x100

Creating a custom IP block in Vivado

 

Creating a custom IP block in Vivado

Update 2017-11-01: Here’s a newer tutorial on creating a custom IP with AXI-Streaming interfaces Tutorial Overview In this tutorial we’ll create a custom AXI IP block in Vivado and modify its functionality by integrating custom VHDL code. We’ll be us

www.fpgadeveloper.com

이 AXI를 설정하기 위해서는 위의 링크 속 방법과 동일하게 시도하면 된다.

AXI4 peripheral을 통해 IP 생성을 해주면, 하단의 사진처럼 Users가 직접 추가하는 port가 존재한다.

 

나는 여기에 데이터 송수신을 위해 입&출력 포트를 적어주었다.

여기서 중요한 것은 AXI에는 총 4개의 32bit 크기의 Register가 존재한다는 것이다.

이를 통해서 데이터를 송수신 및 제어 등이 PS 영역에서 가능한 것이다.

 

그게 바로 위의 사진에 대한 내용이다.

그래서 이를 이용해서 내가 원하는 입출력 신호를 전달해주었다.

 

이렇게 만든 AXI ip와 내가 구동하고자 하는 module을 하나로 융합을 해주면 최종적으로 PL에서 수행해야 하는 부분은 끝이다.

 

728x90

하단의 표 내용은 내가 설정한 Register에 대한 역할들을 나타낸 것이다.

REGISTER value(LSB) 역할

REG0 4bit PS에서 받은 0~15 데이터
REG1 1bit PL나온 홀/짝 데이터

이후 최종적으로 나온 IP의 모습은 다음과 같다.

 

출력은 LED에 대한 값이 필요하기에 이 부분은 constraints를 이용해서 설정해주었다.

이렇게 나온 IP block을 이용해서 전체적으로 PS와 연결을 해주면 Block diagram에 있어서 진짜 완성이 된다.

 

ps) 여기서 Switch 부분은 GPIO를 이용해서 제어를 해주었다.

이후 VITIS에서 사용 가능하도록 Bitstream을 해주고, xsa파일로 EXPORT해준다.


VITIS에서는 우리가 AXI를 사용했기에 그 주소값을 이용해서 데이터를 주고받는 방식으로 제어를 할 것이다.

 

따라서, 먼저 만들었던 xsa파일을 불러주고, 내가 만들었던 AXI ip랑 GPIO의 주소값이 어디있는지 살펴보자.

이렇게 나타난다면 정상적으로 업로드 된 것이고, 이후 사용을 위해서는 “xparameters.h”에 들어가준다.

그럼 이렇게 주소값들이 위의 위치와 동일하게 설정되어 있는 것을 확인할 수 있다.

이제 이 주소값들을 이용해서 AXI를 제어해주면 된다.

 

먼저 Register는 총 2개를 사용했기에 코드를 작성하며 헷갈리지 않도록 각각의 역할을 정의해주었다.

이후 위에서 언급했듯 Switch를 이용해서 출력 데이터를 제어하며, 서로 다른 출력 값을 PC로 재전송 하는 것이 목표였다.

따라서 코드를 다음과 같이 작성해보았다.

	if (tcp_sndbuf(tpcb) > p->len) {
		DipSwitchStatus = XGpio_DiscreteRead(&Gpio, DIP_SWITCH_CHANNEL);
		xil_printf("XGpio_DiscreteRead\\n\\r");
		Xil_Out32((XPAR_IP_SLAVE_V1_0_0_BASEADDR) + (DATA_SEND * AXI_DATA_BYTE), (u32)(number));
		xil_printf("Xil_Out32\\n\\r");
		recieve_data = Xil_In32((XPAR_IP_SLAVE_V1_0_0_BASEADDR) + (DATA_RECIEVE*AXI_DATA_BYTE));
		xil_printf("recieve_data\\n\\r");

		if(DipSwitchStatus){//dip switch on = led & data on
			Recieve_function(recieve_data, state);
			tcp_write(tpcb, state, strlen(state), 1);
		} else 			//dip switch off = led & data off
			tcp_write(tpcb, non, strlen(non), 1);

	}

이 코드를 recieve_callback 함수 내에 작성을 통해서 PC에서 Ethernet을 통해 데이터가 송신되며 발생하는 callback에서 우리가 요구하는 출력물을 PL에서 다시 PC로 전송할 수 있게 되었다.

 

 

다음 그림이 그 출력물이다.

스위치를 내렸을 때에는 nothing을 전송하고, 올렸을 때는 전송된 데이터에 대한 홀/짝을 전송한다.

728x90
반응형