昨年、リリースされてすぐにヒットしたVivado 2016.4の不具合を回避するのを今年、最初のVivado作業としよう。
Vivado 2016.4でBlock RAMをwidth=16, depth=256で作成した。 そして、Synthesisを実行すると次のようにエラーが出た。
[Synth 8-549] port width mismatch for port 'addra': port width = 8, actual width = 4 ["/hoge/src/blk_mem_gen_0/synth/blk_mem_gen_0.vhd":232]
最初、エラーメッセージから自分のソースコードが間違えているんだと一生懸命、ソースコードを見なおしたけど、どこにも問題が見つからない。 もう一度、エラーメッセージを見なおしてみると・・・
をいをい、depth=256で作成しているのにVivadoのBlock RAM Generatorがアドレス幅を4bitで生成してるではないか!
さらに、エラー解析をしようと思ってvivado.logを見ると、次のようにrunme.logにSynthesisのログを出力したとログが出ているのだが実際にはVivadoの実行が完了した時点で削除されてしまっているみたいだ。 ログを見たいのに見れないというのはいかがなものか?
synth_1: /hoge.../synth_1/runme.log
非常にふざけていているよね。
去年のVivadoを見ているとVivado 2016.3から急激にデグレマーチしているような気がする。
この不具合、使用中のプロジェクトで再度、Block RAM Generatorで生成しても同じなので回避することができなくなった。 不具合が発生したプロジェクトはVivado 2016.3からのアップデートしているのだがVivado 2016.4で新規生成プロジェクトだと発生しない。 とにかく、Vivado 2016.3からプロジェクトのアップデートはかなり鬼門になっている気配がある。
具体的な回避策が見つからないのでFFになってもいいから、RTLで書いてしまって推論に任せてみることにした。 ソースコードは次のようになっている。
module mainreg
(
input A_CLK,
input A_WE,
input [7:0] A_ADDR,
input [7:0] A_WDATA,
output [7:0] A_RDATA,
input B_CLK,
input B_WE,
input [7:0] B_ADDR,
input [7:0] B_WDATA,
output [7:0] B_RDATA
);
reg [7:0] ram[0:255];
reg [7:0] a_reg, b_reg;
always @(posedge A_CLK) begin
if(A_WE) begin
ram[A_ADDR] <= A_WDATA;
end
a_reg <= ram[A_ADDR];
end
assign A_RDATA = a_reg;
always @(posedge B_CLK) begin
if(B_WE) begin
ram[B_ADDR] <= B_WDATA;
end
b_reg <= ram[B_ADDR];
end
assign B_RDATA = b_reg;
endmodule
Synthesisを実行すると、次のようにRAMB18E1に割り振られることが判明した。 今まで1Read/1Write×2は推論できなくてFFになるものだと思ってた。 どこかのバージョンでちゃんとBlockRAMに推論してくれるようになっていたんだ。
Report Cell Usage:
+------+---------+------+
| |Cell |Count |
+------+---------+------+
|1 |BUFG | 2|
|2 |RAMB18E1 | 1|
|3 |IBUF | 36|
|4 |OBUF | 16|
+------+---------+------+
RTLベースで解決できることがわかったので不具合の回避策はこれで進めることにした。
1Read/1Write×2が推論で1個のBlock RAMになるのはこの点はすごく評価できる。
ちょっと、幸先良い2017年スタートとなりました。
ここまでは良かったんだけど、Vivado 2016.2のプロジェクトをVivado 2016.4にアップデートしてインプリメントを行ったら"CARRY4が・・・CARRY8で・・・"って、エラーでインプリメントできなかった。 やはり、プロジェクトのアップデートは危険だなぁ。