小さいモジュールを作らない
「小さいモジュールを作らない。階層を深くしない」
ソフトウェア言語では何百行の大きな関数は作らずに小さな関数に分割すると思うが、HDLでは少し事情が異なり小さいモジュールを作ると読みにくくなる。
◇
1つ目の理由は、ソフトウェア言語の関数の入出力と違って、HDLのモジュールの入出力は変数名の示す意味だけでなくタイミングが意味をもつ(レベル信号かパルス信号か、入力から何クロック後に出力されるのか等)ので、カウンタとかマルチプレクサという小さいモジュールでさえ、入出力名だけ見ても動作がさっぱりわからないのである。なので、繰り返し出てくるからといって小さい回路をモジュール化すると、書いた本人にしか読めないRTL記述になってしまう。
× jkff(.rst(),.clk(),j(),k()); // 今どきJK-FFを知っている人はいない counter(.rst(),.clk(),ld(),in(),cnten(),.out()); // カウンタの周期が不明 mux(.rst(),.clk(),sel(),in0(),in1(),.out()); // 入出力FFの有無が不明 |
◇
2つ目の理由は、ソフトウェア言語では関数内の信号は外から隠ぺいされるが、HDLでは変数の値が変化するとどんなに遠く離れているモジュール内の変数にも伝わってしまう、つまりHDLにおける変数はモジュールを分けても所詮グローバル変数であり、HDLを読むときにはモジュールの境界をまたいで信号を追わなければならず、この境界が邪魔になるのである。
× module top(); wire top_data; sub1 sub1(.d(top_data),...); // 下位モジュールへ接続 ... endmodule
module sub1(input d,...); ... sub2 sub2(.d_in(d),...); // さらに下位モジュールへ接続 ... endmodule
module sub2(input d_in,...); ... d_reg <= d_in; // やっと使っている箇所にたどり着いた ... endmodule |
◇
ではどうすればよいかというと、1モジュールの中を機能単位に区切って見出しと目次をつければよい。500行程度の長いモジュールにしても、レイアウトが区切られていれば見た目は構造化されているので読みやすく、変数を追いかけるときもエディタで検索すれば簡単に追える。
○ module top(); /* 目次 * (1)機能○○ * (2)機能△△ * ... */ /*************************** * (1)機能○○ *************************** ... /*************************** * (2)機能△△ *************************** ... endmodule |