FC2カウンター FPGAの部屋 FIFOをISimで論理シミュレーションしたときの不具合(Fifo Generator 7.2を使用)
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

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/1695-00d3690a
この記事にトラックバックする(FC2ブログユーザー)