Schematic을 통해 Register에 대해 관찰하는 작업은 수행했으니 / C 코드 상에서 과거 버전 이슈 해결에 이용했던 CMake 라던가, BASE_ADDR 포인터라던가 이 부분을 조금 더 자세히 파보도록 하자.
내가 지금 궁금한것은 그래서 내가 사용하는 BRAM의 첫번지와 마지막번지가 어딘가? 라는 점은 잊지 말자.
(사실 첫번지 = BASE_ADDR 일 것 같고, BASE_ADDR + 36K 처럼 하면 마지막번지일 것 같기는 하다. 다만, 디테일의 영역일듯)
=====
지금 이 코드에서
이 변수가 어디서 온 얘인지를 판다.
XPAR_LAB01_0_BASEADDR
//////////////////////////////////////////////////////////////////////////////////
// Company: Personal
// Engineer: Matbi / Austin
//
// Create Date:
// Design Name:
// Project Name:
// Target Devices:
// Tool Versions:
// Description: test read and write in bram using AXI4-Lite
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "xparameters.h"
#include "xil_io.h"
#include "xtime_l.h" // To measure of processing time
#include <stdlib.h> // To generate rand value
#define WRITE 1
#define READ 2
#define AXI_DATA_BYTE 4
#define IDLE 1
#define RUN 1 << 1
#define DONE 1 << 2
#define CTRL_REG 0
#define STATUS_REG 1
#define MEM0_ADDR_REG 2
#define MEM0_DATA_REG 3
//#define FSM_COUNTER // (lab10)
#define MEM_DEPTH 4
int main() {
int data;
int read_data;
int reg_num;
XTime tStart, tEnd;
int i;
int write_buf[MEM_DEPTH];
int read_buf[MEM_DEPTH];
while (1) {
printf("======= Hello Lab13 Matbi ======\n");
printf("plz input run mode\n");
printf("1. write (CTRL) \n");
printf("2. read (REG) \n");
scanf("%d",&data);
if(data == WRITE){
#ifdef FSM_COUNTER
Xil_Out32((XPAR_LAB01_0_BASEADDR) + (CTRL_REG*AXI_DATA_BYTE), (u32)(0x00000000)); // Clear
printf("plz input Value 31bit. MSB is the run signal\n");
scanf("%d",&data);
printf("Test SW uSleep\n");
XTime_GetTime(&tStart);
usleep(data/100);
XTime_GetTime(&tEnd);
printf("Output took %llu clock cycles.\n", 2*(tEnd - tStart));
printf("Output took %.2f us.\n",
1.0 * (tEnd - tStart) / (COUNTS_PER_SECOND/1000000));
// check IDLE
do{
read_data = Xil_In32((XPAR_LAB01_0_BASEADDR) + (STATUS_REG*AXI_DATA_BYTE));
} while( (read_data & IDLE) != IDLE);
// start core
printf("LAB13_MATBI_0 Start\n");
Xil_Out32((XPAR_LAB01_0_BASEADDR) + (CTRL_REG*AXI_DATA_BYTE), (u32)(data | 0x80000000)); // MSB run
XTime_GetTime(&tStart);
// wait done
do{
read_data = Xil_In32((XPAR_LAB01_0_BASEADDR) + (STATUS_REG*AXI_DATA_BYTE));
} while( (read_data & DONE) != DONE );
XTime_GetTime(&tEnd);
printf("LAB13_MATBI_0 Done\n");
printf("Output took %llu clock cycles.\n", 2*(tEnd - tStart));
printf("Output took %.2f us.\n",
1.0 * (tEnd - tStart) / (COUNTS_PER_SECOND/1000000));
#endif
// (lab13 Memory Test)
Xil_Out32((XPAR_LAB01_0_BASEADDR) + (MEM0_ADDR_REG*AXI_DATA_BYTE), (u32)(0x00000000)); // Clear
printf("plz input srand value.\n");
scanf("%d",&data);
srand(data);
for(i=0; i< MEM_DEPTH ; i++){
write_buf[i] = i;
Xil_Out32((XPAR_LAB01_0_BASEADDR) + (MEM0_DATA_REG*AXI_DATA_BYTE), write_buf[i]); // Clear
}
} else if (data == READ){
#ifdef FSM_COUNTER
printf("plz input READ reg number (0~3)\n");
scanf("%d",®_num);
read_data = Xil_In32((XPAR_LAB01_0_BASEADDR) + (reg_num*AXI_DATA_BYTE));
printf("LAB13_MATBI_0 REG read done reg_number (%d), value : %d\n", reg_num, read_data & 0x7FFFFFFF); // no check run value
#endif
// (lab13 Memory Test)
Xil_Out32((XPAR_LAB01_0_BASEADDR) + (MEM0_ADDR_REG*AXI_DATA_BYTE), (u32)(0x00000000)); // Clear
for(i=0; i< MEM_DEPTH ; i++){
read_data = Xil_In32((XPAR_LAB01_0_BASEADDR) + (MEM0_DATA_REG*AXI_DATA_BYTE));
if(read_data != write_buf[i]){ // Check Read Result
printf("Matbi!! Mismatch!! plz contact me. idx : %d, Write_data : %d, Read_data : %d\n", i, write_buf[i], read_data);
}
}
printf("Matbi!! Success Test Program.\n");
} else {
// no operation, exit
//break;
}
}
return 0;
}
뻥치지마
아마 여기 있을듯하다.
찾았다~
#define XPAR_LAB01_0_BASEADDR 0x40000000
#define XPAR_LAB01_0_HIGHADDR 0x40000FFF
즉 여기(0x40000000)서부터 여기까지(0x40000FFF) 모두 저장하면 되는데
여기서 비트 바이트 및 진법 표시 관련되어 혼동되는 부분만 정리하면 된다.
-----
이 램은 36Kb의 크기를 가진다.
36Kb
0x40000000 (16=hex)
= 01000000000000000000000000000000 (2=bin)
= 1073741824 (10=dec)
0x40000FFF (16)
= 01000000000000000000111111111111 (2)
= 1073745919 (10)
1073745919 - 1073741824 = 4,095 = 2^12
111111111111 = 12bits
즉
000000000000 부터
000000000001
000000000010
...
111111111110
111111111111 까지
=====
헷갈린다.
물리적 구조와 Mapping 시키기 위하여
16x8 ram을 보자.
The internal structure of a 16x8 RAM.
https://www.researchgate.net/figure/The-internal-structure-of-a-16x8-RAM_fig20_319203501
이것도 개념은 아니다.
개념을 보자.
오키 이쪽을 보다보니
addr에 대해 decode해서 펼치는 개념을 잊었었다.
16(=2^4)*8 ram이라는 것은
이런 모양이라는 뜻이다.
0000 레지스터
0000 레지스터
0000 레지스터
0000 레지스터
0000 레지스터
0000 레지스터
0000 레지스터
0000 레지스터
=====
자 그럼 다시 돌아와서,
정보가 부족한 것 같으니
얘의 datasheet를 찾자.
RAMB18E1
이건 코드
이건 datasheet는 아닌데 그에 버금가게 작성되어있고
https://blog.csdn.net/shuchangsc/article/details/102542799
찾았다 datasheet(?! memory resource guideline)
https://docs.xilinx.com/v/u/en-US/ug473_7Series_Memory_Resources
위의 3가지 자료를 종합해본 결과
현재 분석해야 하는 핵심적인 정보는 다음과 같다.
=====
이 정보중에서 필요해보이는 것만 더 추려보면 다음과 같다.
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Austin
//
// Create Date: 2021.04.29
// Design Name:
// Module Name: dpbram_from_hls
// Project Name:
// Target Devices:
// Tool Versions:
// Description: synthesible true dpbram from vivado hls
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1 ns / 1 ps
module true_sync_dpbram (
clk,
addr0,
ce0,
we0,
q0,
d0,
addr1,
ce1,
we1,
q1,
d1
);
parameter DWIDTH = 16;
parameter AWIDTH = 12;
parameter MEM_SIZE = 3840;
input clk;
input[AWIDTH-1:0] addr0;
input ce0;
input we0;
output reg[DWIDTH-1:0] q0;
input[DWIDTH-1:0] d0;
input[AWIDTH-1:0] addr1;
input ce1;
input we1;
output reg[DWIDTH-1:0] q1;
input[DWIDTH-1:0] d1;
(* ram_style = "block" *)reg [DWIDTH-1:0] ram[0:MEM_SIZE-1];
always @(posedge clk)
begin
if (ce0) begin
if (we0)
ram[addr0] <= d0;
else
q0 <= ram[addr0];
end
end
always @(posedge clk)
begin
if (ce1) begin
if (we1)
ram[addr1] <= d1;
else
q1 <= ram[addr1];
end
end
endmodule
자 필요한 정보를 종합하는 것을 완료했다.
이 모든 자료를 장악한다는 것은 현재 불가능하고.
우리가 이해해야하는 컨셉들을 이해하기 위해 사용해보도록 하자.
여기서부터는 내일 다시 ...
'적극적 생각 > FPGA' 카테고리의 다른 글
0724 - 섹션5 - Data Mover by BRAM (1) (0) | 2022.07.24 |
---|---|
FPGA BRAM에 데이터 저장 (2) 주소문제 해결하기 (3) (0) | 2022.07.24 |
FPGA BRAM에 데이터 저장 (2) 주소문제 해결하기 (0) | 2022.07.23 |
ILA PG172 Document : Integrated Logic Analyzer v6.2 LogiCORE IP Product Guide Vivado Design Suite PG172 October 5, 2016 (0) | 2022.07.23 |
FPGA BRAM에 데이터 저장. (0) | 2022.07.23 |