この記事は、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さんですね。どんな神業を披露してくれるのか、非常に楽しみです。