ポートと内部信号のリストから、verilogファイル出力

ポートと内部信号のリストから、verilogファイルを決まったインデントで生成したいと思いました。 そのためのpythonコードを作成したので、共有しておきます。

まず、入力するcsvファイル(ports.csv)です。以下のように(moduleは除く)、<1:種類>, <2:名前>, <3:ビット幅>として1行ずつ記述します。moduleは、<1:module>, <2:名前>のみです。

module, hogehoge_dut
input,clk,1
input,rst,1
input,A,10
input,AA,11
output,B,9
wire,w_out,9
reg,r_V,10
reg,r_Q,9
reg,r_A,99

port.csvを第一引数で読み込ませる、以下のPythonコードを作成しました。

import csv
import sys

EDUP ="ports declaration has duplication."

def str_add_space_to_input_reg (kind):
    kind = str(kind)
    return kind + " " if ( len(kind) == 3 or len(kind) == 5 ) else kind

def str_bit_width (width):
    _width = int(width)
    if   _width >= 11:
        return "[{width}:0]".format(width=_width)
    elif _width >=  2:
        return "[ {width}:0]".format(width=_width-1)
    elif _width ==  1:
        return "      "

def chk_duplication(_list,cnt):
    # port宣言が重複していたら停止
    if len(_list) != len(set(_list)):
        print ("ERROR: {E} (csv ({ln}) SIG: {nm} )".format(E=EDUP,ln=cnt,nm=_list[-1]))
        exit(1)
    else:
        return

# 入力ポートと出力ポートのリストを初期化
module_name = ""
ports = []
internal_sigs = []
signal_names = []

# CSVファイルを開く
with open(sys.argv[1], newline='') as csvfile:
    portreader = csv.reader(csvfile, delimiter=',')

    cnt = 0
    # 各行を処理
    for row in portreader:
        cnt += 1
        kind  = row[0].replace(' ','')
        name  = row[1].replace(' ','')

        if kind == "module":
            module_name = name
        else:
            width = row[2].replace(' ','')

            signal_names.append(name)
            chk_duplication(signal_names, cnt)

            kind_str = str_add_space_to_input_reg(kind)
            width_str = str_bit_width(width)
            if kind == "input" or kind == "output":
                ports.append        (" "*8+"{kind} {wt} {nm},".format(kind=kind_str,wt=width_str,nm=name))
            elif kind == "reg" or kind == "wire":
                internal_sigs.append(" "*4+"{kind} {wt} {nm};".format(kind=kind_str,wt=width_str,nm=name))

ports[len(ports)-1] = ports[len(ports)-1][:-1]

# ポートと内部信号の宣言を生成
ports_declaration         = '\n'.join(ports)
internal_sigs_declaration = '\n'.join(internal_sigs)

# モジュールの宣言を生成
module_declaration = '''module {module} (
{ports}
);

// モジュールの本体
{internal_sigs}

endmodule'''.format(module=module_name,ports=ports_declaration, internal_sigs=internal_sigs_declaration)

# 宣言を表示
print(module_declaration)

# CSVファイルを開く
with open(module_name+".v",'w') as outfile:
    outfile.write(module_declaration)

次に以下のコマンドを実行します。(llinuxの場合)

# python3 module.py ports.csv

以下、出力結果{module名}.vファイルです。

module hogehoge_dut (
        input         clk,
        input         rst,
        input  [ 9:0] A,
        input  [11:0] AA, 
        output [ 8:0] B
);

// モジュールの本体
    wire [ 8:0] w_out;
    reg  [ 9:0] r_V;
    reg  [ 8:0] r_Q;
    reg  [99:0] r_A;

endmodule

以上。どうでしょうか?