Veriloggenって何だろう(2)LEDチカチカ
Verilog HDLを生成するための記述をpythonで行うことでFPGA回路の生成を楽にする為のライブラリーVeriloggenを使ってみたいと思います。
前回はWindows上に環境を作ったので、さっそくサンプルを動かしてみましょう。
veriloggen サンプルのダウンロード
サンプルは下記のリンクのexamplesにあります。
veriloggenのバージョンアップに応じてサンプルも変わっているようです。インストールしたveriloggenのバージョンのものを見るようにしましょう。
veriloggenのバージョンはAnaconda Promptを開いてverilog環境に切り替え、conda listで見ることができます。
>activate verilog >conda list ・・・ veriloggen 1.2.0 <pip> ・・・
examplesをダウンロードしたい時にはveriloggen全体をtagをバージョンに合わせておいて、「Download ZIP」でまとめてダウンロードするのが良いでしょう。(最新版1.2.0になってます)
Spyderの起動
Pythonをコマンドラインで使うのは面倒なので、Spyderを使いましょう。
「スタート」-「Anaconda3」-「Spyder(verilog)」からSpyderを立ち上げます。
前回の様に仮想環境を設定してあると、標準環境の「Spyder」の他にveriloggenをインストールした環境用に「Spyder(verilog)」が登録されているはずです。
まずはexamplesのled.pyをベースに機能確認をしましょう。
※「Spyder(verilog)」でワーニングが出る時には「Anaconda Navigator」から verilog 仮想環境でSpyderを起動してみてください。
LEDチカチカ
led.pyを読み込むか、新規作成します。分かりやすくするために、少し下記の様に手を加えました。
import veriloggen as vg #%% LEDチカチカ本体のモジュールblinkledを生成(HDL変換のターゲット) def mkLed(): m = vg.Module('blinkled') width = m.Parameter('WIDTH', 8) clk = m.Input('CLK') rst = m.Input('RST') led = m.OutputReg('LED', width) count = m.Reg('count', 32) m.Always(vg.Posedge(clk))( vg.If(rst)( count(0) ).Else( vg.If(count == 1023)( count(0) ).Else( count(count + 1) ) )) m.Always(vg.Posedge(clk))( vg.If(rst)( led(0) ).Else( vg.If(count == 1024 - 1)( led(led + 1) ) )) return m #%% blinkledにクロックとリセット信号をつないでテストするモジュールtestを生成 def mkTest(): m = vg.Module('test') # target instance led = mkLed() # copy paras and ports params = m.copy_params(led) ports = m.copy_sim_ports(led) clk = ports['CLK'] rst = ports['RST'] uut = m.Instance(led, 'uut', params=m.connect_params(led), ports=m.connect_ports(led)) vg.simulation.setup_waveform(m, uut, m.get_vars()) vg.simulation.setup_clock(m, clk, hperiod=5) init = vg.simulation.setup_reset(m, rst, m.make_reset(), period=100) init.add( vg.Delay(1000 * 100), vg.Systask('finish'), ) return m #%% メインルーチン testモジュールをVerilog HDLに変換してシミュレーション if __name__ == '__main__': test = mkTest() verilog = test.to_verilog('tmp.v') print(verilog) sim = vg.simulation.Simulator(test) rslt = sim.run() print(rslt) sim.view_waveform()
緑三角をクリックして led.py を実行すると、ちゃんと動けばフォルダーに Verilog HDL に変換されたファイル tmp.v、iverilog の中間ファイル a.out、vvp でシミュレーションした結果の uut.vcd ができているはずです。
同時に、シミュレーション結果 uut.vcd が読み込まれた状態で gtkwave が立ち上がるはずです。
Veriloggen によって作られた Verilog HDL は tmp.v にありますが、次のようなものです。
module test # ( parameter WIDTH = 8 ) ( ); reg CLK; reg RST; wire [WIDTH-1:0] LED; blinkled #( .WIDTH(WIDTH) ) uut ( .CLK(CLK), .RST(RST), .LED(LED) ); initial begin $dumpfile("uut.vcd"); $dumpvars(0, uut, CLK, RST, LED); end initial begin CLK = 0; forever begin #5 CLK = !CLK; end end initial begin RST = 0; #100; RST = 1; #100; RST = 0; #100000; $finish; end endmodule module blinkled # ( parameter WIDTH = 8 ) ( input CLK, input RST, output reg [WIDTH-1:0] LED ); reg [32-1:0] count; always @(posedge CLK) begin if(RST) begin count <= 0; end else begin if(count == 1023) begin count <= 0; end else begin count <= count + 1; end end end always @(posedge CLK) begin if(RST) begin LED <= 0; end else begin if(count == 1023) begin LED <= LED + 1; end end end endmodule
module blinkled が肝心の部分です。
Veriloggen の Always が Verilog HDL の always になったのが分かります。Veriloggen を使うことで、読み易くはなりましたがほとんど1対1なので行数はほとんど同じで、まだこの段階では今一つな感じです。
とりあえず動いたので今回はここまで。
次回は、モジュールの組み立て方と Always について書いてみます。