ISE11.2iでのSpartan-3とSpartan-6の速度差 

@eleでぐらろさんがSpartan-6はSpratan-2Eの2倍速いと書いておられたので、私もSpartan-3とSpartan-6でやってみた。比較する回路は、DDR2 SDRAMコントローラなどは、そのFPGAに固有のプリミティブを使っていたりするのでだめ。なので、ちょっとしょぼいがキャラクタ・ディスプレイ・コントローラでやってみることにした。使用したバージョンはISE11.2i。
これは本当は50MHzのクロックを入れて、それをDCMで1/2の25MHzに落として動作する。今回はDCMを取り除いて、入力したクロックで直接動作するように変更した。この入力周波数をを200MHz、周期5nsで動作するようにUCFを書き換え、入出力パッドの制約をコメントアウトした。

#PACE: Start of Constraints generated by PACE
#PACE: Start of PACE I/O Pin Assignments
#NET "clk" LOC = "T9";
#NET "reset" LOC = "L14";
#NET "VGA_BLUE" LOC = "R11" | DRIVE = 8 | SLEW = FAST ;
#NET "VGA_GREEN" LOC = "T12" | DRIVE = 8 | SLEW = FAST ;
#NET "VGA_HSYNC" LOC = "R9" | DRIVE = 8 | SLEW = FAST ;
#NET "VGA_RED" LOC = "R12" | DRIVE = 8 | SLEW = FAST ;
#NET "VGA_VSYNC" LOC = "T10" | DRIVE = 8 | SLEW = FAST ;
#PACE: Start of PACE Area Constraints
#PACE: Start of PACE Prohibit Constraints
#PACE: End of Constraints generated by PACE
NET "clk" TNM_NET = "clk";
TIMESPEC "TS_clk" = PERIOD "clk" 5 ns HIGH 50 %;


これでSpartan-3 (xc3s200-4ft256) で、ISEの設定をデフォルトの状態でインプリメントした。
PARのタイミングレポートを下に示す。

----------------------------------------------------------------------------------------------------------
  Constraint                                |    Check    | Worst Case |  Best Case | Timing |   Timing   
                                            |             |    Slack   | Achievable | Errors |    Score   
----------------------------------------------------------------------------------------------------------
* TS_clk = PERIOD TIMEGRP "clk" 5 ns HIGH 5 | SETUP       |    -1.829ns|     6.829ns|      35|       20907
  0%                                        | HOLD        |     0.806ns|            |       0|           0
------------------------------------------------------------------------------------------------------


クリティカルパスが6.829ns、146MHzと結構、頑張っている。
使用したロジックを下に示す。
spartan3_chardisp_ISE112_090701.png

次にSpartan-6 (xc6slx9-2csg225) に変更して、同じ条件でインプリメントしてみる。

----------------------------------------------------------------------------------------------------------
  Constraint                                |    Check    | Worst Case |  Best Case | Timing |   Timing   
                                            |             |    Slack   | Achievable | Errors |    Score   
----------------------------------------------------------------------------------------------------------
* TS_clk = PERIOD TIMEGRP "clk" 5 ns HIGH 5 | SETUP       |    -0.638ns|     5.638ns|      43|       12140
  0%                                        | HOLD        |     0.776ns|            |       0|           0
------------------------------------------------------------------------------------------------------


上のように通っていないが、5.638ns、177MHz動作となった。Spartan-3よりも速い。
使用したロジックを下に示す。
spartan6_chardisp_ISE112_090701.png

まだまだ、表示しきれないほどロジックがある。ISERDESやOSERDESなども見えた。
使用したLUT数はSpartan-3は129で、Spartan-6は88だった。
Spartan-6は楽しみなFPGAだと思う。FPGA Editorで見るといろいろ入っているようだ。

2009/07/04 追加:
Virtex-4, xc4vlx15-10sf363 で同様にやると、制約5nsパス、制約4nsもパス。制約を3nsにしたら、さすがに3.615ns、277MHzとなりました。
Virtex-5, xc5vlx30-1ff324 では、3.440ns、291MHz
Virtex-6, xc6vlx75-1ff484 では、3.330ns、300MHz
でした。
さすがにVirtexシリーズは速いようです。やはり配線の数が違うのでしょうか?

 diceのVerilog版 

Sim's blogさんの”diceをverilogに書き換えてみました”でdiceのVeriog版が載っていたので、私の作った電子サイコロのVerilog版も貼ってみた。
非同期リセットのVHDL版と説明はこちら

まずはdice_top.vから

`default_nettype none
`timescale 1ns / 1ps

// 電子サイコロ Verilog2001

module dice_top(
    input wire reset_sw,
    input wire clk,
    input wire roll,
    output wire [3:0] an_n,
    output wire a_n,
    output wire b_n,
    output wire c_n,
    output wire d_n,
    output wire e_n,
    output wire f_n,
    output wire g_n,
    output wire dp_n
);
    
    wire roll_sig;
    wire roll_ena;
    wire [2:0] binary;
    
    assign an_n = 4'b1110; // AN0のみ点灯
    assign dp_n = 1'b1; // ドットの消灯
    
    reject_chatter inst_reject_chatter(
        .reset_sw(reset_sw),
        .clk(clk),
        .roll(roll),
        .roll_sig(roll_sig),
        .roll_ena(roll_ena)
    );
        
    dice_state_machine inst_dice_sm(
        .reset_sw(reset_sw),
        .clk(clk),
        .roll(roll_sig),
        .roll_ena(roll_ena),
        .spots(binary)
    );

    seven_seg_dec inst_seven_seg_dec(
        .binary(binary),
        .a_n(a_n),
        .b_n(b_n),
        .c_n(c_n),
        .d_n(d_n),
        .e_n(e_n),
        .f_n(f_n),
        .g_n(g_n)
    );
    
endmodule
`default_nettype wire


次は、reject_chatter.v。

`default_nettype none
`timescale 1ns / 1ps

// スイッチのチャタリング除去とサイコロの表示変更タイミング20msをカウントする
// Verilog2001

module reject_chatter(
    input wire reset_sw,
    input wire clk,
    input wire roll,
    output wire roll_sig,
    output reg roll_ena
);
    reg [17:0] sw_cnt;
    reg [1:0] roll_cnt;
    reg roll_node;
    
    parameter frequency_KHz = 50000; // KHz単位でのクロック周波数
    parameter divided_200Hz = frequency_KHz * 5; // 200Hzに分周するための分周比
    
    // 200Hz, 5ms
    always @(posedge clk) begin
        if (reset_sw)
            sw_cnt <= 18'd0;
        else begin
            if (sw_cnt == (divided_200Hz-1))
                sw_cnt <= 18'd0;
            else
                sw_cnt <= sw_cnt + 18'd1;
        end
    end
    
    always @(posedge clk) begin
        if (reset_sw)
            roll_node <= 1'b0;
        else
            if (sw_cnt == (divided_200Hz-1))
                roll_node <= roll;
    end
    assign roll_sig = roll_node;
    
    // 50Hz, 20ms
    always @(posedge clk) begin
        if (reset_sw) begin
            roll_cnt <= 2'd0;
            roll_ena <= 1'b0;
        end else begin
            if (sw_cnt==(divided_200Hz-1)) begin
                if (roll_cnt==2'b11) begin
                    roll_cnt <= 2'd0;
                    roll_ena <= 1'b1;
                end else begin
                    roll_cnt <= roll_cnt + 2'd1;
                    roll_ena <= 1'b0;
                end
            end else
                roll_ena <= 1'b0;
        end
    end
endmodule    
`default_nettype wire


dice_state_machine.v

`default_nettype none
`timescale 1ns / 1ps

// 1から6までのサイコロの目を表すステートマシン, Verilog2001

module dice_state_machine(
    input wire reset_sw,
    input wire clk,
    input wire roll,
    input wire roll_ena,
    output reg [2:0] spots
);

    parameter        st_one        = 6'b000001,
                    st_two        = 6'b000010,
                    st_three    = 6'b000100,
                    st_four        = 6'b001000,
                    st_five        = 6'b010000,
                    st_six        = 6'b100000;
    reg [5:0] current_state, next_state;
    
    always @(posedge clk) begin
        if (reset_sw)
            current_state <= st_one;
        else
            current_state <= next_state;
    end
            
    always @* begin
        case (current_state)
            st_one : begin
                spots <= 3'd1;
                if (roll & roll_ena)
                    next_state <= st_two;
                else
                    next_state <= st_one;
            end
            st_two : begin
                spots <= 3'd2;
                if (roll & roll_ena)
                    next_state <= st_three;
                else
                    next_state <= st_two;
            end
            st_three : begin
                spots <= 3'd3;
                if (roll & roll_ena)
                    next_state <= st_four;
                else
                    next_state <= st_three;
            end
            st_four : begin
                spots <= 3'd4;
                if (roll & roll_ena)
                    next_state <= st_five;
                else
                    next_state <= st_four;
            end
            st_five : begin
                spots <= 3'd5;
                if (roll & roll_ena)
                    next_state <= st_six;
                else
                    next_state <= st_five;
            end
            st_six : begin 
                spots <= 3'd6;
                if (roll & roll_ena)
                    next_state <= st_one;
                else
                    next_state <= st_six;
            end
            default : begin
                spots <= 3'd1;
                next_state <= st_one;
            end
        endcase
    end
    
// synthesis translate_off
    reg [20*8:1] DICE_STATE; 
    
    always @(current_state) begin
        case (current_state)
            st_one    : DICE_STATE <= "ST_ONE";
            st_two    : DICE_STATE <= "ST_TWO";
            st_three: DICE_STATE <= "ST_THREE";
            st_four    : DICE_STATE <= "ST_FOUR";
            st_five    : DICE_STATE <= "ST_FIVE";
            st_six    : DICE_STATE <= "ST_SIX";
            default    : DICE_STATE <= "ST_ONE";
        endcase
    end
// synthesis translate_on
endmodule
`default_nettype wire


seven_seg_dec.v

`default_nettype none
`timescale 1ns / 1ps

// 7セグメントLEDデコーダ、0で点灯します。

(* bram_map="yes" *)
module seven_seg_dec(
    input wire [2:0] binary,
    output reg a_n,
    output reg b_n,
    output reg c_n,
    output reg d_n,
    output reg e_n,
    output reg f_n,
    output reg g_n
);

    always @* begin
        case (binary)
            3'd1 : begin
                a_n<=1'b1; b_n<=1'b0; c_n<=1'b0; d_n<=1'b1; e_n<=1'b1; f_n<=1'b1; g_n<=1'b1;
            end
            3'd2 : begin
                a_n<=1'b0; b_n<=1'b0; c_n<=1'b1; d_n<=1'b0; e_n<=1'b0; f_n<=1'b1; g_n<=1'b0;
            end
            3'd3 : begin
                a_n<=1'b0; b_n<=1'b0; c_n<=1'b0; d_n<=1'b0; e_n<=1'b1; f_n<=1'b1; g_n<=1'b0;
            end
            3'd4 : begin
                a_n<=1'b1; b_n<=1'b0; c_n<=1'b0; d_n<=1'b1; e_n<=1'b1; f_n<=1'b0; g_n<=1'b0;
            end
            3'd5 : begin
                a_n<=1'b0; b_n<=1'b1; c_n<=1'b0; d_n<=1'b0; e_n<=1'b1; f_n<=1'b0; g_n<=1'b0;
            end
            3'd6 : begin
                a_n<=1'b0; b_n<=1'b1; c_n<=1'b0; d_n<=1'b0; e_n<=1'b0; f_n<=1'b0; g_n<=1'b0;
            end
            default : begin
                a_n<=1'b1; b_n<=1'b0; c_n<=1'b0; d_n<=1'b1; e_n<=1'b1; f_n<=1'b1; g_n<=1'b1;
            end
        endcase
    end
endmodule
`default_nettype wire


同期リセットになっているはず。。。
特徴は`default_nettype none 〜`default_nettype wireで括ってあることと、ステートマシンのステートをワンホットにしてあることだろうか?
痛い目にあったので、integerのリテラルには必ずビット幅を書くようにしている。

VHDL版非同期リセット電子サイコロとVerilog版同期リセットの電子サイコロのISE10.1iでのインプリメント結果を下に示す。
まずは、VHDL版非同期リセット電子サイコロから。
dice_VHDL_ISE101_090623.png

次は、Verilog版同期リセットの電子サイコロ。
dice_Verilog_ISE101_090623.png

VHDL版非同期リセット電子サイコロの方が、Verilog版同期リセットの電子サイコロよりもLUTの使用数が倍近く多い。

何か間違いがあったらお知らせください。

 ISE11.1iのチュートリアル1(導入編)の訂正 

Sim's blogさんの”diceを動かしてみました”で、”ISE11.1iのチュートリアル1(導入編)”のVHDL記述のバグについてご指摘をいただきました。訂正いたします。なお、すでにブログは訂正いたしました。
確かにprocess文のsensitivity listにreset_sw が抜けていました。抜けていてもISE11.1でのインプリメントは通ります。ただしXSTでwarningがでます。reset_sw が抜けている状態でインプリメントしたものをFPGA Editorで見ると非同期リセットになっています。電子サイコロの動作は、process文のsensitivity listにreset_sw が抜けた状態でも問題はありませんでした。
シミュレーションもclkのイベントでreset_swが1となっていれば、リセットされると思いますので、表面上は問題なく動作していたようです。
初めはVerilogで同期リセットFFでdiceを作ったので、VHDLにするときに勘違いしたようです。また、何か間違っているソースや記述があったらご指摘ください。よろしくお願いいたします。

 徒然日記さんで電子サイコロをAlteraデバイスによって実装 

トラ技の2009年6月号の別冊付録”再確認!電子機器の開発ツール”に載せた電子サイコロのプロジェクトを使って、”ISE11.1iのチュートリアル”をブログに書いた。それを、徒然日記さんの”電子サイコロ”という記事でAltera用に書き換えて、実際にAlteraのDE1というボードに実装して頂いたようだ。
その記事中にAlteraのツールはデフォルトで未使用ピンのレベルを L にするので、未使用の7セグLEDのセグメントがついてしまうとのことだった。
ということは、AlteraのボードDE1は4つの7セグメントLEDが直接FPGAの出力ピンにつながっているのだろうか?Spartan3 Starter Kitはダイナミック点灯なので、そうはならない。現在の電子サイコロのコードでは、0番目の7セグLEDに固定してあるので、一番右の7セグLEDしか点灯しない。
DE1はAlteraのCyclone2のボードで、Cyclone II FPGA スターター開発ボード リファレンスマニュアルの40ページの図2-18. 7 セグメント・ディスプレイの回路図を見ると、7セグLEDのセグメントが全部FPGAのピンにつながっているが分かる。
それで、FPGAの未使用ピンがLだと点灯してしまうんだな。でもかなり勢いが良く点灯しているので、本当に強くLに固定なんだろう。XilinxでもCPLDは完全にGND固定があった。
FPGAはbitgenのオプションで確か変えられたはず。さっそくProject NavigaterのGenerate Programming File のプロパティを見てみる。ダイアログ中のConfiguration Options を見ると、
Unused_IO_option_090524.png

UnusedPinはデフォルトではPull Downだった。Pull UpとFloatが選べる。
そういえば、7セグメントLEDを使わないときには、薄く点灯している。

#今日はF1モナコの予選が録画してあったので、朝それを見たが、Spartan3A Starter KitのDDR2 SDRAMコントローラを作ってやってみようとVerilogコードを作成中だ。おいおい作って、シミュレーションし、実装という手順になると思う。
昨日の午後は家具作りをした。食品棚も真ん中の垂直の棚と横の棚のはめ込みもだいたいうまくいったが板の反りが大きいので、クランプで修正中だ。どうも少し板が割れてしまったよう。。。

 2009年4月の検索キーワードベスト30 

Sim's blogさんでキーワードベスト20 その2をやっていたので、私も2009年4月の検索キーワードベスト30を見てみることにした。
まずはベスト30まで。
best30_090520.png

FPGAの部屋が1位だった。fpgaの部屋を入れれば505検索だった。次はディジタル・デザイン・テクノロジ、下の似たような言葉も入れると、343検索。
FPGA入門も多い。やはり、カーナビのガーミンの検索も依然として多い。
私のブログではソフトウェアの検索も多いみたい。tortoisesvnとかnotepadとか、notepadはそのまま使えると思うのだが?補完のやり方とかかな?しかし、notepad++でないのが不思議。もしかして本当にnotepadの使い方の検索???
後はverilogやmico32などのキーワードが多い。
LVPECLのキーワードも上位なのが面白い。そんなに使うのだろうか?