하시설 보고서 - sangmoon/snu GitHub Wiki
-
Shifter IP verilog
IP structure ip 구조는
axi part
와user logic part
로 나눌 수 있다.axi part
에서는 interface를 구현하여 bram과 통신이 가능하게 한다.user logic part
에서는 shifter를 위한 logic을 구현 한다.IP interface user interface와 axi interface로 나눌 수 있다.
- user interface
output wire [BRAM_ADDR_WIDTH-1:0] BRAM_ADDR,//READ,WRITE를 할 BRAM 주소 output wire BRAM_CLK,//BRAM clock output wire [BRAM_DATA_WIDTH-1:0] BRAM_WRDATA,//WRITE 할 data input wire [BRAM_DATA_WIDTH-1:0] BRAM_RDDATA, // READ 해온 data output wire BRAM_EN, // BRAM enable output wire BRAM_RST, //BRAM reset output wire [BRAM_WE_WIDTH-1:0] BRAM_WE, //write enable
- axi interface
AXI protocol
에 맞는 interface이다.AXI4-LITE
형태이다.AXI4-LITE
는 simple, low-throughput memory-mapped communication 을 위한 간단한 protocol이다. read addr, read data, write addr, write data, write response가 있다.
input wire S_AXI_ACLK, // Global Clock Signal input wire S_AXI_ARESETN, // Global Reset Signal. This Signal is Active LOW /* WRITE 관련 wire 들 */ input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, // Write address . input wire [2 : 0] S_AXI_AWPROT, // Write channel Protection type. input wire S_AXI_AWVALID,// Write address valid. output wire S_AXI_AWREADY, // Write address ready. input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, // Write data . input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,// Write strobes. input wire S_AXI_WVALID,// Write valid. output wire S_AXI_WREADY,//Write ready. output wire [1 : 0] S_AXI_BRESP, // Write response. output wire S_AXI_BVALID,// Write response valid. input wire S_AXI_BREADY,// Response ready. /* READ 관련 wire 들 */ input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, // Read address input wire [2 : 0] S_AXI_ARPROT, // Protection type. input wire S_AXI_ARVALID, // Read address valid. output wire S_AXI_ARREADY, // Read address ready. output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, // Read data output wire [1 : 0] S_AXI_RRESP, // Read response. output wire S_AXI_RVALID, // Read valid. input wire S_AXI_RREADY // Read ready.
IP core
- 우선 읽어온 값을 2배로 하는 부분은 아래 부분이다. bitwise shift연산을 사용한다.
assign BRAM_WRDATA = BRAM_RDDATA << 1; // 읽어온 READ_RDDATA를 2배해서 BRAM_WRDATA에 할당.
- IP init을 담당하는
magic_code
이다. c code에서 h5555를 할당하면, logic이 시작한다.
wire magic_code = (slv_reg0 == 32'h5555);
- STATE 관리 영역이다. IDLE -> repeat {READ->WAIT->WRITE} -> IDLE 로 표현할 수 있다.
always @( posedge S_AXI_ACLK ) begin if ( S_AXI_ARESETN == 1'b0 ) bram_state <= BRAM_IDLE; else case (bram_state) BRAM_IDLE: bram_state <= (magic_code)? BRAM_READ : BRAM_IDLE; BRAM_READ: bram_state <= BRAM_WAIT; BRAM_WAIT: bram_state <= BRAM_WRITE; BRAM_WRITE: bram_state <= (run_complete)? BRAM_IDLE: BRAM_READ; default : bram_state <= BRAM_IDLE; endcase end
- counting 하는 부분이다. up-counting 으로, BRAM_WRITE state일 때 1씩 더해줘서 3이 되면 run_complete flag를 1로 바꿔서 state를 바꾼다.
always @( posedge S_AXI_ACLK ) begin if ( bram_counter_reset ) bram_counter <= 2'd0; else begin if (bram_counter_enable) bram_counter <= bram_counter + 2'd1; else bram_counter <= bram_counter; end end assign run_complete = (bram_counter == 2'h3); // User logic ends
- OS, application 설명
- Makefile
all: main.c gcc main.c && sudo ./a.out # main.c 라는 dependency를 갖고 실행한다. # gcc main.c 와 sudo ./a.out를 이어서 실행한다. # main.c 를 컴파일해서 a.out이라는 default 실행 파일을 만든 후 #이를 sudo 권한으로 실행한다
-
main.c
main.c 는 메모리 맵핑, 메모리 초기화, ip 구동 크게 3부분으로 나뉜다. 메모리 맵핑 부분은 다음과 같다.
int foo = open("/dev/mem", O_RDWR); // device의 system memory를 연다 int *fpga_bram = mmap(NULL, SIZE * sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED, foo, 0x40000000); int *fpga_ip = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED, foo, 0x43C00000); // bram 과 ip에 대한 virtual addr 와 physical addr를 mapping 한다
mmap
이라는 system call을 사용한다. 이 함수는 virtual addr와 실제 addr를 연결한다.
ip의 시작 주소에 0x5555 값을 할당하면 ip가 작동한다.void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) /* return val: 맵핑되는 실제 메모리 주소 * addr: 어디에 mapping해야 좋은지 제안값 * size: 맵핑시킬 메모리 영역의 길이 * prot: 맵핑에 원하는 메모미 보호 정책 * flag: 맵핑 유형과 동작 구성 요소 * fd: file descriptor * offset: 맵핑할 때 len의 시작점 */
*(fpga_ip) = 0x5555; while (*fpga_ip == 0x5555);
- SD card file && booting process
-
SD card file SD card는 2부분으로 파티션 되어있다. 첫 부분은 zed board를 위한 부분으로
- BOOT.BIN
- u-boot.img
- zynq.bit
- devicetree.dtb
- uImage
로 구성되어 있다. 두 번째 부분은 linux file sytem으로 구성되어 있다.
-
booting process linux booting 은 BIOS -> boot loader -> kernel -> init 순으로 이루어진다. zynq linux booting은 크게 4부분으로 나뉜다.
- Boot ROM
- FSBL (BOOT.bin)
- SSBL (u-boot.img)
- Linux kernel
우선 Boot ROM 에서 uImage를 확인하고, chip memory로 BOOT.bin을 load 한다. 그리고 zynq.bit file이 있는지 체크한 후, programmable logic으로 zynq.bit를 복사해 실행한다.