[verilog][wreal] wrealを使ったアナログ風シミュレーション
この記事は、HDL Advent Calendar 2013の5日目の記事です。
こんばんは@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に寄贈を参照して下さい)に寄贈しています。そして、SystemVerilog2012にめでたく採用された、というストーリーだと思うのですが、残念ながら、この辺がどうなっているのか、よくわかりません。エロい人教えて下さい。
では、シミュレーション
それでは、このwrealを使って、早速シミュレーションをしてみましょう。今回は、アナログの王道ADC/DACのモデルを使って、それをModelSim-ASEでシミュレーションしたいと思います。
ちなみに、今回使用するのは、ModelSimですが、このWrealの機能は、Icarusでも実装されています(要は、実装が簡単なのですね)。他にもC社さんはもちろんのこと、S社さんのシミュレータでも使用できます。
ADCのモデル
今回はファンクションだけの非常にシンプルなモデルです。
`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もさらにシンプルなモデルです。
`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に入力して、アナログ信号に変換します。
`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の信号はそのままでは表示されません。その際には、波形名を右クリックして、フォーマットをアナログにしてあげましょう。
最後に
ということで、wrealいかがでしたでしょうか? 実数値をモジュール間で渡せるからって、何がおいしいの? と思われると思います。活用先としては、C社さんがよく言っているように、アナログモジュールにおけるアルゴリズムの設計(従来、MATLABでやっていたようなやつですね)というのが、まずは最初だと思います。今回は、ADC/DACなので、特に意味がないのですが、ΔΣADCのアーキテクチャの設計には、このwrealはぴったしにハマります。また、PLLなども信号処理の要素が強いので、いい応用になると思います。実際に、Event-Driven型のPLLのモデルを作って、ジッタの注入を行って、ループ特性の最適化を図る、なんて論文は出ています。
もう一つの活用先としては、デジタルの高度な検証手法を用いて、Mixed-Signalの検証を行う、というのもよいと思います。むしろVerilog単体で動かすことができるので、こちらの方が向いているかなぁ、とボクは思います。
最後に2
約1年ぶりにブログを書きました。ここ最近、アウトプットをサボっていたなぁ、と感じています。でも、Hatena Blogに移行するいい機会になりましたw あと、Markdown記法を勉強するのも。
明日は、最も神に近いHDLerである@natsutanさんですね。どんな神業を披露してくれるのか、非常に楽しみです。