【シミュレーション】ModelSim AEでSystemVerilog/VHDL混在シミュレーション

前回、シフト演算を使用して乗算器を作成しました。

【VHDL】ビットシフトを利用した乗算回路

この乗算器のシミュレーション用のテストベンチをSystemVerilogで作成してみたいと思います。シフト演算モジュールはVHDLで作成されているので、SystemVerilog/VHDL混在シミュレーションという形になります。

実行環境

  • Windows 10 64bit
  • ModelSim Altera Starter Edition 10.4b
  • ソースコード

    シフト演算モジュール(VHDL)

    シフト演算モジュールは前回と同じですが、再掲します。

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    
    entity shift_mul is
        port    (
            srstn_i : in    std_logic;
            clk_i   : in    std_logic;
    
            sig_i   : in    std_logic_vector (7 downto 0);
            mul_i   : in    std_logic_vector (3 downto 0);
            sig_o   : out   std_logic_vector (11 downto 0)
        );
    end shift_mul;
    
    architecture rtl of shift_mul is
    
    signal sig_x1   : std_logic_vector (11 downto 0);
    signal sig_x2   : std_logic_vector (11 downto 0);
    signal sig_x4   : std_logic_vector (11 downto 0);
    signal sig_x8   : std_logic_vector (11 downto 0);
    signal sig_x16  : std_logic_vector (11 downto 0);
    signal mul      : std_logic_vector (11 downto 0);
    
    begin
    
    -- 入力信号を左シフトして2のべき乗をかけた信号を生成
    sig_x1  <= (11 downto  8 => '0') & sig_i;
    sig_x2  <= (11 downto  9 => '0') & sig_i & (0 downto 0 => '0');
    sig_x4  <= (11 downto 10 => '0') & sig_i & (1 downto 0 => '0');
    sig_x8  <= (11 downto 11 => '0') & sig_i & (2 downto 0 => '0');
    sig_x16 <= sig_i & (3 downto 0 => '0');
    
    -- シフト信号の組み合わせで乗算を実現
    process (clk_i) begin
        if (clk_i'event and clk_i='1') then
            if (srstn_i = '0') then
                mul <= (others=>'0');
            else
                case mul_i is
                    when x"0"   => mul  <= (others=>'0');               -- x0は0
                    when x"1"   => mul  <= sig_x1;                      -- x1=そのまま出力
                    when x"2"   => mul  <= sig_x2;                      -- x2=1bit左シフト
                    when x"3"   => mul  <= sig_x2 + sig_x1;             -- x3=x(2+1)
                    when x"4"   => mul  <= sig_x4;                      -- x4=2bit左シフト
                    when x"5"   => mul  <= sig_x4 + sig_x1;             -- x5=x(4+1)
                    when x"6"   => mul  <= sig_x4 + sig_x2;             -- x6=x(4+2)
                    when x"7"   => mul  <= sig_x8 - sig_x1;             -- x7=x(8-1)
                    when x"8"   => mul  <= sig_x8;                      -- x8=3bit左シフト
                    when x"9"   => mul  <= sig_x8 + sig_x1;             -- x9=x(8+1)
                    when x"a"   => mul  <= sig_x8 + sig_x2;             -- x10=x(8+2)
                    when x"b"   => mul  <= sig_x8 + sig_x2 + sig_x1;    -- x11=x(8+2+1)
                    when x"c"   => mul  <= sig_x16 - sig_x4;            -- x12=x(16-4)
                    when x"d"   => mul  <= sig_x16 - sig_x2 - sig_x1;   -- x13=x(16-2-1)
                    when x"e"   => mul  <= sig_x16 - sig_x2;            -- x14=x(16-2)
                    when x"f"   => mul  <= sig_x16 - sig_x1;            -- x15=x(16-1)
                    when others => mul  <= (others=>'0');
                end case;
            end if;
        end if;
    end process;
    
    sig_o   <= mul;
    
    end rtl;

    テストベンチ(SystemVerilog)

    テスト内容は前回同様、以下を順番に行っています。

  • 1に0~15を乗算
  • 2に0~15を乗算
  • 255に15を乗算
  • SystemVerilogを書いていて便利だと思ったのが、SystemVerilog上で宣言する信号名とVHDLモジュールのポート名を合わせれば、モジュール宣言では記述を省略できるところですね。これは楽です。

    `timescale 1ns / 1ps
    
    module sv_test_top;
        // 信号
        logic srstn_i           = '0;
        logic clk_i             = '0;
        logic [7:0]     sig_i   = '0;
        logic [3:0]     mul_i   = '0;
        logic [11:0]    sig_o   = '0;
    
        // クロック生成
        always #5ns clk_i <= ~clk_i; 
    
        // 同期リセット生成
        initial begin
            srstn_i <= '0;
            #99ns
            @(posedge clk_i);
            srstn_i <= '1;
        end
    
        // 入力生成
        initial begin
            // リセット解除後1クロック待機
            @(srstn_i);
            @(posedge clk_i);
            // 入力信号1に対して0~15を順番に乗算
            for (int i=0; i<16; i=i+1) begin
                sig_i   <= 8'h01;
                mul_i   <= i;
                @(posedge clk_i);
            end
    
            @(posedge clk_i);
            
            // 入力信号2に対して0~15を順番に乗算
            for (int i=0; i<16; i=i+1) begin
                sig_i   <= 8'h02;
                mul_i   <= i;
                @(posedge clk_i);
            end
    
            @(posedge clk_i);
    
            // 入力信号256に対して15を乗算
            sig_i   <= 8'hFF;
            mul_i   <= 15;
        end
    
        // 信号接続をいちいち書かないで済むので楽!
        shift_mul u_shift_mul (.*);
    
    endmodule

    doファイル(ファイル名:sim.do)

    waveファイルは適当に用意してください。sim.do上から削除しても実行はできると思います。(その場合はdoファイルを実行してModelSim上のWaveビューで波形追加後にrestartが必要です。)

    vlib work
    vcom shift_mul.vhd
    vlog test.sv
    vsim work.testbench
    do wave.do
    run 500ns

    シミュレーション結果

    結果の波形です。前回と同様の結果が得られていることが分かります。

    SystemVerilog VHDL 混在シミュレーション ModelSim AE

    シェアする

    • このエントリーをはてなブックマークに追加

    フォローする