대학원/대회 준비 관련

[ZCU-104]이미지 파일 전송해서 BRAM에 저장

오비루 2024. 3. 23. 16:42
728x90
728x90

본 내용은 공부를 하면서 Notion에 작성했던 기록들을 나열한 것 임을 감안하고 봐주면 감사하겠습니다.

 

" 51x51x3 channel 이미지 기준 0.007초 정도 (송신(저장) + 다시 읽기) 소모됨"

 

현재 대략적으로 구상중인 구조는 이러하다.

이후 Bram에 해당 데이터를 저장 후 PS영역으로 넘겨주어 데이터가 제대로 저장되었는지 확인할 것이다.

 

입력으로 넣을 이미지이며 size 는 51 x 51이다.

(이상하게 BRAM 크기가 부족하다는 오류 발생으로 임의적으로 크기를 줄임)

 

 

오류 발생1

 

모든 indx에 동일한 데이터가 들어가고, BRAM에는 데이터가 저장되지 않고있음.

일단은 index별로 제대로 데이터가 들어가도록 수정이 필요함.

https://support.xilinx.com/s/question/0D52E00006iHoaVSAS/how-to-get-the-data-stored-in-bram-of-zynq-ultrascale-through-ethernetrj45-in-vivado-and-sdk-using-lwip-echo-server?language=en_US

 

How to get the data stored in BRAM of Zynq Ultrascale+ through Ethernet(RJ45) in Vivado and SDK using LWIP Echo Server

 

support.xilinx.com

https://blog.naver.com/kim1417/221316624071

 

PBUF 구조체

Packet Buffer StructureLwIP는 pbuf라는 데이터 구조체를 사용하여 패킷 버퍼를 관리합니다. pbuf ...

blog.naver.com

아무래도 recv_callback에 대해서 조금 알아봐야 데이터 송수신에 있어서 정확한 전달이 될 듯..


pbuf = chain 형태로 함께 링크 가능하며, 이는 packet들을 여러개의 pbuf에 걸쳐서 있게 된다.

 

데이터는 결국 payload에

이걸 보면 tot_len이 2^16인데, 이게 65536임.

이래서 최대 buff size가 65536이라고 한 듯.

수신된 패킷의 크기에 따라서 pbufs의 개수를 다르게 할당? (동적 할당)

320x100

pbuf의 array당 size는 8bit 같은데… 16bit를 사용하려면 배열 2개를 사용해야하는건가 그럼??

이건 너무 비 효율적이지 않나? 아닌가..

배열 size는 늘릴 수 있는게 아닌건가? 8말고 16으로 늘릴 수 있으면 상관 없을 듯 한데

 

 


 

일단 0~99 값을 10씩 나눠가면서 BRAM에 저장하도록 해보자.


다시 확인해보니 Header 부분을 추가하고 나서부터는 올바르게 작성중이긴 했음.

 

다만, Bram에 동일한 데이터가 저장되지는 않고 있어서 문제..

 

 

데이터 보내지는 순서도 뒤로 갈 수록 자기 멋 대로 보내짐.

저장되는 주소만 같다면 상관이 없으려나?

baseaddress = cpy_buf * BUF_SIZE 로 정하면 초기 주소는 상관 없긴 할 듯

 

 

문제 발생 2

 

아무래도 데이터 전송하는 속도가 너무 빨라서 데이터를 보내고, PS영역에서 잘 받았다는 신호를 PC로 보내는 것이 필요하겠다고 판단했음.


따라서 하단의 코드처럼 조건식을 하나 추가함

 

 

0~99에 대한 데이터를 송신하는 것으로 바꿔서 해봄.

써지는건 뭐 잘 써진다고 쳐도, BRAM에 데이터가 저장되어 있지 않으면서도 frame_buf 숫자도 이상하고, 10개 전부 도착하지도 않음.

일단 BRAM 저장부터 확인해 볼 계획 (ILA)

아직 불확실하지만 데이터가 겹쳐서 보내지나?

이걸 해결하기 위해서 전송(send) 데이터가 전부 보내지면, 수신(recv)에서 완료 되었음을 알리는 신호를 전달한다.

 

하단은 내가 데이터 송 수신에서 사용한 코드이다.

728x90
from socket import socket, AF_INET, SOCK_STREAM
import time

FPGA_IP = "192.168.1.10"  # FPGA의 IP 주소
FPGA_PORT = 7  
CHUNK_SIZE = 1024  # 청크 크기 설정
received_data = 1

def send_bmp_file(filename, sock):
    try:
        chunk_number = 0                                                            # For frame_number checking
        global received_data                                                        # Global로 선언해야 수신받은 값을 사용 가능
        with open(filename, "rb") as file:                                          # BMP 파일 열기
            start_time = time.time()  # 송신 시작 시간 기록
            while True:                             
                if (received_data == 1 or chunk_number == 0):                       # 받은 데이터가 '1'이면
                    received_data = 0
                    bmp_chunk = file.read(CHUNK_SIZE)                               # 청크 단위로 파일을 읽음
                    if not bmp_chunk:                                               # 파일 끝에 도달하면 전송 중단
                        break           
                    header = chunk_number.to_bytes(2, byteorder='big')              # 청크 번호를 2바이트 헤더로 변환
                    sock.sendall(header + bmp_chunk)                                # send data (frame number (0,1 번지), 나머지는 데이터)
                    chunk_number += 1                                               # 다음 청크 번호 증가
                    received_data = sock.recv(1)                                    # 1바이트 데이터 수신
                    received_data = int.from_bytes(received_data, byteorder='big')  # 0x01로 되어있는 byte 표현 숫자로 바꿔주기
                    #print("Sent chunk number:", chunk_number)
                    #print("received_data:", received_data)
            end_time = time.time()  # 송신 종료 시간 기록
            print("BMP 파일을 전송했습니다.")
            elapsed_time = end_time - start_time  # 소요된 전체 시간 계산
            print("전송에 걸린 시간:", elapsed_time, "초")  # 전송에 걸린 시간 출력
    except FileNotFoundError:
        print(f"파일 '{filename}'을 찾을 수 없습니다.")

def receive_bmp_file(filename, sock):
    try:
        with open(filename, "wb") as file:                                          # BMP 파일 열기
            while True:
                received_data = sock.recv(CHUNK_SIZE)                               # 최대 CHUNK_SIZE 바이트 데이터 수신
                if not received_data:                                               # 수신된 데이터가 없으면 수신 중단
                    break
                file.write(received_data)                                           # 수신된 데이터를 파일에 씀
        print("BMP 파일을 수신했습니다.")
    except:
        print("데이터를 수신하지 못했습니다.")

s = socket(AF_INET, SOCK_STREAM)                                                    # 소켓 생성
s.connect((FPGA_IP, FPGA_PORT))                                                     # TCP 서버가 수신 대기 중인 주소에 연결

# BMP 파일을 전송
send_bmp_file("picture.bmp", s)

# 데이터 받기
# receive_bmp_file("received_image.bmp", s)

s.close()  # 소켓 닫기

 

 

 

데이터는 확실히 잘 전송되긴 하는데, 왜 write가 안 되는거지?

자료형을 int로 바꿔줬는데도 안 되네

write가 문제?? 아니면 read가 문제???

ILA로 확인

데이터 전송은 문제 없이 잘 이루어짐.

이러면 읽는게 문제인건데..??

언뜻봐도 읽는 부분에서 문제가 있는게 보임.

이러면 BRAM에 내용은 제대로 적혀있는지부터 확인해봐야 할 듯 한데.. 어떻게 확인하지?

test bench를 이용하는 방법밖에 없을듯한데?

그냥 한 번 mem0_data_width를 24에서 32bit로 바꿔봄

→ 내가 맛비 코드에서 변경한 사항이 이게 전부였기 때문에..

다시 처음부터 보니 top module에 wire 선언을 해두지 않았다;;;

그리고 ram 크기가 작아서 ultra로 변경해줌.

[DRC UTLZ-1] Resource utilization: RAMB18 and RAMB36/FIFO over-utilized in Top Level Design (This design requires more RAMB18 and RAMB36/FIFO cells than are available in the target device. This design requires 710 of such cell types but only 624 compatible sites are available in the target device. Please analyze your synthesis results and constraints to ensure the design is mapped to Xilinx primitives as expected. If so, please consider targeting a larger device.)

그래도 계속 이런 오류가 발생해서, Ultrascale Memory에 대한 User Guide를 읽어보자.

모르겠다. 보다보면 끝도 없을듯해서, 일단은 데이터 송 수신이 잘 되는지 확인하기 위해서 이미지 크기를 51x51로 대폭 줄여서 우선은 확인하자.

데이터가 하나 씩 밀려서 저장되는 중인데??


마지막 줄에 delay를 하나 주지 않았었다. (verilog 내의..)

휴먼 에러였음..

 

읽기도 정상 동작이 되는 것을 확인 했음.

여기까지 하면 이제 BRAM에 데이터 저장이 가능함을 확인한 것이니 DMA & DRAM 사용 방법을 공부 시작하면 될 듯.

728x90
반응형