FC2カウンター FPGAの部屋 VHDLでOVLアサーションを使用する2(VHDLライブラリを使用)
fc2ブログ

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

FPGAの部屋

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

VHDLでOVLアサーションを使用する2(VHDLライブラリを使用)

VHDLでOVLアサーションを使用する1(ライブラリのコンパイル)”でライブラリをコンパイルした。今回は、req_sm.vhd, ack_sm.vhd, tb_req_ack.vhd, ついでにパッケージのproj_pkg.vhd(これは、マニュアルを引用した)を作って、ModelSim Altera Starter Editon 6.5b のプロジェクトを作り、”VHDLでOVLアサーションを使用する1(ライブラリのコンパイル)”で作ったライブラリをModelSimのプロジェクトにインポートする。そうしてからVHDLファイルをコンパイルし、シミュレーションを行う。
さて、まずは、ModelSimのプロジェクトを作成し、ファイルをプロジェクトに加える。
ovl_vhdl_5_100327.png

次に、accellera_ovl_vhdlとaccellera_ovl_vlogライブラリをリンクしよう。
ModelSimのfileメニューからNew -> Library... を選択する。
ovl_vhdl_2_100327.png

Create a New Libraryダイアログが開くので、Library Name:にaccellera_ovl_vhdl を入力し、Library Maps to:はBrowse...ボタンをクリックして、accellera_ovl_vhdlを選択して、Next>ボタンをクリックする。
ovl_vhdl_3_100327.png

ModelSimのLibraryペインにaccellera_ovl_vhdlライブラリが入る。
ovl_vhdl_4_100327.png

同様に、accellera_ovl_vlogライブラリをプロジェクトにインクルードする。

ここで、各VHDLファイルを示す。まずは、グローバルなライブラリの設定を行うproj_pkg.vhdから。

-- proj_pkg.vhd

library accellera_ovl_vhdl;
use accellera_ovl_vhdl.std_ovl.all;
use accellera_ovl_vhdl.std_ovl_procs.all;

package proj_pkg is
    -- OVL configuration
    constant ovl_proj_controls : ovl_ctrl_record := (
        -- generate statement controls
        xcheck_ctrl                 => OVL_ON,
        implicit_xcheck_ctrl        => OVL_ON,
        init_msg_ctrl               => OVL_ON,
        init_count_ctrl             => OVL_OFF,
        assert_ctrl                 => OVL_ON,
        cover_ctrl                  => OVL_ON,
        global_reset_ctrl           => OVL_OFF,
        finish_ctrl                 => OVL_ON,
        gating_ctrl                 => OVL_ON,
        -- user configurable library constants
        max_report_error            => 4,
        max_report_cover_point      => 15,
        runtime_after_fatal         => "150 ns    ",
        -- default values for common generics
        severity_level_default      => OVL_SEVERITY_DEFAULT,
        property_type_default       => OVL_PROPERTY_DEFAULT,
        --msg_default => OVL_MSG_DEFAULT,
        msg_default                 => ovl_set_msg("Assertion Error"),
        coverage_level_default      => OVL_COVER_DEFAULT,
        clock_edge_default          => OVL_CLOCK_EDGE_DEFAULT,
        reset_polarity_default      => OVL_RESET_POLARITY_DEFAULT,
        gating_type_default         => OVL_GATING_TYPE_DEFAULT
    );
end package proj_pkg;


req_sm.vhdを下に示す。

-- OVLテスト用 req_sm.vhd
-- req_start 信号を受けると、reqを1にアサートする。ackを受け取るとreqを0にディアサートする

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity req_sm is
    port(
        clk : in std_logic;
        reset : in std_logic;
        req_start : in std_logic;
        ack : in std_logic;
        req : out std_logic
    );
end req_sm;

architecture RTL of req_sm is
type cs_req_state is (idle_req, assert_req);
signal cs_req : cs_req_state;
begin
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_req <= idle_req;
                req <= '0';
            else
                case cs_req is
                    when idle_req =>
                        if req_start='1' then
                            cs_req <= assert_req;
                            req <= '1';
                        end if;
                    when assert_req =>
                        if ack='1' then
                            cs_req <= idle_req;
                            req <= '0';
                        end if;
                end case;
            end if;
        end if;
    end process;
end RTL;


ack_smを下に示す。

-- OVLテスト用 ack_sm.vhd
-- 2つのreqを管理して、reqがアサートされている状態で、taがアサートされるとackを返す

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity ack_sm is
    port(
        clk : in std_logic;
        reset : in std_logic;
        req0 : in std_logic;
        req1 : in std_logic;
        ta0 : in std_logic; -- Transfer Acknowledge
        ta1 : in std_logic; -- Transfer Acknowledge
        ack0 : out std_logic;
        ack1 : out std_logic
    );
end ack_sm;

architecture RTL of ack_sm is
type cs_main_state is (idle_req, assert_req0, assert_req1, assert_req01, req0_ack, req1_ack, req01_ack);
signal cs_main : cs_main_state;
begin
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_main <= idle_req;
                ack0 <= '0'; ack1 <= '0';
            else
                case cs_main is
                    when idle_req =>
                        if req0='1' then
                            cs_main <= assert_req0;
                            ack0 <= '0'; ack1 <= '0';
                        elsif req1='1' then
                            cs_main <= assert_req1;
                            ack0 <= '0'; ack1 <= '0';
                        end if;
                    when assert_req0 =>
                        if req1='1' then
                            cs_main <= assert_req01;
                            ack0 <= '0'; ack1 <= '0';
                        elsif ta0='1' then
                            cs_main <= req0_ack;
                            ack0 <= '1'; ack1 <= '0';
                        end if;
                    when assert_req1 =>
                        if req0='1' then
                            cs_main <= assert_req01;
                            ack0 <= '0'; ack1 <= '0';
                        elsif ta1='1' then
                            cs_main <= req1_ack;
                            ack0 <= '0'; ack1 <= '1';
                        end if;
                    when assert_req01 =>
                        if ta0='1' and ta1='0' then
                            cs_main <= req0_ack;
                            ack0 <= '1'; ack1 <= '0';
                        elsif ta0='0' and ta1='1' then
                            cs_main <= req1_ack;
                            ack0 <= '0'; ack1 <= '1';
                        elsif ta0='1' and ta1='1' then
                            cs_main <= req01_ack;
                            ack0 <= '1'; ack1 <= '1';
                        end if;
                    when req0_ack =>
                        if req1='1' then
                            cs_main <= assert_req1;
                            ack0 <= '0'; ack1 <= '0';
                        else
                            cs_main <= idle_req;
                            ack0 <= '0'; ack1 <= '0';
                        end if;
                    when req1_ack =>
                        if req0='1' then
                            cs_main <= assert_req0;
                            ack0 <= '0'; ack1 <= '0';
                        else
                            cs_main <= idle_req;
                            ack0 <= '0'; ack1 <= '0';
                        end if;
                    when req01_ack =>
                        cs_main <= idle_req;
                        ack0 <= '0'; ack1 <= '0';
                end case;
            end if;
        end if;
    end process;
end RTL;


最後に、テストベンチのtb_req_ack.vhd を示す。

-- tb_req_ack.vhd

-- tb_req_ack.vhd本体
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
library accellera_ovl_vhdl;
use accellera_ovl_vhdl.std_ovl.all;
use accellera_ovl_vhdl.std_ovl_components.all;
use accellera_ovl_vhdl.std_ovl_procs.all;
library work;
use work.proj_pkg.all;

entity tb_req_ack is
end tb_req_ack;

architecture testbench_arch of tb_req_ack is
component ack_sm
    port(
        clk : in std_logic;
        reset : in std_logic;
        req0 : in std_logic;
        req1 : in std_logic;
        ta0 : in std_logic; -- Transfer Acknowledge
        ta1 : in std_logic; -- Transfer Acknowledge
        ack0 : out std_logic;
        ack1 : out std_logic
    );
end component;
component req_sm
    port(
        clk : in std_logic;
        reset : in std_logic;
        req_start : in std_logic;
        ack : in std_logic;
        req : out std_logic
    );
end component;
signal clk : std_logic := '1';
signal reset : std_logic := '1';
signal req_start0 : std_logic := '0';
signal req_start1 : std_logic := '0';
signal req0 : std_logic := '0';
signal req1 : std_logic := '0';
signal ta0 : std_logic := '0';
signal ta1 : std_logic := '0';
signal ack0 : std_logic := '0';
signal ack1 : std_logic := '0';
signal fire_ta0_ack0_as, fire_ta1_ack1_as : std_logic_vector(OVL_FIRE_WIDTH - 1 downto 0);
signal fire_req0_ack0_as, fire_req1_ack1_as : std_logic_vector(OVL_FIRE_WIDTH - 1 downto 0);

constant PERIOD : time := 20 ns;
constant DUTY_CYCLE : real := 0.5;

-- req_startとtaを出力するprocedure
procedure REQ_START_TA(
    signal clk : in std_logic;
    loop_count : in integer;
    signal req_start : out std_logic;
    signal ta : out std_logic
) is
begin
    wait until clk'event and clk='1'; -- clkの立ち上がりまでwait
    wait for 1 ns; -- 遅延を挟んで
    req_start <= '1';
    wait until clk'event and clk='1'; -- clkの立ち上がりまでwait
    wait for 1 ns; -- 遅延を挟んで
    req_start <= '0';
     
    for n in loop_count to 1 loop
        wait until clk'event and clk='1'; -- clkの立ち上がりまでwait
        wait for 1 ns; -- 遅延を挟んで
    end loop;
    ta <= '1';
    wait until clk'event and clk='1'; -- clkの立ち上がりまでwait
    wait for 1 ns; -- 遅延を挟んで
    ta <= '0';
end REQ_START_TA;

begin
    -- clkの生成(50MHz)
    clk_generate : process begin
        clock_loop : loop
            clk <= '1';
            wait for (PERIOD * DUTY_CYCLE);
            clk <= '0';
            wait for (PERIOD - (PERIOD * DUTY_CYCLE));
        end loop clock_loop;
    end process clk_generate;
    
    -- シミュレーション時にOVLチェッカの初期化数を表示
    ovl_print_init_count_p : process begin
        wait for 0 ns;
        ovl_print_init_count_proc(ovl_proj_controls);
        wait; -- forever
    end process ovl_print_init_count_p;
    
    -- resetの生成
    reset_generate : process begin
        reset <= '1';
        wait for 100 ns;
        reset <= '0';
        wait; -- forever
    end process reset_generate;
    
    ack_sm_inst : ack_sm port map(
        clk => clk,
        reset => reset,
        req0 => req0,
        req1 => req1,
        ta0 => ta0, 
        ta1 => ta1,
        ack0 => ack0,
        ack1 => ack1
    );
    req_am_inst0 : req_sm port map(
        clk => clk,
        reset => reset,
        req_start => req_start0,
        ack => ack0,
        req => req0
    );
    req_am_inst1 : req_sm port map(
        clk => clk,
        reset => reset,
        req_start => req_start1,
        ack => ack1,
        req => req1
    );
        
    -- req_start0 とta0 の関係を生成する
    process begin
        req_start0 <= '0';
        ta0 <= '0';
        wait until reset'event and reset='0'; -- resetの立ち下がりまでwait
        wait for 100 ns;
        REQ_START_TA(clk, 1, req_start0, ta0);
        REQ_START_TA(clk, 2, req_start0, ta0);
        REQ_START_TA(clk, 3, req_start0, ta0);
        REQ_START_TA(clk, 2, req_start0, ta0);
        REQ_START_TA(clk, 1, req_start0, ta0);
        REQ_START_TA(clk, 3, req_start0, ta0);
        REQ_START_TA(clk, 2, req_start0, ta0);
        wait for 200 ns;
        assert (false) report "Simulation End!" severity failure;
    end process;
    
    -- req_start1 とta1 の関係を生成する
    process begin
        req_start1 <= '0';
        ta1 <= '0';
        wait until reset'event and reset='0'; -- resetの立ち下がりまでwait
        wait for 100 ns;
        REQ_START_TA(clk, 2, req_start1, ta1);
        REQ_START_TA(clk, 1, req_start1, ta1);
        REQ_START_TA(clk, 2, req_start1, ta1);
        REQ_START_TA(clk, 3, req_start1, ta1);
        REQ_START_TA(clk, 3, req_start1, ta1);
        REQ_START_TA(clk, 1, req_start1, ta1);
        REQ_START_TA(clk, 2, req_start1, ta1);
        wait; -- forever
    end process;
    
    -- OVLアサーション
    ovl_gen : if (ovl_proj_controls.assert_ctrl = OVL_ON) generate
        ta0_ack0_assertion : ovl_next generic map (
            severity_level        => OVL_ERROR,
            num_cks             => 1,
            check_overlapping   => OVL_CHK_OVERLAP_OFF,
            check_missing_start => OVL_ON,
            property_type        => OVL_ASSERT,
            msg                 =>"ERROR: ack0 isn't asserted of with the next clock that ta0 was asserted.",
            coverage_level      => OVL_COVER_BASIC,
            clock_edge            => OVL_POSEDGE,
            reset_polarity        => OVL_ACTIVE_HIGH,
            gating_type            => OVL_GATE_CLOCK,
            controls            => OVL_CTRL_DEFAULTS
        )port map (
            clock               => clk,
            reset               => reset,
            enable              => '1',
            start_event         => ta0,
            test_expr           => ack0,
            fire                => fire_ta0_ack0_as
        );
        ta1_ack1_assertion : ovl_next generic map (
            severity_level        => OVL_ERROR,
            num_cks             => 1,
            check_overlapping   => OVL_CHK_OVERLAP_OFF,
            check_missing_start => OVL_ON,
            property_type        => OVL_ASSERT,
            msg                 =>"ERROR: ack1 isn't asserted of with the next clock that ta1 was asserted.",
            coverage_level      => OVL_COVER_BASIC,
            clock_edge            => OVL_POSEDGE,
            reset_polarity        => OVL_ACTIVE_HIGH,
            gating_type            => OVL_GATE_CLOCK,
            controls            => OVL_CTRL_DEFAULTS
        )port map (
            clock               => clk,
            reset               => reset,
            enable              => '1',
            start_event         => ta1,
            test_expr           => ack1,
            fire                => fire_ta1_ack1_as
        );
    end generate ovl_gen;
end testbench_arch;


これでModelSimでシミュレーションをしてみた。結果の図を下に示す。
ovl_vhdl_6_100327.png

出力されたOVLアサーションのログを下に示す。

#        OVL_ERROR : OVL_NEXT : ERROR: ack1 isn't asserted of with the next clock that ta1 was asserted. : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 260000 ps :tb_req_ack:ovl_gen:ta1_ack1_assertion:
#        OVL_ERROR : OVL_NEXT : ERROR: ack0 isn't asserted of with the next clock that ta0 was asserted. : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 280000 ps :tb_req_ack:ovl_gen:ta0_ack0_assertion:
#        OVL_ERROR : OVL_NEXT : ERROR: ack0 isn't asserted of with the next clock that ta0 was asserted. : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 400000 ps :tb_req_ack:ovl_gen:ta0_ack0_assertion:
#        OVL_ERROR : OVL_NEXT : ERROR: ack1 isn't asserted of with the next clock that ta1 was asserted. : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 400000 ps :tb_req_ack:ovl_gen:ta1_ack1_assertion:
#        OVL_ERROR : OVL_NEXT : ERROR: ack1 isn't asserted of with the next clock that ta1 was asserted. : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 520000 ps :tb_req_ack:ovl_gen:ta1_ack1_assertion:
#        OVL_ERROR : OVL_NEXT : ERROR: ack0 isn't asserted of with the next clock that ta0 was asserted. : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 540000 ps :tb_req_ack:ovl_gen:ta0_ack0_assertion:
#        OVL_ERROR : OVL_NEXT : ERROR: ack0 isn't asserted of with the next clock that ta0 was asserted. : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 660000 ps :tb_req_ack:ovl_gen:ta0_ack0_assertion:
#        OVL_ERROR : OVL_NEXT : ERROR: ack1 isn't asserted of with the next clock that ta1 was asserted. : Test expression is not asserted after elapse of num_cks cycles from start event : severity 1 : time 660000 ps :tb_req_ack:ovl_gen:ta1_ack1_assertion:
# ** Failure: Simulation End!
#    Time: 841 ns  Iteration: 0  Process: /tb_req_ack/line__133 File: H:/HDL/OVL/example/req_ack_test_vhdl/tb_req_ack.vhd
# Break in Process line__133 at H:/HDL/OVL/example/req_ack_test_vhdl/tb_req_ack.vhd line 146

  1. 2010年03月28日 06:09 |
  2. アサーション事始め
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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