FC2カウンター FPGAの部屋 VHDLでのブロックRAMや分散RAMの初期化(外部データファイル)
FC2ブログ

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

FPGAの部屋

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

VHDLでのブロックRAMや分散RAMの初期化(外部データファイル)

”soc-lm32をSpartan3E Stater Kitにコンフィギュレーション”でVerilogでのブロックRAMの外部データによる初期化を勉強したが、ISE10.1iSP3のXSTガイドのマニュアルのVerilogでの初期化の前にページにVHDLでの外部データファイルでの初期化も載っていた(245ページ)。
それで、VHDLでも、やってみることにした。実験用のMIPSプロセッサのサブセットの命令、データ用メモリがプリミティブで書いてあるので、それをXSTガイドのマニュアル245ページ(ブロックRAMの初期化(外部データファイル)のVHDLコード例)の方法で書きなおしてみた。
プロセッサのシミュレーションで一番問題なのは、プログラムをメモリにロードしないとシミュレーションできないことだ。ちなみに今までは、プリミティブで書かれたVHDLファイルの初期化部分をRuby で作ったスクリプトで、アセンブラの出力したプログラムリストをもとに書き換えてシミュレーションしていた。これの代わりにを外部データファイルでメモリを初期化できたら良いな?と思ったのだった。
idram.vhdはブロックRAMではなく、分散RAM(SLICEM)を使用しているので、dout の部分を process 文の外に出してある。こうするとXSTはブロックRAMではなく、SLICEMの分散RAMを使用してくれるようだ。

library IEEE, STD;
use IEEE.std_logic_1164.all;
use STD.textio.all;
use IEEE.std_logic_textio.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
-- pragma translate_off
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;
-- pragma translate_on
library work;
use work.lpm_pack.all;

entity idram is
    port(
        clk, reset : in std_logic;
        wr : in std_logic;
        iad, dad : in std_logic_vector(7 downto 0);
        ini : in std_logic_vector(31 downto 0);
        iout, dout : out std_logic_vector(31 downto 0));
end idram;

architecture RTL of idram is
type RamType is array(0 to 255) of bit_vector(31 downto 0);
impure function InitRamFromFile (RamFileName : in string) return RamType is
    FILE RamFile : text is in RamFileName;
    variable RamFileLine : line;
    variable RAM : RamType;
begin
    for I in RamType'range loop
        readline (RamFile, RamFileLine);
        read (RamFileLine, RAM(I));
    end loop;
    return RAM;
end function;
signal RAM : RamType := InitRamFromFile("idram.data");
begin
    -- データ用RAM
    process (clk) begin
        if clk'event and clk = '1' then
            if wr = '1' then
                RAM(conv_integer(dad)) <= to_bitvector(ini);
            end if;
            
        end if;
    end process;
    dout <= to_stdlogicvector(RAM(conv_integer(dad)));
    
    -- 命令用RAM
    iout <= to_stdlogicvector(RAM(conv_integer(iad)));

end RTL;


ここで、idram.data の一部がこれ。全部で256行。

10001100010000010000000000010100
00000000100001010001100000100010
00000000111010000011000000100100
00000001010010110100100000100101
00000001101011100110000000100000
00000000000000000000000000000001


残念ながらhread は使えなかった。read のみ使用可なので、idram.dataは2進数で書く必要がある。
これをシミュレーションすると、インストラクションが実行されている。
VHDL_init_data_file_1_081015.png

IF/IDのinstraction がそれだ。この機械語は、日経BP社の”コンピュータの構成と設計 第2版 下”の435ページのサンプルコードだ。引用させていただいてる。下にその自作アセンブラの出力したリストファイルを示す。

assembler        comment
----------------------------------------------------------------------------
            # P435 ラベル付けしたパイプラインでの命令実行状況
            
000    8C410014    :    lw    $1,20($2)    #
004    00851822    :    sub    $3,$4,$5    #
008    00E83024    :    and    $6,$7,$8    #
00C    014B4825    :    or    $9,$10,$11    #
010    01AE6020    :    add    $12,$13,$14    #
014    00000001    :    .word    1    #


というわけで、シミュレーションで実行できる。
さらに、インプリメントし、FPGAにコンフィグしても分散RAMにプログラムがロードされている。

次に、今までは分散RAMの外部データファイルによる初期化をやってみたが、今度はブロックRAMでやってみる。先ほどのidram.vhdを分散RAMからブロックRAMに変更する。
dout と iout をprocess 文の中に入れるとブロックRAMが生成されるはず。。。

    process (clk) begin
        if clk'event and clk = '1' then
            if wr = '1' then
                RAM(conv_integer(dad)) <= to_bitvector(ini);
            end if;
            dout <= to_stdlogicvector(RAM(conv_integer(dad)));
            
            -- 命令用RAM
            iout <= to_stdlogicvector(RAM(conv_integer(iad)));
        end if;
    end process;


これをインプリメントしてFPGA Editorで見てみる。
VHDL_init_data_file_2_081015.png

INT_00 のところに命令データがロードできているのが確認できる。(FPGA Editorのこの辺の使い方は”DCMの位相シフト量の変え方”を参照)
これで、ブロックRAMの場合も初期化できそうだ。
  1. 2008年10月15日 22:08 |
  2. VHDLの書き方
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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