2007年07月24日

VHDL TIPS 「access typeの使用法」

VHDLにはアクセスタイプと言うC言語のポインタのような機能がある。
ほとんど使用する機会は無いと思うがおもしろい機能なので紹介したい。

C言語のポインタが分かる人なら以下のサンプルを見て理解できると思う。
このサンプルは4Bank構成のメモリで最初はメモリ領域を確保せず、Bank毎に最初にアクセスがあったときに初めてメモリ領域を確保している。また、リセットを入れると全てのメモリ領域を開放する。
(記述としてはジェネリックを使わず固定値にしていたり、メモリとしても非効率かつ無意味な機能があったりするが、あくまでアクセスタイプのサンプルなので...)


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

-- 16Wordx8Bitx4Banksの同期メモリ
entity test_accs is
    port
    (
        CLK         : in    std_logic;                      -- クロック
        RST         : in    std_logic;                      -- リセット
        ADDR        : in    std_logic_vector(3 downto 0);   -- アドレス(16Word=4Bit)
        BA          : in    std_logic_vector(1 downto 0);   -- バンクアドレス(4Bank=2Bit)
        CS          : in    std_logic;                      -- チップセレクト
        WE          : in    std_logic;                      -- ライトイネーブル
        INDATA      : in    std_logic_vector(7 downto 0);   -- ライトデータ
        OUTDATA     : out   std_logic_vector(7 downto 0)    -- リードデータ
    );
end test_accs;

architecture behavior of test_accs is

    -- データ幅8Bitのサブタイプ
    subtype BUSWIDS     is std_logic_vector(7 downto 0);
    -- 16Wordのサブタイプ
    subtype ARRAYNUM    is std_logic_vector(15 downto 0);
    -- 1Bankのデータタイプ
    type    CELLARRAY   is array(ARRAYNUM'range) of BUSWIDS;
    -- 1Bankのアクセスタイプ(ポインタ)
    type    BNKACCESS   is access CELLARRAY;
    -- 1Bankのアクセスタイプの4配列(ポインタの配列)
    type    BNKARRAY    is array(3 downto 0) of BNKACCESS;

begin

    process
        -- アクセスタイプの4配列をインスタンス
        variable    BANK        : BNKARRAY := (others => NULL);

        variable    BA_INT      : integer;
        variable    ADDR_INT    : integer;
    begin

        -- クロックの立ち上がりエッジで動作する
        wait until CLK = '1';

        -- データ型変換
        BA_INT := conv_integer(BA);
        ADDR_INT := conv_integer(ADDR);

        -- チップセレクトがイネーブルで選択されているバンクに
        -- メモリが割り当たっていない場合
        if ( RST = '0' and CS = '1' and BANK(BA_INT) = NULL ) then
            -- 選択されているバンクにメモリを確保する
            BANK(BA_INT) := new CELLARRAY;
            -- 確保したメモリ領域を0クリアする
            for i in ARRAYNUM'range loop
                BANK(BA_INT)(i) := BUSWIDS'(others => '0');
            end loop;
        end if;

        -- チップセレクトがイネーブルでライトイネーブルがイネーブルの場合
        if ( RST = '0' and CS = '1' and WE = '1' ) then
            -- メモリにデータを書き込む
            BANK(BA_INT)(ADDR_INT) := INDATA;
        end if;

        -- チップセレクトがイネーブルの場合
        if ( RST = '0' and CS = '1' ) then
            -- メモリからデータを読み出す
            OUTDATA <= BANK(BA_INT)(ADDR_INT);

        -- チップセレクトがイネーブルでない場合
        else
            -- データを弱いHIGH(プルアップ)にする
            OUTDATA <= (others => 'H');
        end if;

        -- リセットがイネーブルの場合
        if ( RST = '1' ) then
            -- メモリ割り当てを解放する
            for i in BNKARRAY'range loop
                if ( BANK(i) /= NULL ) then
                    deallocate(BANK(i));
                    BANK(i) := NULL;
                end if;
            end loop;
        end if;

    end process;

end behavior;



まとめとして、サンプルコードでのアクセスタイプは、
    type    BNKACCESS   is access CELLARRAY;
でアクセスタイプを定義して、
        variable    BANK        : BNKARRAY := (others => NULL);
でアクセスタイプのインスタンスを作成し、
            BANK(BA_INT) := new CELLARRAY;
でメモリ領域を割り当て、
                deallocate(BANK(i));
でメモリ領域を開放する。
以上のような流れで使用している。

これに関連して今度は「incomplete type」を紹介しようと思う。



投稿時刻(12:32)│コメント(0)VHDL 

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
最新コメント
ブログ内検索
カテゴリ別表示
月別表示
問い合わせ・連絡先
ta_bo__@livedoor.com

本サイトは以下のアクセス解析を使用しております。
基礎化粧品