AXI BRAMやLMB BRAMなどのメモリの初期化に使用される.coeの規則について説明します。以下の記事のまとめです。
恐ろしさ
VivadoのcoeのValidate機能がザルなので、ある程度雑に書いても入力として認められてしまいます。しかし、誤った形式で進めるとなぜか部分的に1bit左シフトまたは右シフトしていたり、途中から0埋めになっていたり、と予期せぬトラブルに見舞われます。
基本構文
memory_initialization_radix = radix;
memory_initialization_vector =
value,
value,
value;
具体例
正しい記述
memory_initialization_radix = 2;
memory_initialization_vector =
00000000000000000000000000000000,
00000000000000000000000000000001,
00000000000000000000000000000010;
誤った記述 (全てvaliate通ります)
memory_initialization_radix = 2;
memory_initialization_vector =
00000000000000000000000000000000,
00000000000000000000000000000001,
00000000000000000000000000000010,
memory_initialization_radix = 2;
memory_initialization_vector =
00000000000000000000000000000000
00000000000000000000000000000001
00000000000000000000000000000010
memory_initialization_radix = 2;
memory_initialization_vector =
00000000000000000000000000000000
00000000000000000000000000000001
00000000000000000000000000000010;
まとめ
,と;の扱いが最重要です。規則通りにファイルを用意してValidate, Saveを行えば問題なく初期化されます。
また、なぜか.coeのうち特定行が初期化に使われなかったりするので場合に応じて適切な.coeを用意しましょう。
おまけ
適当な`.coe`を作成する`c`
#include<stdio.h>
#define N 1
void fprint_bin32(FILE *fp, unsigned int v) {
for (int i = 31; i >= 0; i--) {
fputc((v & (1 << i)) ? '1' : '0', fp);
}
}
int main(void){
char *outputs[N] = {"output.coe"};
for(int i=0; i<N; i++){
char *output_all = outputs[i];
FILE *fp_output_all = fopen(output_all, "w");
fprintf(fp_output_all, "memory_initialization_radix = 2;\nmemory_initialization_vector = \n");
unsigned int counter = 0;
while(1){
if(counter++ = 100)break;
fprint_bin32(fp_output_all, counter);fputc(',', fp_output_all);fputc('\n', fp_output_all);
fprint_bin32(fp_output_all, 0);fputc(',', fp_output_all);fputc('\n', fp_output_all);
fprint_bin32(fp_output_all, 0);fputc(',', fp_output_all);fputc('\n', fp_output_all);
fprint_bin32(fp_output_all, 0);fputc(',', fp_output_all);fputc('\n', fp_output_all);
}
fprint_bin32(fp_output_all, 0);fputc(';', fp_output_all);fputc('\n', fp_output_all);
int chk = fclose(fp_output_all);
if(chk != 0){
return 1;
}
}
return 0;
}