FC2カウンター FPGAの部屋 2009年06月23日
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

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の使用数が倍近く多い。

何か間違いがあったらお知らせください。
  1. 2009年06月23日 20:40 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:8

Spartan3A Starter KitのDDR2 SDRAMコントローラのバーストテストのプロジェクト

Spartan3A Starter KitのDDR2 SDRAMコントローラのバーストテストのプロジェクトを置いておくので、興味のある方はダウンロードしてください。いつものように保証なし、原則転載禁止(転載したい方はメールでお知らせください)とします。それからSpartan3A Starter Kitを持っている方は正常に動作したかどうかをぜひ教えてください。よろしくお願いします。ISE11.1iを持っていない方もddr2_burst_testフォルダの下にビットファイルddr2_burst_test.bitを入れておきますので、iMPACTでコンフィグすれば確かめてみることができます。これはChipScope入りのビットファイルです。

ZIPファイルを開けて、ddr2_burst_test/Synth111フォルダの中にISE11.1iのプロジェクトファイルddr2_burst_test.xise がある。今回のプロジェクトにはChipScopeは入っていないが、ChipScopeをインストールしてある方は、DDR2_burst_test_cs.cdc をプロジェクトに入れてほしい。ChipScopeのプロジェクトDDR2_burst_test_cs.cpj も入れてある。ddr2_burst_test/Synth111フォルダの内容を下に示す。
Spa3A_STKit_DDR2_proj_1_090622.png

下がProject Navigatorのプロジェクトの階層だ。
Spa3A_STKit_DDR2_proj_2_090622.png

プロジェクトはインプリメントしていない状態なので、ビットファイルを生成して、iMPACTでSpartan3A Starter KitのSpartan3Aをコンフィギュレーションしてほしい。その辺のやり方は、”ISE11.1iのチュートリアル6(デザインのインプリメント)”、”ISE11.1iのチュートリアル7(FPGAのコンフィギュレーション)”を参照のこと。

使用方法だが、チップスコープを使って、Readデータを見ないと本当に詰まらない動作だ。使用するのはLD0, LD1の2つのLEDとリセット用の押しボタンスイッチSOUTH (T15) 。LD0 はDDR2 SDRAMのバーストテストが正常に読み書きできているときに点灯している。これが点灯していれば、Writeしたバーストデータが正常にバーストRead出来ていることを表す。LD0 が消えてLD1 が点灯するとWriteしたデータと異なるデータがReadされたことを示す。
ChipScopeがインストールされていて、DDR2_burst_test_cs.cdc をプロジェクトに入れてインプリメントすると下の図のようにどのようなデータをリードしているかが分かる。
Spa3A_STKit_DDR2_Debug_6_090617.png

Spartan3A Starter KitでのLD0、LD1と押しボタンスイッチSOUTH (T15) の位置を下の写真に示す。
Spa3A_STKit_Pict_090623.jpg

シミュレーションのやり方は次回に。

2009/06/27 追記:
ddr2_bust_testのダウンロードできるプロジェクトを変更しました。

2009/08/21 追記:
ISE11.2でインプリメントエラーが出るようになってしまったので、ダウンロードプロジェクトを変更しました。詳しくは、”Spartan3A Starter KitのDDR2 SDRAMコントローラのバーストテストのインプリメントエラー”をご覧ください。

2010/08/27 追記:
<注意> バグが発覚したので、Spartan3A Starter KitのDDR2 SDRAMコントローラのバーストテストのプロジェクトを修正しました。必要な方はもう一度ダウンロードしてください。
Spartan-3A Starter KitでCMOSカメラ・ディスプレイ回路19(DDR2 SDRAMコントローラのバグフィック)”参照
  1. 2009年06月23日 05:30 |
  2. Spartan3A Starter Kit
  3. | トラックバック:0
  4. | コメント:0