不管是RISC-V, MIPS, Nios II, MicroBlaze, MSP430, 8051, OpenRISC, OpenSPARC, LEON2/LEON3等等软核处理器,在FPGA上实现的时候我们通常需要一部分片上RAM存储bootloader,可以使用gcc的objcopy把bootloader的text, exception vector, rodata, data or bss等你需要的内容copy出来,可以通过-O binary生成二进制文件,可以通过-j .section提取你要的section,当然也可以通过--gap-fill 0x00 参数指定默认各sections之间空白填充的数据。通过以下C程序可以生成符合Altera (Intel)、Xilinx和Verilog中$readmemh调用的内存初始化数据。可以根据不同处理器的大小端字节序做修改,下面的程序为小端序设计。
/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * copyright @ Lyu Yang */ #include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int i, j, FileLen = 0, address = 0, maxaddr; FILE * FileIn, * FileOut; if (argc != 3) { printf("Arguments Error! "); printf(" Usage: bin2fpga.exe Depth InputFile "); return 0; } else { FileIn = fopen(*(argv + 2), "rb"); if (FileIn == NULL){ printf("File does not exist! "); return 0; } fseek(FileIn, 0L, SEEK_END); FileLen = ftell(FileIn); maxaddr = atoi(*(argv + 1)); unsigned char * buf = (unsigned char*)malloc(sizeof(char)* FileLen); if(buf == NULL) { printf("Memory Allocate Error! "); return 0; } // For altera fpga mif file FileOut = fopen("./altera.mif", "w"); if (FileOut == NULL) { printf("Output File Create Error! "); return 0; } fprintf(FileOut, "DEPTH = %d; WIDTH = 32; ADDRESS_RADIX = DEC; DATA_RADIX = HEX; CONTENT BEGIN ", maxaddr); fseek(FileIn, 0L, SEEK_SET); fread(buf, FileLen, 1, FileIn); for (i = 0; i < FileLen; i += 4) { fprintf(FileOut, "%d: ", address); fprintf(FileOut, "%02x", buf[i + 3]); fprintf(FileOut, "%02x", buf[i + 2]); fprintf(FileOut, "%02x", buf[i + 1]); fprintf(FileOut, "%02x", buf[i + 0]); fprintf(FileOut, "; "); address++; } fprintf(FileOut, "[%d..%d]: 0; ", address, maxaddr - 1); fprintf(FileOut, " END; "); fclose(FileOut); // For xilinx fpga mif file FileOut = fopen("./xilinx.mif", "w"); if (FileOut == NULL) { printf("Output File Create Error! "); return 0; } fseek(FileIn, 0L, SEEK_SET); fread(buf, FileLen, 1, FileIn); for (i = 0; i < FileLen; i += 4) { unsigned int word = *((unsigned int*)(buf + i)); int x = 32; while(x--) fprintf(FileOut, "%c", (word >> x & 0x1) + '0'); fprintf(FileOut, " "); } fclose(FileOut); // For xilinx fpga coe file FileOut = fopen("./xilinx.coe", "w"); if (FileOut == NULL) { printf("Output File Create Error! "); return 0; } fprintf(FileOut, "MEMORY_INITIALIZATION_RADIX=16; MEMORY_INITIALIZATION_VECTOR= "); fseek(FileIn, 0L, SEEK_SET); fread(buf, FileLen, 1, FileIn); for (i = 0; i < FileLen; i += 4) { fprintf(FileOut, "%02x", buf[i + 3]); fprintf(FileOut, "%02x", buf[i + 2]); fprintf(FileOut, "%02x", buf[i + 1]); fprintf(FileOut, "%02x", buf[i + 0]); fprintf(FileOut, ", "); } fseek(FileOut, -2L, SEEK_END); fprintf(FileOut, "; "); fclose(FileOut); // Generic verilog readmemh file FileOut = fopen("./readmemh.txt", "w"); if (FileOut == NULL) { printf("Output File Create Error! "); return 0; } address = 0x0; fseek(FileIn, 0L, SEEK_SET); fread(buf, FileLen, 1, FileIn); for (i = 0; i < FileLen; i += 4) { fprintf(FileOut, "@%08x ", address); fprintf(FileOut, "%02x", buf[i + 3]); fprintf(FileOut, "%02x", buf[i + 2]); fprintf(FileOut, "%02x", buf[i + 1]); fprintf(FileOut, "%02x", buf[i + 0]); fprintf(FileOut, " "); address++; } free(buf); fclose(FileIn); fclose(FileOut); } return 0; }