xsim (Vivadoシミュレータ)

# 概要
バージョン: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へのエイリアスで宣言されているため

```vhdl:
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)で代用可能

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

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

```vhdl:
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](https://forums.xilinx.com/t5/Simulation-and-Verification/xsim-VHDL-2008-function-resolusion-limit-returns-12-ps/td-p/856162)
VHDL-2008で追加されたresolusion_limitは >0 な時間を返すはずが、あろうことか負の時間である-12psを返す
そのため、シミュレータでの最小時間だけ待つ下記のコードが実行時エラーになる

```vhdl:
use std.env.all;
 ...
wait for resolution_limit;  --エラー wait for -12 ps になる
```
下記で代用可

```vhdl:
delay_length'succ(delay_length'low)
```
厳密には正しくないかもしれないが、ModelSimでも複数のResolution設定で動作した

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

```vhdl:
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で何がしたいかというと、ローカル変数で宣言した分周カウンタのカウント終了値をローカル変数の宣言から取り出したい

```vhdl:
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;
```

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

```vhdl:
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でコンパイラが落ちて、どこに問題があるのかも分からなかったから。

```vhdl:
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 変数トレースのサポートについて](Vivado シミュレータでの VHDL 変数トレースのサポートについて)
いつかサポートされると良いな
分周カウンタなんかはprocessのローカル変数にしたい

```vhdl:
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で代用可能、しかし記述が増える

```vhdl:
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;
```