INIT_RAM_XX のビット配置Gowin 社の FPGA が持つ BSRAM には、初期値を指定するためのパラメタとして INIT_RAM_XX があります。ここに 8 ビット単位ではないビット幅の初期値を指定するときのビット表現を調べました。
例えば、次のように初期値を指定できます。
defparam sdpx9b_inst_0.INIT_RAM_00 = 288'h0003C000000000000000000000000001BEEF00000000000000000000000000072003DEAD;
defparam sdpx9b_inst_0.INIT_RAM_01 = 288'h0007C00000000000000000000000000000180005C0000000000000000000000000440010;
...
defparam sdpx9b_inst_0.INIT_RAM_0F = 288'h32BF80000000000000000000000000000000000000000000000000000000000000000000;
288 ビットの中のどこが、RAM のどのアドレスに対応するのか、ということを調べました。何故そんなことを調べたかというと、defparam の行を自動生成したかったからです。自動生成するために、どこにどんな値を書けばいいかを知る必要がありました。
調査のために、Gowin EDA の IP Core Generator を用いて、1 ワードあたり 18 ビット、合計 256 ワードのセミ・デュアル・ポート(SDP)RAM を作ってみます。初期値として指定する Memory Initialization File に記述した内容は次の通りです。
| ワードアドレス | ワード値 |
|---|---|
| 00 | 3DEAD |
| 01 | 1C800 |
| ... | |
| 08 | 1BEEF |
| ... | |
| 0F | 0000F |
| 10 | 00010 |
| 11 | 00011 |
| ... | |
| 17 | 00017 |
| 18 | 00018 |
| ... | |
| 1F | 0001F |
| ... | |
| FF | 0CAFE |
省略「...」したところに書かれている値はすべて 0 です。
defparam 行18 ビット×256 ワードですから、計 4608 ビットです。これを 288 ビット毎に分けると 16 行になります。だから defparam は 16 行生成されました。
defparam sdpx9b_inst_0.INIT_RAM_00 = 288'h0003C000000000000000000000000001BEEF00000000000000000000000000072003DEAD;
defparam sdpx9b_inst_0.INIT_RAM_01 = 288'h0007C00000000000000000000000000000180005C0000000000000000000000000440010;
defparam sdpx9b_inst_0.INIT_RAM_02 = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_03 = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_04 = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_05 = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_06 = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_07 = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_08 = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_09 = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_0A = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_0B = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_0C = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_0D = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_0E = 288'h000000000000000000000000000000000000000000000000000000000000000000000000;
defparam sdpx9b_inst_0.INIT_RAM_0F = 288'h32BF80000000000000000000000000000000000000000000000000000000000000000000;
まず 1 行目 288'h0003C000000000000000000000000001BEEF00000000000000000000000000072003DEAD; に注目します。
最下位にある「3DEAD」は分かりやすいです。しかし、その次の「07200」は謎です。アドレス 1 には「1C800」があるはずなのに、「07200」って何でしょうか。
その謎を解くためにいったん 2 進数で表してみます。下 9 桁 72003DEAD を 2 進数で表すと 0111 0010 0000 0000 0011 1101 1110 1010 1101 となります。
これをちょうど半分に分けます。
0111 0010 0000 0000 0011 1101 1110 1010 1101ワード 1 のビットの区切りを修正すると 01 1100 1000 0000 0000 となります。つまり 1C800 です!
とまあこんな風に 2 ワード 9 桁をひとかたまりとして取り出し、整理すると、次のようになります。
| ワード | 16進値 | 下位ワード | 上位ワード |
|---|---|---|---|
| 0,1 | 72003DEAD |
3DEAD | 1C800 |
| 8,9 | 00001BEEF |
1BEEF | 00000 |
| 14,15 | 0003C0000 |
00000 | 0000F |
ここまでの調査で答えが出ました。INIT_RAM_XX には、下位ビットから隙間無くデータが詰め込まれているようです。
2 進数で表せば、2 ワード分は bbbb bbbb bbbb bbbb bbaa aaaa aaaa aaaa aaaa と詰め込まれます。上位ワードを b、下位ワードを a で書いています。