Veriloggenって何だろう(7)Parameter Delay Mux Sra
Verilog HDL を生成するための記述を python で行うことで FPGA 回路の生成を楽にする為のライブラリー Veriloggen を使ってみたいと思います。
今回はこう書くとこうなるという小技をいくつか、忘れないようにその部分だけ書いておきます。
- 便利関数の定義
- パラメータリストの作り方
- 慣性遅延(inertial delay)
- 伝播遅延(transport delay)
- 連接演算子 { } の書き方
- マルチプレクサ Mux
- 論理シフトと算術シフト
便利関数の定義
veriloggen_util.pyという名前で下記の関数を定義しておきます。
import subprocess import veriloggen as vg # %% def addtimescale(fname): ''' 指定されたファイルの先頭にtimescaleを挿入 ''' with open(fname) as f: l = f.readlines() l.insert(0,"`timescale 1ns/1ns \n") with open(fname, mode='w') as f: f.writelines(l) # %% def dset(t): ''' 代入分遅延用delayをEmbeddedCodeで埋め込み ''' return vg.EmbeddedCode('#{}'.format(t)) # %% def num2h(x, bit): ''' 数字を16進verilogフォーマット文字に変換してEmbeddedCodeで埋め込み ''' n = int((bit+3)/4) st = "{0}'h{1:0>"+str(n)+"x}" return vg.EmbeddedCode(st.format(bit,x)) # %% def num2b(x, bit): ''' 数字を16進verilogフォーマット文字に変換してEmbeddedCodeで埋め込み ''' n = bit st = "{0}'b{1:0>"+str(n)+"b}" return vg.EmbeddedCode(st.format(bit,x)) # %% def view_waveform_gtkwave(filename='uut.vcd', background=False): ''' シミュレーション結果の表示 ''' cmd = [] cmd.append('gtkwave') cmd.append('--giga') cmd.append(filename) if background: cmd.append('&') subprocess.run(cmd) # %% def run_iverilog(inputfile, top=None, outputfile='a.out'): ''' iverilog コンパイル ''' cmd = [] cmd.append('iverilog') cmd.append(inputfile) if top is not NONE: cmd.append('-s') cmd.append(top) cmd.append('-o') cmd.append(outputfile) subprocess.run(cmd) # %% def run_vvp(inputfile='a.out'): ''' vvp シミュレーション実行 ''' cmd=[] cmd.append('vvp') cmd.append(inputfile) subprocess.run(cmd) # %% def delete_file(fname): ''' ファイル削除 ''' cmd = [] cmd.append('del') cmd.append('fname') subprocess.run(cmd,shell=True)
パラメータリストの作り方
python側で作った値のリストをパラメータとして埋め込むことができます。
import veriloggen_util as vu para = [i*7 for i in range(12)] paralist = [m.Parameter('p{0:0>2d}'.format(i), vu.num2b(para[i], 8)) for i in range(len(para))]
Verilog展開結果
parameter p00 = 8'b00000000, parameter p01 = 8'b00000111, parameter p02 = 8'b00001110, parameter p03 = 8'b00010101, parameter p04 = 8'b00011100, parameter p05 = 8'b00100011, parameter p06 = 8'b00101010, parameter p07 = 8'b00110001, parameter p08 = 8'b00111000, parameter p09 = 8'b00111111, parameter p10 = 8'b01000110, parameter p11 = 8'b01001101
使い方は
seq.add(count(count+paralist[1]))
の様にpythonのリストの様に使えます。
展開されると こんな感じ
count <= count + p01;
慣性遅延(inertial delay)
代入文の遅延の記述方法が分からなかったので、dset(t)という関数を定義してEmbeddedCode( )で#付きの数字を埋め込むことにします。これにより慣性遅延は次のように書けます。
seq.add(data2(data1, ldelay=vu.dset(5))
展開すると
#5 data2 <= data1;
の様に式の左側にdelayが挿入されます。
伝播遅延(transport delay)
伝搬遅延は次のようにして書けます。
seq.add(data2(data1, rdelay=vu.dset(5)))
展開すると
data2 <= #5 data1;
の様に式の右側にdelayが挿入されます。
連接演算子 { } の書き方
連接演算子はVeriloggenのCatで作ることができます。
m.Assign(data2(vg.Cat(data1,vu.num2b(3,4))))
展開すると
assign data2 = { data1, 4'b0011 };
となります。
マルチプレクサ Mux
マルチプレクサはveriloggenのMuxを使って作成することができます。
下記の様にして絶対値変換が書けます。
pythonの便利なところとしてdata[-1]と言うように書いて最上位bitが指定できます。
data = m.Reg('data', 8 ,signed=True) absdata = m.Wire('absdata', 8, signed=True) ........................... m.Assign(absdata(vg.Mux(data[-1], ~data+1, data)))
展開すると次のようになります。
reg signed [8-1:0] data; wire signed [8-1:0] absdata; ........................... assign absdata = (data[7])? ~data + 1 : data;
論理シフトと算術シフト
veriloggenにはシフトのために
論理左シフト: Sll
論理右シフト: Srl
算術右シフト: Sra
があります。
それぞれ次のように書けます。
seq.add(data2(vg.Sll(data1,1))) seq.add(data2(vg.Srl(data1,1))) seq.add(data2(vg.Sra(data1,1)))
展開すると次のようになります。
data2 <= data1 << 1; data2 <= data1 >> 1; data2 <= data1 >>> 1;
算術シフトが機能するためには変数はsignedで定義されていなくてはいけません。