LoginSignup
9
4

More than 3 years have passed since last update.

xsim (Vivadoシミュレータ)

Posted at

概要

バージョン:Vivado 2019.1

xsim(Vivadoシミュレータ)使用上のバッドノウハウ
いろいろ言いたいことはあるけど、無償で制限無しの混合言語シミュレーションが出来るのであまり文句は言わない
VHDL-2008のサポート範囲がVivado合成とxsimで違う!、その上どちらかがもう一方のサブセット/スーパーセットという関係でもないので、気を付ける必要がある。
シミュレーションなんてしない、実機デバッグとVivadoロジアナさえあれば万事OKという人は、Vivado合成の方がVHDL-2008のサポート範囲が広いはずなのでご自由に。

そもそもVHDL使うなんて変態か、という意見はごもっとも。でも俺はVHDLが好きだ。(downtoなんて書かせるのと、チン…じゃなくてcomponent宣言を除いて)

使えるはずの記述はModelSim Intel 10.5bで確認
但しModelSimもエラーチェックが緩い所があり、本来エラーにすべき記述がスルーされてしまう事もあるのでModelSimが絶対正しいとは限らない。

to_string()が使えない (VHDL-2008)

未サポートというエラーになる
ERROR: [XSIM 43-4187] (中略) : The "Vhdl 2008 to_string Operator" is not supported yet for simulation.

合成でも同様。まあ、合成では使わないけど
ERROR: [Synth 8-5883] invalid operator type for expression

ieee.std_logic_1164で宣言される以下の変換関数は使えるが、to_bstringだけは使えない
to_stringへのエイリアスで宣言されているため

function TO_OSTRING (VALUE : STD_ULOGIC_VECTOR) return STRING; -- 8進文字列に変換 OK
function TO_HSTRING (VALUE : STD_ULOGIC_VECTOR) return STRING; --16進文字列に変換 OK

alias TO_BSTRING is TO_STRING [STD_ULOGIC_VECTOR return STRING]; --2進文字列に変換 
                                                                 --実体はto_stringなのでNG

integer,timeのようなscalar型ならto_stringはT'image(x)で代用可能

variable i : integer;
variable t : time;
 ...
report integer'image(i);
report time'image(t);

型によってto_stringと使い分けを考えるのが面倒なので、自分はパッケージを作ってそこでto_string()として実装してる。

package sim_pkg is
  function to_string(v: integer) return string;
  function to_string(v: time) return string;
package body sim_pkg is
  function to_string(v: integer) return string is
  begin
    return integer'image(v);
  end;

  function to_string(v: time) return string is
  begin
    return time'image(v);
  end;
end;

std.env.resolution_limitが-12psを返す (VHDL-2008)

Xilinxフォーラム xsim:VHDL-2008 function resolusion_limit returns -12 ps
VHDL-2008で追加されたresolusion_limitは >0 な時間を返すはずが、あろうことか負の時間である-12psを返す
そのため、シミュレータでの最小時間だけ待つ下記のコードが実行時エラーになる

use std.env.all;
 ...
wait for resolution_limit;  --エラー wait for -12 ps になる

下記で代用可

delay_length'succ(delay_length'low)

厳密には正しくないかもしれないが、ModelSimでも複数のResolution設定で動作した

宣言部以外で'subtypeにさらにattributeを適用するとエラー

コンパイルは出来るが、エラボレーションでEXCEPTION_ACCESS_VIOLATIONが発生して内部エラーになってしまう
合成でもエラーになるので、そもそも'subtypeがちゃんとサポートされていないらしい

variable cnt   : natural range 0 to 3;
subtype  cnt_t : cnt'subtype; --cntの型になる 合成でもOK

constant cnt_t_high : integer := cnt_t'high;       --OK:3
constant cnt_high   : integer := cnt'subtype'high; --OK:3 ここでは使える
                                                   --合成では unsupported attribute でエラーになる
  ...

if (cnt = cnt_t'high)       --OK
if (cnt = cnt'subtype'high) --エラー
cnt := cnt'subtype'high;    --エラー

'subtypeで何がしたいかというと、ローカル変数で宣言した分周カウンタのカウント終了値をローカル変数の宣言から取り出したい

process
  variable cnt : natural range 0 to 2;  --分周カウンタ 2で終了
begin
  wait until rising_edge(CLK);
  --cnt = 2と書かずに済む
  --cntの宣言を変更すれば条件も合わせて変わる
  if (cnt = cnt'subtype'high) then
    CLK_div <= not CLK_div;  --分周クロック反転
    cnt := 0;
  else
    cnt := cnt + 1;
  end if;
end;

ちゃんと定数を宣言すれば同じ事は出来るし、本来こうすべきだけどテストベンチのような書き捨てのコードで楽をしたい

process
  constant end_cnt : natural := 2;  --分周カウンタ終了値
  variable cnt     : natural range 0 to end_cnt;  
begin
  wait until rising_edge(CLK);
  if (cnt = end_cnt) then
    CLK_div <= not CLK_div;  --分周クロック反転
    cnt := 0;
  else
    cnt := cnt + 1;
  end if;
end;

順次処理領域でsignalに対して選択代入文が使えない (VHDL-2008 xsim制限)

xsimでは未サポートというエラーになる。合成はOK。
ERROR: [XSIM 43-4187] (中略) : The "Vhdl 2008 Sequential Conditional Signal Assignment" is not supported yet for simulation.
エラー出してくれるだけマシかもね。以前(2018.1くらいの頃)だと恐怖のInternal Errorでコンパイラが落ちて、どこに問題があるのかも分からなかったから。

architecture rtl of tb is
begin
  q <= a when (sel = '0') else b;  --同時処理領域では以前から使える

  process (all)
    variable v: sig_logic;
  begin
    v := a when (sel = '0') else b;  --変数代入は出来る
    q <= a when (sel = '0') else b;  --信号代入はエラー ERROR: [XSIM 43-4187]
  end process;
end;

variableが波形ウインドウに追加出来ない (xsim制限)

AR#63628:Vivado シミュレータでの VHDL 変数トレースのサポートについて
いつかサポートされると良いな
分周カウンタなんかはprocessのローカル変数にしたい

process
  variable cnt : natural range 0 to 3;  --分周カウンタ variableなので波形が見られない
begin
  wait until rising_edge(CLK);
  if (cnt = 3) then
    CLK_div <= not CLK_div;  --分周クロック反転
    cnt := 0;
  else
    cnt := cnt + 1;
  end if;
end;

ローカル変数というか、スコープを限定したオブジェクトはブロックのローカルsignalで代用可能、しかし記述が増える

block_label: block
  signal cnt : natural range 0 to 3;  --ブロックのローカルsignalに変更 波形が見られる
begin
  process begin
    wait until rising_edge(CLK);
    if (cnt = 3) then
      CLK_div <= not CLK_div;  --分周クロック反転
      cnt <= 0;
    else
      cnt <= cnt + 1;
    end if;
  end;
end block;
9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4