[verilog][wreal] wrealを使ったアナログ風シミュレーション

この記事は、[HDL Advent Calendar 2013](http://qiita.com/advent-calendar/2013/hdl)の5日目の記事です。

こんばんは[@mizutomo](http://twitter.com/mizutomo)です。参加者の皆様がデジタルバリバリなので、gkbrですが、ぼくは、デジタルのことはほとんど知らないので、臆せずにアナログ寄りの記事を書いていきたいと思います。

wrealって何よ?
================

最近、巷で話題のwrealですが(えっ、聞いたことがないって?)、そもそもこいつは何なのでしょう? ともったいぶってもしょうがないので、結論から言いますと、実数値が伝搬できるwireです。そもそも、wrealはwired realの略で、realと入っているので、一瞬reg型かなぁ、と思ってしまいますが、れっきとしたwire型の端子です。


えっ、それだけなの?　って感じですが、本当にそれだけなのです。そもそも、それだったら、VHDLは実数値を伝搬できるし、SystemVerilogだって。。。と思われると思いますが、まさにその通りです。ただ、Verilog HDLで、ってところに価値があるのだと思います(日本のメーカーさんは、Verilog大好きですもんね)。そして、アナログのソルバを使わずに、デジタルのソルバだけで、なんちゃってアナログを表現できるところに価値があります(これで、デジタル屋さんも大丈夫)。


さて、このwrealですが、元々はVerilog-AMSで採用された規格(と言っていいものかな?)です。その後、C社さんがAccellera(詳細は、[Cadence，Verilog-AMSの実数値モデリング機能の拡張仕様をAccelleraに寄贈](http://techon.nikkeibp.co.jp/article/NEWS/20100423/182134/)を参照して下さい)に寄贈しています。そして、SystemVerilog2012にめでたく採用された、というストーリーだと思うのですが、残念ながら、この辺がどうなっているのか、よくわかりません。エロい人教えて下さい。


では、シミュレーション
=============================

それでは、このwrealを使って、早速シミュレーションをしてみましょう。今回は、アナログの王道ADC/DACのモデルを使って、それをModelSim-ASEでシミュレーションしたいと思います。


ちなみに、今回使用するのは、ModelSimですが、このWrealの機能は、Icarusでも実装されています(要は、実装が簡単なのですね)。他にもC社さんはもちろんのこと、S社さんのシミュレータでも使用できます。


ADCのモデル
---------------------

今回はファンクションだけの非常にシンプルなモデルです。

```verilog:adc.v
`timescale 1ns/1ps

module ADC_8bit (DOUT, AIN, CLK, VDD, VSS);
  output [7:0] DOUT;
  input  CLK;
  input  AIN,VDD,VSS;

  wire  [7:0] DOUT;
  wire  CLK;
  wreal AIN,VDD,VSS;   // AIN, VDD, VSS has continous value

  real LSB;
  integer dig_val;

  always @(VDD, VSS) begin
    LSB = (VDD-VSS) / (2**8-1);
  end

  always @(CLK) begin
    if (AIN <= VSS)
      dig_val = 8'b0;
    else if (AIN >= VDD)
      dig_val = 8'b11111111;
    else
      dig_val = (AIN-VSS) / LSB;
  end
  assign DOUT = dig_val;
endmodule
```

入力電圧を1bitの電圧で割って、それをデジタルコードにassignしているだけです。

DACのモデル
---------------------

DACもさらにシンプルなモデルです。

```verilog:dac.v
`timescale 1ns/1ps

module DAC_8bit (AOUT, DIN, CLK, VDD, VSS);
  input [7:0] DIN;
  input CLK,VDD,VSS;
  output AOUT;

  wire [7:0] DIN;
  wire CLK;
  wreal AOUT,VDD,VSS;   // AOUT, VDD, VSS has contious value

  real LSB, ana_val;

  always @(VDD, VSS) LSB = (VDD-VSS) / (2**8-1);

  always @(CLK) ana_val <= VSS + LSB*DIN;

  assign  AOUT = ana_val;
endmodule
```

こちらもデジタルコードを10進数にして、1bit分の電圧を書けているだけです。

テストベンチ
-----------------

今回は単純なsin波を入れて、それをADCでデジタルコードに変換して、さらにそのデジタルコードをDACに入力して、アナログ信号に変換します。

```verilog:top.v
`timescale 1ns/1ps
`define M_TWO_PI 6.283185307179586

module top ();
  wreal AIN, AOUT, VDD, VSS;
  wire [7:0] DOUT;
  wire CLK;

  ADC_8bit ADC_8bit (DOUT, AIN,  CLK, VDD, VSS);
  DAC_8bit DAC_8bit (AOUT, DOUT, CLK, VDD, VSS);

  real reg_ain, reg_vdd, reg_vss;
  real freq=500e+3, phase=0;
  reg reg_clk;

  initial begin
    $dumpfile("wreal.vcd");
    $dumpvars();
  end

  initial begin
    reg_clk = 0;
    reg_vdd = 3.3;
    reg_vss = 0.0;
    reg_ain = 0.0;
    #30
    while ($realtime*1e-9 < 6e-6) begin
      #2
      phase = phase+2e-9*freq;
      if (phase>1) phase=phase-1;
      reg_ain=1.8*(1+$sin(`M_TWO_PI*phase));
    end
    #200 $finish;
  end

  always #2 reg_clk = ~reg_clk;

  assign AIN = reg_ain;
  assign CLK = reg_clk;
  assign VDD = reg_vdd;
  assign VSS = reg_vss;
endmodule
```

wrealの注意点は、reg型ではないということです。あくまでwire型なので、always文の中では使用することができません。そのため、reg型の変数を使って、信号処理を行って、最後にassign文でwireに接続します。


シミュレーションの実行
--------------------------------

今回は、実行にModelSim-ASEを使用します。ただ、そのままコンパイルすると、wrealって何それ? おいしいの? って怒られていまいます。そのため、vlogに-amsオプションを渡してやる必要があります。

> % vlog adc.v -work ./work -ams
> % vlog dac.v -work ./work -ams
> % vlog top.v -work ./work -ams

コンパイルが無事に終了すると、後はvsimでシミュレーションを行うだけです。この時には、特にオプションは不要です。


波形の見方
--------------------------------

波形のそのままModelSimで見ることができます(当たり前ですが)。ただ、ModelSimのデフォルトは、0/1のデジタルの世界なので、当然wrealの信号はそのままでは表示されません。その際には、波形名を右クリックして、フォーマットをアナログにしてあげましょう。

![20131205000357.png](https://qiita-image-store.s3.amazonaws.com/0/33580/9c489b92-34ff-f9ab-a577-bf3624a62c45.png)


最後に
================

ということで、wrealいかがでしたでしょうか? 実数値をモジュール間で渡せるからって、何がおいしいの? と思われると思います。活用先としては、C社さんがよく言っているように、アナログモジュールにおけるアルゴリズムの設計(従来、MATLABでやっていたようなやつですね)というのが、まずは最初だと思います。今回は、ADC/DACなので、特に意味がないのですが、ΔΣADCのアーキテクチャの設計には、このwrealはぴったしにハマります。また、PLLなども信号処理の要素が強いので、いい応用になると思います。実際に、Event-Driven型のPLLのモデルを作って、ジッタの注入を行って、ループ特性の最適化を図る、なんて論文は出ています。

もう一つの活用先としては、デジタルの高度な検証手法を用いて、Mixed-Signalの検証を行う、というのもよいと思います。むしろVerilog単体で動かすことができるので、こちらの方が向いているかなぁ、とボクは思います。


最後に2
===============

約1年ぶりにブログを書きました。ここ最近、アウトプットをサボっていたなぁ、と感じています。でも、Hatena Blogに移行するいい機会になりましたw あと、Markdown記法を勉強するのも。


明日は、最も神に近いHDLerである[@natsutan](http://twitter.com/natsutan)さんですね。どんな神業を披露してくれるのか、非常に楽しみです。