4.1.2 乗算器
今度は、乗算器を設計してみましょう。
4.1.2.1 RTLシミュレーション
単に、入力A,BをFFで受けて、掛け算するだけのソースです。
論理合成ソース
//`define No_Qout
module mul (clock,reset,A,B,c256);
parameter width=6;
input clock;
input reset;
input [width-1:0] A,B;
output [width*2-1:0] c256;
`ifndef No_Qout
reg [width*2-1:0] c256;
`endif
reg [width-1:0] a,b;
always @(posedge clock) begin
if (reset) begin
a<=0;
b<=0;
end else begin
a<=A;
b<=B;
end
end
`ifdef No_Qout
assign c256=a*b;
`else
always @ (posedge clock) begin
c256<=a*b;
end
`endif
endmodule
|
テストベンチソース
ランダムな6ビット幅A,Bを発生させて入力としています。
後で、論理合成したH/WとRTLの結果を比較するためにコンペアする記述も加えています。
`timescale 1ns/1ps
//`define ENABLE_VCD
//`define No_Qout
`define CYCLE (8.648/2)
module mul_vcd_test;
reg clock=0;
reg reset=1;
parameter width=6;
reg [width-1:0] A,B,a,b;
wire [width*2-1:0] C;
reg [width*2-1:0] c,c_rtl;
integer i,j;
initial begin
reset=1;
A=0;
B=0;
#105 ;
@(posedge clock);
#1;//ensure hold time
reset=0;
for (j=0; j<256;j=j+1) begin
for (i=0; i<256;i=i+1) begin
@(posedge clock);
#1;//ensure hold time
A=$random;
B=$random;
end
end
end
initial begin
#50000 ;
$dumpflush;
$finish;
end
always @(C) c=C;
always @(posedge clock)begin
if (reset) begin
a<=0;
b<=0;
end else begin
a <=A;
b <=B;
end
end
`ifndef No_Qout
always @(posedge clock)begin
if (c_rtl !==C && !reset) $display("Compare Error c_rtl=%h C=%h time=%d",c_rtl,C,$time);
c_rtl <=a*b;
end
`else
always @(posedge clock)begin
c_rtl =a*b;
if (c_rtl !==C && !reset) $display("Compare Error c_rtl=%h C=%h time=%d",c_rtl,C,$time);
end
`endif
always #(`CYCLE) clock=~clock;
mul #(width) u1(.clock(clock),.reset(reset),.A(A),.B(B),.c256(C));
initial begin
#0;//Do $sdf_annotate first.
`ifdef ENABLE_VCD
$dumpfile("counter.vcd");
$dumpvars(1,mul_vcd_test);
`endif
end
endmodule
|
RTLシミュレーション結果です。結果を得るまでに二つのFFを通過するので2CLOCK遅れで結果が出力されています。

Quartusによる論理合成
mul.vを論理合成して、下図の遅延情報を得ました。

この回路のボトルネックは、内部FF間の遅延で、Clock Setupの115.63Mzが最大駆動可能周波数とQuartusは解析し報告しています。また、出力遅延7.536nsは、CLock Setup(8.648ns)よりも小さいので、テストベンチ上もClockSetupで駆動できる(コンペアエラーは発生しない)筈です。Clock Cycleを下記のように変更してコンペアエラーがで発生しないことを確認してみましょう。
`define CYCLE (8.648/2)
ところで、出力最大遅延7.536nsが発生している箇所は、比較的簡単に見つけることができました。(下図参照)
Clock Edgeから最後の変化がQuartasの報告通り、C[5]であること確認できました。

コンペアエラーが発生しないことが確認できました。
ところで、ゲートシミュレーション上、個々の時刻ではどれだけの余裕で動いているものでしょうか?
この様子を見るために、SDOファイルのSETUPをエディタで変更してみると様子がわかります。
エディタで
(37:37:37)=>(100:100:100)
一括置換して、再度走らせてみます。
SPEC.を100psに変更したので、SETUPエラーが発生しています。Veritakでは、SETUPエラーが発生してもxにせず、シミュレーション結果になんの影響も与えない仕様になっています。
最初の行では、時刻 664293psに、Setup Spec.100psMin.のところ、44psしかないと報告しています。それでも、37psよりは大きいので、DefaultのSpec.ではエラーにならなかった訳です。
F:\altera\mul\mul_test.v(5)::mul_vcd_test Verilogのシミュレーションの準備が完了しました。スタートは,Goボタンを押してください。 ------------- シミュレーションを開始します。-------------------- SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 664293ps <- 44ps: mul_vcd_test.u1.c256[10]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[10]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 664293ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 1658813ps <- 82ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 4521301ps <- 44ps: mul_vcd_test.u1.c256[10]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[10]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 4521301ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 5809853ps <- 44ps: mul_vcd_test.u1.c256[10]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[10]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 5809853ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 6640061ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 6968685ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 10929469ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 13688181ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 15435077ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 16611205ps <- 82ps: mul_vcd_test.u1.c256[10]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[10]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 16611205ps <- 82ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 17432765ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 19369917ps <- 82ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 22344829ps <- 88ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 26158597ps <- 88ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 27092581ps <- 82ps: mul_vcd_test.u1.c256[10]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[10]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 27092581ps <- 82ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 29142157ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 30197213ps <- 44ps: mul_vcd_test.u1.c256[11]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[11]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 30197213ps <- 44ps: mul_vcd_test.u1.c256[10]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[10]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 30197213ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 30465301ps <- 88ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 33924501ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 35524381ps <- 57ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 36233517ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 36371885ps <- 44ps: mul_vcd_test.u1.c256[11]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[11]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 36371885ps <- 44ps: mul_vcd_test.u1.c256[10]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[10]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 36371885ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 37323165ps <- 57ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 39640829ps <- 88ps: mul_vcd_test.u1.c256[10]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[10]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 39640829ps <- 88ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 41724997ps <- 95ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 42010381ps <- 95ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 42287117ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 44155085ps <- 44ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk SDF: timing check[0] SETUP[Spec.100ps] FAILS at simtime 46368973ps <- 95ps: mul_vcd_test.u1.c256[9]~reg0_I.lereg.datain ==> posedge mul_vcd_test.u1.c256[9]~reg0_I.lereg.clk Info: $finishコマンドを実行します。time=50000 ---------- シミュレーションを終了します。time=50000---------- |
以下様々なTiming Errorが発生していますが、信号自体は、c256[10],C256[9]が多いです。。恐らくこのパスがクリティカルパスなのでしょう。確かにQuartusのClockSetupのレポートをみると、8.648nsのクリティカルパスに含まれています。

しかしながら、Veritakのシミュレーションでは、最小値で44psになっており、本当の最小値の37psは発生していません。パターン数が少ないという指摘は当たっていますが、仮に全パターン遷移を行ったとしてもこのような結果は普通に起こりえます。深い論理においてQuartasの静的なTiming解析と動的なパス遅延(慣性遅延も含む)とで、最大値が一致するということはむしろまれです。ただし、動的なパス遅延が静的遅延を超えることはありません。従い、Quartasの報告する駆動周波数で、ゲートシミュレーションが動かないということは(設計上のエラーがない限り)ありません。Setup、Holdエラーの発生の原因の多くは、テストベンチとのIFにあります。
このエラーが発生したときは、まず、テストベンチのIFを疑いましょう。
**シミュレーション開始時の最初のクロックエッジでの報告は、シミュレータの過渡状態によるものですので、無視して構いません。