[Verilog][SystemVerilog] Beep音が鳴らなかった・・・

昨日の SystemVerilog読書会の際にあった
「Escape sequences for printing special characters」にて、
「\a」Bellって書いたあるので、試してみました。

module testbench();

  initial begin
    $write("\a");
  end

endmodule

結果は音ならず。。。
しかも、

# run -all 
# a quit 

ってな感じで、ModelSim-ASEだと「a」が表示されました。
iverilogでもやってみましたが同じ結果でした。


期待していただけに残念(´・ω・`)

[Verilog][SystemVerilog] $ramdomの使い方

[Verilog][SystemVerilog] $random使用時の失敗


にて、コメント頂きました。
ありがとうございます m(_ _)m


コメント頂きました記述方法にて、確認出来ましたのでこちらでも記載しときます。

module testbench();

  integer seed_a = 1 ;
  integer seed_b = 2 ;
  integer temp_a = 0 ;
  integer temp_b = 0 ;

  initial begin
    repeat(10) begin
      temp_a = $random(seed_a) % 5;
      temp_b = $random(seed_b) % 5;
      $display("--- temp_a = %3d, temp_b = %3d ---", temp_a, temp_b);
    end
    $finish(2);
  end

endmodule
  • 実行結果
# --- temp_a =  -3, temp_b =  -3 ---
# --- temp_a =  -3, temp_b =   0 ---
# --- temp_a =   2, temp_b =  -1 ---
# --- temp_a =  -4, temp_b =   0 ---
# --- temp_a =   1, temp_b =   0 ---
# --- temp_a =   3, temp_b =   3 ---
# --- temp_a =  -3, temp_b =   1 ---
# --- temp_a =  -1, temp_b =   2 ---
# --- temp_a =   0, temp_b =   0 ---
# --- temp_a =  -1, temp_b =   0 ---

$random の seed引数って更新されるんですね。
確かにこの記述方法だと、前に書いたような失敗が起きないですね。

[Verilog][SystemVerilog] $random使用時の失敗

ModelSim-ASEでも $random使えることを知ったので、
ちょっと遊んでいて、失敗して、でも、そうだよなと思ったのでメモ。

  • コード1

  • module testbench();
    
      integer temp_a = 0 ;
    
      initial begin
        repeat(10) begin
          temp_a = $random % 5;
          $display("--- temp_a = %2d ---", temp_a);
        end
        $finish(2);
      end
    
    endmodule
  • 結果

  • # --- temp_a =  3 ---
    # --- temp_a = -4 ---
    # --- temp_a = -4 ---
    # --- temp_a = -4 ---
    # --- temp_a =  2 ---
    # --- temp_a =  2 ---
    # --- temp_a = -1 ---
    # --- temp_a = -4 ---
    # --- temp_a =  1 ---
    # --- temp_a =  4 ---
  • コード2

  • module testbench();
    
      integer temp_a = 0 ;
      integer temp_b = 0 ;
    
      initial begin
        repeat(10) begin
          temp_a = $random % 5;
          temp_b = $random % 5;
          $display("--- temp_a = %2d ---", temp_a);
          $display("--- temp_b = %2d ---", temp_b);
        end
        $finish(2);
      end
    
    endmodule
  • 結果

  • # --- temp_a =  3 ---
    # --- temp_b = -4 ---
    # --- temp_a = -4 ---
    # --- temp_b = -4 ---
    # --- temp_a =  2 ---
    # --- temp_b =  2 ---
    # --- temp_a = -1 ---
    # --- temp_b = -4 ---
    # --- temp_a =  1 ---
    # --- temp_b =  4 ---
    # --- temp_a =  3 ---
    # --- temp_b =  2 ---
    # --- temp_a =  4 ---
    # --- temp_b =  2 ---
    # --- temp_a =  4 ---
    # --- temp_b =  0 ---
    # --- temp_a = -4 ---
    # --- temp_b = -4 ---
    # --- temp_a =  0 ---
    # --- temp_b = -1 ---
    

とまぁ、$randomの返り値は同じなんですが、
代入先が異なるので。例えば、classとかで擬似的作ろうとすると。

  • コード3

  • class hoge;
       integer temp;
       function new();
         temp = 0;
       endfunction: new
    
       function integer f_rand();
         temp = $random % 5;
         return temp;
       endfunction
    
    endclass: hoge
    
    module testbench();
    
      integer temp_a = 0 ;
      integer temp_b = 0 ;
      hoge mhoge = new();
      hoge mmhoge = new();
    
      initial begin
        repeat(10) begin
          temp_a = mhoge.f_rand();
          temp_b = mhoge.f_rand();
          $display("--- temp_a = %2d ---", temp_a);
          $display("--- temp_b = %2d ---", temp_b);
        end
        $finish(2);
      end
    
    endmodule
  • 結果

  • # --- temp_a =  3 ---
    # --- temp_b = -4 ---
    # --- temp_a = -4 ---
    # --- temp_b = -4 ---
    # --- temp_a =  2 ---
    # --- temp_b =  2 ---
    # --- temp_a = -1 ---
    # --- temp_b = -4 ---
    # --- temp_a =  1 ---
    # --- temp_b =  4 ---
    # --- temp_a =  3 ---
    # --- temp_b =  2 ---
    # --- temp_a =  4 ---
    # --- temp_b =  2 ---
    # --- temp_a =  4 ---
    # --- temp_b =  0 ---
    # --- temp_a = -4 ---
    # --- temp_b = -4 ---
    # --- temp_a =  0 ---
    # --- temp_b = -1 ---
    

これまた、同じような結果になってしまうと・・・
SystemVerilogの rand型とrandomize()がどうなのかはチェック出来てませんが、
$randomだと、コールされた順に値が出てくるので、テストベンチ修正(変数追加)したりすると、前のランダム値が再現しなくなるなーっと。


あと、同じタイミングで $random コールした場合とかはシミュレータ依存なんだろうなーっと思ったり。


まぁーランダム使うなら、ゴールを決めてやるべきだとは思うのですが、
ModelSim-ASEだと制限あるので、なんとも。

[Verilog] $dist_uniform

先日「[SystemVerilog][DPI-C] 一様乱数生成を試す。」を書いたら、
Twitterで $dist_uniform があることを教えて頂きました。


っということで、試してみました。

  • LRM(SystemVerilogより参照)
  • $dist_uniform ( seed , start , end )

  • コード

  • module test();
    
      integer seed   = 10 ;
      integer temp_a = 0 ;
      integer temp_b = 0 ;
    
      initial begin
        repeat(10) begin
          temp_a = $random % 5;
          temp_b = $dist_uniform(seed, -4, 4);
          $display("--- temp_a = %2d, temp_b = %2d ---", temp_a, temp_b);
        end
        $finish(2);
      end
    
    endmodule
  • 実行結果

  • # --- temp_a =  3, temp_b = -4 ---
    # --- temp_a = -4, temp_b = -4 ---
    # --- temp_a = -4, temp_b =  1 ---
    # --- temp_a = -4, temp_b =  4 ---
    # --- temp_a =  2, temp_b = -1 ---
    # --- temp_a =  2, temp_b =  2 ---
    # --- temp_a = -1, temp_b =  3 ---
    # --- temp_a = -4, temp_b = -2 ---
    # --- temp_a =  1, temp_b =  0 ---
    # --- temp_a =  4, temp_b =  4 ---
    


ちなみに、seed引数は inout型らしいので直接値を記述することは禁止っぽいです。
更に、ModelSim-ASEでシミュレーション出来て椅子から転げ落ちています。

[Verilog] 組み合わせ回路記述の罠(その3)

[Verilog] 組み合わせ回路記述の罠(その1)
[Verilog] 組み合わせ回路記述の罠(その2)


の続きで、結論です。
ソースを書き換えました。↓

module testbench();

  reg [2:0] control = 0;
  reg tb_a = 0, tb_b = 0;
  reg tb_c = 0, tb_d = 1;

  task automatic print (input in);
    if(in==0)
      $display("Call a - @%0t control = '%3b, tb_a = %0b, tb_b = %0b"
               , $time, control, tb_a, tb_b);
    else
      $display("Call b - @%0t control = '%3b, tb_a = %0b, tb_b = %0b"
               , $time, control, tb_a, tb_b);
  endtask

  initial begin
    #10;
    control = 'b001; #10; // print();
    control = 'b010; #10; // print();
    control = 'b110; #10; // print();
    control = 'b101; #10; // print();
    $finish();
  end

  always @(control, tb_c) begin
    tb_a = 0; // ★
    tb_b = 0; // ★
    casex (control)
      3'b00x : tb_a = 1 ;
      3'b1xx : if(tb_c) tb_b = 1 ;
    endcase
  end

  always @(tb_a, tb_d) begin
    print(0);
    tb_c = 0; // ★
    if(tb_d) tb_c = 1;
  end

  always @(tb_b) begin
    print(1);
  end

endmodule


実行結果

:
# Call a - @0 control = '000, tb_a = 1, tb_b = 0
:
:
# Call a - @0 control = '000, tb_a = 1, tb_b = 0
# Call a - @0 control = '000, tb_a = 1, tb_b = 0
# ** Error: (vsim-3601) Iteration limit reached at time 0 ns.

※エラーにならずに、無限ループに陥るシミュレータもあります。


動作を説明すると、tb_a と tb_c が今後に動いてるというようになります。
つまり。

tb_a = 0 -> tb_a = 1 -> (34行目always) tb_c = 0 -> tb_c = 1 -> (25行目always) tb_a = 0 -> ...

このようなことが起きないためには、以下のような書き方をしたほうがいいでしょう。

  always @(control, tb_c) begin
    casex (control)
      3'b00x : begin
        tb_a = 1 ;
        tb_b = 0 ;
      end
      3'b1xx :
       if(tb_c) begin
         tb_a = 0 ;
         tb_b = 1 ;
      end
      default : begin
        tb_a = 0;
        tb_b = 0;
      end
    endcase
  end

  always @(tb_a, tb_d) begin
    print(0);
    if(tb_d) tb_c = 1;
    else     tb_c = 0;
  end


VHDLの場合は?

ちょっと端折ってますが、こんな感じです。↓
VHDLのソースでは私はよく見かける記述スタイルです。
もちろん、Verilog HDLのようには動きません。

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_textio.all;
use std.textio.all;

entity testbench is
end testbench;

architecture SIM of testbench is

signal control : std_logic_vector(2 downto 0) := (others=>'0');
signal tb_a : std_logic := '0';
signal tb_b : std_logic := '0';
signal tb_c : std_logic := '0';
signal tb_d : std_logic := '1';

begin

  process
  begin
    wait for 10ns;
    control <= "001"; wait for 10ns;
    control <= "010"; wait for 10ns;
    control <= "110"; wait for 10ns;
    control <= "101"; wait for 10ns;
    wait;
  end process;

  process(control, tb_c) begin
    tb_a <= '0';
    tb_b <= '0';
    case  control is
      when "000" | "001" => tb_a <= '1';
      when "100" | "101" | "110" | "111" =>
        if (tb_d = '1') then
          tb_b <= '1';
        end if;
      when others => tb_a <= '0';
    end case;
  end process;

  process(tb_a, tb_d)
    variable L : line;
  begin
    write(L, "tb_a = " & to_string(tb_a));
    writeline(output, L);

    tb_c <= '0';
    if(tb_d) then
      tb_c <= '1';
    end if;
  end process;

end SIM;


まとめ

Verilog HDLの組み合わせ記述において、最初に初期値を書くという
記述スタイルに「ノー」という気はありません。
ただ、そういった現象が起きるというのを知らないと
思わぬところでハマってしまうかと思います。


ちなみに、私なら書かないかな~

続きを読む

プロフィール

Kocha

Author:Kocha
なんでもチャレンジ!(^o^)/
E-mail
github:Kocha
イベントカレンダー

カレンダー
10 | 2017/11 | 12
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
カテゴリ
OVP (4)
最新記事
最新コメント
アーカイブ
リンク
Twitter
アクセス人数