2017年7月16日日曜日

vivado case文の不具合?

vivado2017.1でcase文を使ったら、意図しない回路を生成してくれやがったのでメモ。

module graycounter_3bit(
  input CLK, RST,
  output [2:0] GOUT
);
reg [2:0] gc3;
always @ (posedge CLK or posedge RST) begin
  if (RST) gc3 <= 0;
  else
    case (gc3)
      3'b000 : gc3[2:0] <= 3'b001;
      3'b001 : gc3[2:0] <= 3'b011;
      3'b010 : gc3[2:0] <= 3'b110;
      3'b011 : gc3[2:0] <= 3'b010;
      3'b100 : gc3[2:0] <= 3'b000;
      3'b101 : gc3[2:0] <= 3'b100;
      3'b110 : gc3[2:0] <= 3'b111;
      3'b111 : gc3[2:0] <= 3'b101;
      default : gc3[2:0] <= 3'bxxx;
    endcase
  end
  assign GOUT[2:0] = gc3[2:0];
endmocule

上のような3ビットのグレイコードカウンタを記述したところ、
下のような8bitのレジスタ+LUTの回路を生成しやがりました。

出力はちゃんとグレイコードしてますが、せっかくグレイコードカウンタを記述してるのに回路面積を増やしてくれやがるのはダメですね。ちゃんとレジ止めしてるのに出力段にLUTを生成してくれやがるので、ゲートシムするとヒゲが出ます。一番ダメなのは、3bitのレジを作ったつもりが8bitになってるあたり。

というわけでマニュアルオプティマイズをした3bitグレイコードカウンタを作成し、コンパイルしてみました。

module graycounter_3bit(
  input CLK, RST,
  output [2:0] GOUT
);
reg [2:0] gc3;
always @ (posedge CLK or posedge RST) begin
  if (RST) gc3 <= 0;
  else begin
            gc3[0] <= (!gc3[2] && !gc3[1]) || (gc3[2] && gc3[1]);
            gc3[1] <= (!gc3[2] && gc3[0]) || (gc3[1] && !gc3[0]);
            gc3[2] <= (gc3[1] && !gc3[0]) || (gc3[2] && gc3[0]);
    end
  end
endmodule


こちらで合成すれば、ちゃんと意図した回路を生成してくれます。

case文を使った箇所を一度見直す必要がありそうです orz

追記 4bitグレイコードカウンタ
加法標準形を書き出しただけですが、オプティマイズされた回路が出力されるようです。
ZYNQのLUTが6bitなので、6bitまでなら、このやり方で最適な回路が生成されるかと思われます。

 reg [3:0] gc4;
 always @ (posedge CLK or posedge nRST) begin
    if (nRST) gc4 <= 0;
    else begin
      gc4[0] <= (gc4 == 4'b0000) || (gc4 == 4'b0001) || (gc4 == 4'b0110) || (gc4 == 4'b0111) || (gc4 == 4'b1100) || (gc4 == 4'b1101) || (gc4 == 4'b1010) || (gc4 == 4'b1011);
      gc4[1] <= (gc4 == 4'b0001) || (gc4 == 4'b0011) || (gc4 == 4'b0010) || (gc4 == 4'b0110) || (gc4 == 4'b1101) || (gc4 == 4'b1111) || (gc4 == 4'b1110) || (gc4 == 4'b1010);
      gc4[2] <= (gc4 == 4'b0010) || (gc4 == 4'b0110) || (gc4 == 4'b0111) || (gc4 == 4'b0101) || (gc4 == 4'b0100) || (gc4 == 4'b1100) || (gc4 == 4'b1101) || (gc4 == 4'b1111);
      gc4[3] <= (gc4 == 4'b0100) || (gc4 == 4'b1100) || (gc4 == 4'b1101) || (gc4 == 4'b1111) || (gc4 == 4'b1110) || (gc4 == 4'b1010) || (gc4 == 4'b1011) || (gc4 == 4'b1001);
   end
  end
assign GOUT = gc4;

0 件のコメント:

コメントを投稿