ISE 12.4で構文チェックに合格するモジュールを取得しようとしていますが、理解できないエラーが表示されます。最初のコードスニペット:
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
generate
always @(posedge sysclk) begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0;
end
end
endgenerate
構文チェックを試みると、次のエラーメッセージが表示されます。
エラー:HDLCompiler:731-"test.v"行46:非レジスタ<c>への手続き型の割り当ては許可されていません。
私はそれが不平を言っている理由を本当に理解していません。 「c」はワイヤーではなく、genvarです。これは、完全に正当な構文と同等でなければなりません。
reg [3:0] temp;
always @(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
生成せずにこれを記述する方が簡単だというコメントはありません。これは、複数のifと「temp」への非ブロッキング割り当てを含む、はるかに複雑なコードの簡単な例です。また、ISEの新しいバージョンがあることだけを教えてはいけません。すでに知っています。 OTOH、know ISEの以降のバージョンで修正された場合、どのバージョンが機能するかをお知らせください。
Generateブロック内のネストを逆にする必要があります。
genvar c;
generate
for (c = 0; c < ROWBITS; c = c + 1) begin: test
always @(posedge sysclk) begin
temp[c] <= 1'b0;
end
end
endgenerate
技術的には、これにより4つのalwaysブロックが生成されます。
always @(posedge sysclk) temp[0] <= 1'b0;
always @(posedge sysclk) temp[1] <= 1'b0;
always @(posedge sysclk) temp[2] <= 1'b0;
always @(posedge sysclk) temp[3] <= 1'b0;
この単純な例では、4つのalwaysブロックと4つの割り当てを含む1つのalwaysブロックの間に動作の違いはありませんが、他の場合には可能性があります。
Genvar依存の操作は、デザインのメモリ内表現を構築するとき(シミュレータの場合)、または論理ゲートにマッピングするとき(合成ツールの場合)に解決する必要があります。 always @posedge
は、デザインが動作するまで意味を持ちません。
一定の制限がありますが、合成可能なコードであっても、常にブロック内にforループを配置できます。合成の場合、ループは展開されます。ただし、その場合、forループはreg
、integer
、または同様のもので動作する必要があります。 genvar
を使用することはできません。これは、常にブロック内にforループがあると、デザインのエラボレーション中に静的に展開できる操作ではなく、クロックの各エッジで発生する操作を記述するためです。
同じalwaysブロックでtemp
のすべてのビットを割り当てたい場合、生成ブロックは必要ありません。
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
for (integer c=0; c<ROWBITS; c=c+1) begin: test
temp[c] <= 1'b0;
end
end
または、シミュレータがIEEE 1800(SytemVerilog)をサポートしている場合、
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
temp <= '0; // fill with 0
end
end
ファイルをコンパイル/生成する必要がない場合は、前処理技術を使用できます。これにより、生成のパワーが得られますが、多くの場合デバッグが容易になり、シミュレータの問題が少なくなるクリーンなVerilogファイルが生成されます。
RubyIt を使用して、ERB(Embedded Ruby)を使用してテンプレートからverilogファイルを生成します。
parameter ROWBITS = <%= ROWBITS %> ;
always @(posedge sysclk) begin
<% (0...ROWBITS).each do |addr| -%>
temp[<%= addr %>] <= 1'b0;
<% end -%>
end
Module_name.vファイルの生成:
$ Ruby_it --parameter ROWBITS=4 --outpath ./ --file ./module_name.rv
生成されたmodule_name.v
parameter ROWBITS = 4 ;
always @(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
モジュール内では、Verilogには基本的に2つの構成要素が含まれています:アイテムとステートメント。ステートメントは、プロシージャコンテキストで常に検出されます。これには、begin..end、関数、タスク、常にブロック、および初期ブロックの間にあるものが含まれます。 generateコンストラクトなどのアイテムは、モジュールに直接リストされます。 forループとほとんどの変数/定数宣言は、両方のコンテキストに存在できます。
コードでは、forループを生成項目として評価したいようですが、ループは実際にはalwaysブロックの手続きコンテキストの一部です。 forループを生成ループとして扱うには、モジュールコンテキスト内になければなりません。 generate..endgenerateキーワードは完全にオプションで(一部のツールでは必要です)、効果はありません。生成ループの評価方法の例については、 この回答 を参照してください。
//Compiler sees this
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
always @(posedge sysclk) //Procedural context starts here
begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0; //Still a genvar
end
end
ベリログのためだけに
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
temp <= {ROWBITS{1'b0}}; // fill with 0
end