トップレベル記述の書き方がわかったところで、いよいよブロックRAMを使ってみましょう。
今回は tutorial4_1.chc
を使って、RAMへの書き込みと検証を行います。
process writeRAM(clkin uint#1 clk, rstin uint#1 rst, ram uint#9 r0[2048], out uint#1 latch sy)
{
sy = 0;
uint#9 seed = 0b101010101;
uint#11 i = 0;
do {
seed = (seed << 1) ^ (seed >> 3) ^ i;
r0[i] = seed#(8..0);
} while (++i != 0);
sy = 1;
while (true);
}
process readRAM(clkin uint#1 clk, rstin uint#1 rst, ram uint#9 r0[2048], in uint#1 sy, out uint#5 latch leds, out uint#1 latch led)
{
led = 0;
leds = 0b00000;
while (~sy) ;
uint#9 seed = 0b101010101;
uint#11 i = 0;
do {
seed = (seed << 1) ^ (seed >> 3) ^ i;
if (r0[i] != seed#(8..0)) leds = 0b11111;
} while (++i != 0);
led = 1;
while (true);
}
toplevel logicboy(
in uint#1 pin<52> period<37> clk,
in uint#1 pin<3> iostandard<LVCMOS18> pullup rst,
out uint#5 pin<10,11,13,14,15> leds,
out uint#1 pin<16> led)
{
com uint#1 sy;
com uint#5 ls;
com uint#1 l;
leds = ~ls;
led = ~l;
ram uint#9 port_num<2> clock<clk,clk> r0[2048];
writeRAM(clk, rst, r0 port<0>, sy);
readRAM(clk, rst, r0 port<1>, sy, ls, l);
}
ram uint#9 port_num<2> clock<clk,clk> r0[2048];
がRAMの宣言部分uint#9
は9ビット幅の unsigned 型port_num<2>
はデュアルポートRAMであることを示すclock<clk,clk>
は両ポートとも clk
を使用r0[2048]
はRAMの名前とサイズTang Nano 9K では、以下のようなブロックRAMが使えます:
合計で最大26個まで使用できます。
writeRAM
が疑似乱数を生成し、RAMに全アドレス分を書き込みsy
シグナルが1になり、readRAM
が検証を開始トップレベルでの writeRAM
と readRAM
の呼び出しでは、
r0 port<0>
→ RAMのポート0を使用r0 port<1>
→ RAMのポート1を使用それぞれのプロセスに、RAMの異なるポートを割り当てることで並列動作が可能になります。
CHERRY SYN によって生成される回路では、RAM は回路のクロックとは 逆のエッジ で動作します。
これは高位合成において制御を簡潔にするための設計方針です。
シングルポートRAMの記述はここでは扱いませんが、single_port_ram_test.chc
という例題があるので参考にしてください。
これでブロックRAMが使えるようになりました。
データの保存、検証、並列処理など、かなり面白いことができるはずです。
次回は、RAMの応用や、より複雑な構造にも挑戦してみましょう。