VHDLでCORDICを書いていますが、下位のエンティティのテスト・ベクターを作るC++プログラムがようやく軌道に乗りました。
テスト・ベクターを安定して記述できるようになり、diffの結果としてテストを見ることが出来るようになったため、VHDLで書いたコードのリファクタリングを行っています。
何しろ素人ですので、書き始めは冗長で柔軟性の低いコードから始めています。それをテストしながらリファクタリングで柔軟性を高めていく目論見です。ところが、柔軟性を高めていくと、あれっと?思うような場面に出くわします。
たとえば、以下のようなコードがコンパイル・エラーになります。q_nextはnumeric_std.signed型です。
q_next <= ( others => '0' );
これがエラーになるのは、どうやらポート宣言で
signal q_qnext : out signed;
としているのが原因のようです。ワード幅を与えるタイミングをポートマッピング時点まで遅らせることで、エンティティ自体にワード幅をハードコードしない設計を狙ったわけですが、その結果、上のようなエラーになりました。
結局以下のように書くことで問題を解決しました。
q_next <= ( q_next'range => '0' );
納得がいきません。q_next’rangeの値をコンパイル時に決定できるのであれば、最初の記述でもその値を使ってコンパイルしてくれれば良いのです。実際、q_nextを
signal q_qnext : out signed( 7 downto 0 );
のように宣言すれば、コンパイルは通るのです。不平を言っても仕方ないのでVHDLの言語標準であるIEEE 1076-2008を調べてみたところ、”9.3.3.3 Array Aggregates”に以下のような記述を見つけました。これはArray Aggregateにotherを含んでも良い条件です。
As an actual associated with a formal parameter, formal generic, or formal port (or member thereof),where either the formal (or the member) is declared to be of a fully constrained array subtype, or theformal designator is a slice name
うーむ。この場合はq_nextはformal portに当たるわけですので、Array Aggregateにotherを入れたければ、代入先をfully constrained array subtypeとして(つまり明示的にビットベクトル幅を)宣言しなければならないということになります。
言い換えるとout signed( 7 downto 0 );のように宣言されていれば、othersを使ってベクトル型定数を記述出来るのですが、out signed; として宣言しているので、othersは使えないということです。
VHDLは難しいです。