FC2カウンター FPGAの部屋 2011年01月20日
FC2ブログ

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

FPGAの部屋

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

FIFOをISimで論理シミュレーションしたときの不具合(Fifo Generator 7.2を使用)

SRAMのコントローラを作成していて、Read/WriteをバーストでアクセスするためにRead用、Write用それぞれのFIFOをFifo Generator 7.2を使って作成した。そのSRAMコントローラをISE12.4のISimでシミュレーションしているときに、おかしな動作になってしまった。FIFOの仕様は、分散RAM仕様のFWFT FIFOで、深度が16(18)、ビット幅が16(Read用)、34(Write用)、DATA_COUNT、almost_full, almost_empty付きだ。

どのようにおかしいかというと、下のISimのシミュレーション図で、まずはwr_fifoの方を見ていく。wr_fifo_emptyだが、wr_fifo_rd_enが'1'になったと同時に'1'になっている(ピンクの四角)。これは、水色の四角で示すwr_fifo_rd_enが'1'から'0'になるclk(見えていないが。。。)の立ち上がりまで'1'になる必要がある。しかも、wr_fifo_countも01のままで00にならない。
rd_fifo_emptyも黄色い四角で示す位置で'1'になるはずがならない。。。
FIFOG_1_110120.png

FIFO付近のVHDLコードを下に示す。

    -- Write Data Path
    wr_fifo_din <= wr_address & wr_data;
    wr_fifo_rd_en_node <= wr_fifo_rd_en;
    wr_fifo_inst : write_fifo port map(
        clk => clk,
        srst => reset,
        din => wr_fifo_din,
        wr_en => wr_enable,
        rd_en => wr_fifo_rd_en,
        dout => wr_fifo_dout,
        full => open,
        almost_full => wr_fifo_full,
        empty => wr_fifo_empty,
        almost_empty => wr_fifo_almost_empty,
        data_count => wr_fifo_count
    );
    
    
    -- Read Data Path
    rd_fifo_rd_en_node <= rd_fifo_rd_en;
    rd_fifo_inst : read_fifo port map(
        clk => clk,
        srst => reset,
        din => rd_address,
        wr_en => rd_enable,
        rd_en => rd_fifo_rd_en,
        dout => rd_fifo_dout,
        full => open,
        almost_full => rd_fifo_full,
        empty => rd_fifo_empty,
        almost_empty => rd_fifo_almost_empty,
        data_count => rd_fifo_count
    );
    
    -- SRAMのRead, Write 用ステートマシン(Read優先)
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_SRAM_RW <= SRAM_RW_STATE'(idle);
                wr_fifo_rd_en <= '0';
                rd_fifo_rd_en <= '0';
            else
                case cs_SRAM_RW is
                    when SRAM_RW_STATE'(idle) =>
                        if rd_fifo_empty='0' then
                            cs_SRAM_RW <= READ_STATE;
                            rd_fifo_rd_en <= '1';
                        elsif wr_fifo_empty='0' then
                            cs_SRAM_RW <= WRITE_STATE1;
                        end if;
                    when READ_STATE =>
                        if rd_fifo_almost_empty='0' then -- まだRead用FIFOに残っている
                            cs_SRAM_RW <= READ_STATE;
                        else
                            cs_SRAM_RW <= SRAM_RW_STATE'(idle);
                            rd_fifo_rd_en <= '0';
                        end if;
                    when WRITE_STATE1 =>
                        cs_SRAM_RW <= WRITE_STATE2;
                        wr_fifo_rd_en <= '1';
                    when WRITE_STATE2 =>
                        wr_fifo_rd_en <= '0';
                        if rd_fifo_empty='0' then -- Read優先, ReadとWriteの間は1クロック間を空ける。
                            cs_SRAM_RW <= SRAM_RW_STATE'(idle);
                        elsif wr_fifo_almost_empty='0' then -- まだWrite用FIFOに残っている
                            cs_SRAM_RW <= WRITE_STATE1;
                        else
                            cs_SRAM_RW <= SRAM_RW_STATE'(idle);
                        end if;
                end case;
            end if;
        end if;
    end process;



これは、どうやらデルタ遅延のいたずらのようだ。
2つのFIFOのrd_enを1つノードを通して入れると正常な動作になった。
FIFOG_2_110120.png
(注)上のVHDLコードにはバグがあったので、修正してあります。

FIFO付近のコードを以下に示す。

    -- Write Data Path
    wr_fifo_din <= wr_address & wr_data;
    wr_fifo_rd_en_node <= wr_fifo_rd_en;
    wr_fifo_inst : write_fifo port map(
        clk => clk,
        srst => reset,
        din => wr_fifo_din,
        wr_en => wr_enable,
        rd_en => wr_fifo_rd_en_node,
        dout => wr_fifo_dout,
        full => open,
        almost_full => wr_fifo_full,
        empty => wr_fifo_empty,
        almost_empty => wr_fifo_almost_empty,
        data_count => wr_fifo_count
    );    
    
    -- Read Data Path
    rd_fifo_rd_en_node <= rd_fifo_rd_en;
    rd_fifo_inst : read_fifo port map(
        clk => clk,
        srst => reset,
        din => rd_address,
        wr_en => rd_enable,
        rd_en => rd_fifo_rd_en_node,
        dout => rd_fifo_dout,
        full => open,
        almost_full => rd_fifo_full,
        empty => rd_fifo_empty,
        almost_empty => rd_fifo_almost_empty,
        data_count => rd_fifo_count
    );


2つのFIFOのrd_en に1つノードを追加した。これで正常にシミュレーションすることができた。

clkはポートから直結なんだけど?FIFO Generator のクロックのパスが長いのだろうか?いずれにせよ。これでだいぶ時間をつぶしてしまった。。IPの中なので、自分では注意できない。よって、おかしいことがあったら、まずはデルタ遅延を疑おうと思った。
  1. 2011年01月20日 12:16 |
  2. Core Generator
  3. | トラックバック:0
  4. | コメント:0

電子サイコロをNSLで書いてみる2(NSLに変換)

電子サイコロをNSLで書いてみる1(Papyrusでクラス図を作成)”でUMLのクラス図を作った。今度はUMLtoNSLでNSLファイルに変換してみる。

UMLtoNSLツールを起動して、dice.nslに変換した。下に変換後のdice.nslを示す。

// UML2NSL converter Ver. 2010-03-28 Copyright (c) 2009-2010 IP ARCH, Inc. All rights reserved.
// xmi  --- version 2.1 --- 



declare    dice  {
    
    // -- dice  --
    input    roll;
    output    seg_o[8];
    output    seg_figure[4];
    
}

declare    counter_1to6  {
    
    // -- counter_1to6  --
    output    seg0to6_o[8];
    
    // -- counter_1to6  --
    func_in    countup();

}

declare    hex_to_7segout  {
    
    // -- hex_to_7segout  --
    input    hexdata[3];
    
    // -- hex_to_7segout  --
    func_in    output7seg(hexdata);

}
module    dice {
    
    // -- dice  --
    reg    count_5msec[18];
        reg    count_20msec[3];
        counter_1to6    u_counter_1to6;
    


    /* common operations */
    {
    
    }

    
}
module    counter_1to6 {
    
    // -- counter_1to6  --
    reg    counter_1to6[3];
        hex_to_7segout    u_hex_to_7segout;
    


    /* common operations */
    {
    
    }

    
    /* func_in countup() operation */
    function    countup {
    
    }
        
}
module    hex_to_7segout {
    
    // -- hex_to_7segout  --
    wire    seg_value[8];
        


    /* common operations */
    {
    
    }

    
    /* func_in output7seg(hexdata) operation */
    function    output7seg {
    
    }
        
}


さて、このスケルトンからNSLのメソッドを書いていくのだが、Notepad++がNSLに対応していないので、キーワードの色分けが出来ていない。Notepad++はキーワードを定義する機能があるので、キーワードを定義してから、メソッドを書いていくことにする。
  1. 2011年01月20日 05:35 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0