スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

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


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


追記

HDLご存知の方は Verilog HDLと例と VHDLの記述例で
明らかに対比するのはおかしいと思ったと思います。
それは、ブロッキングとノンブロッキングの違いだと思います。


すいません。これは明らかに私が書いたミスになります。
しかし、Verilog HDLに関して言えば、ブロッキングであれ、
ノンブロッキングであれ、これまで題材としてきた記述は
あまりよろしくないかと思います。


理解不足等あれば、私も勉強中の身なので、
Twitterなり、Blogへのコメントなりでご意見いただければ幸いです。

関連記事

コメントの投稿

非公開コメント

プロフィール

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
アクセス人数
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。