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を疑いましょう。
**シミュレーション開始時の最初のクロックエッジでの報告は、シミュレータの過渡状態によるものですので、無視して構いません。