見出し画像

OpenMPW Walkthrough: 3 自分の設計を組み込む

この記事では自分の設計を user_project_wrapper に組み込むためにどういうファイルを用意るえばいいかを説明します.

1.RTLファイルの作成

1.1 ユーザモジュールの作成

デジタル回路設計の核になるのは HDL による RTL (Register Transfer Level) の設計です.Caravel のフローでは Verilog を使用します.
トップディレクトリの下の verilog/rtl ディレクトリ (この例では caravel_tutorial/verilog/rtl/) に verilogファイルを置きます.ここでは簡単に 8ビットのカウンタを作ることにして,counter8.v を以下の内容で作成します.

`default_nettype none

module counter8(
`ifdef USE_POWER_PINS
        inout vccd1,
        inout vssd1,
`endif
        input wire wb_clk_i,
        input wire wb_rst_i,
        output wire [7:0] io_out,
        output wire [7:0] io_oeb
);

        reg [7:0] count;
        assign io_out = count;
        assign io_oeb = 8'b00000000;

        always @(posedge wb_clk_i) begin
        if (wb_rst_i) begin
                count <= 0;
        end else begin
                count <= count + 1;
            end
        end
endmodule

`default_nettype wire

電源ピンの記述など,通常の Verilogでは不要な記述がいくつか入っています.必ずしもなくても動くようですが,電源ピンも記述しておくことが推奨されています.また,io_oeb は Output Enable Bar なので,有効にする出力ピンに対応するピンを 0に落とします (Enable Bar なので 0 に落とすと有効).スクラッチから書くより,user_prj_example.v を改造していく方が確実だと思います.

1.2 counter8 を使うように修正

次に,同じディレクトリにある user_project_wrapper.v を counter8.v に対応するように変更します.変更するのは

/--------------------------------------/
/* User project is instantiated  here   /
/--------------------------------------*/

の下の部分です.user_prj_example を counter8 に変更し,不要なピンを消しましょう.

counter8 counter8 (
`ifdef USE_POWER_PINS
        .vccd1(vccd1),  // User area 1 1.8V power
        .vssd1(vssd1),  // User area 1 digital ground
`endif

    .wb_clk_i(wb_clk_i),
    .wb_rst_i(wb_rst_i),

    // IO Pads

    .io_out(io_out[15:8]),
    .io_oeb(io_oeb[15:8])
);

io_out と io_oeb が 0からでなく 8 からになっているのは,0~7 の8本は Dual mode だから使わない方がよいからです.(と OpenMPW-6 Walkthrough で言っています.使うとどんなトラブルが起こるのかは未確認.)

また,verilog/includes/includes.rtl.caravel_user_project で counter8.v を読み込むように変更します.

# Caravel user project includes
-v $(USER_PROJECT_VERILOG)/rtl/user_project_wrapper.v
-v $(USER_PROJECT_VERILOG)/rtl/counter8.v

2.テストの設定

2.1 テストの設定

verilog/dv/ の下に counter8 用のテストの設定をします.dv/io_ports を dv/counter8 の名前でコピーし,中のファイルを修正します.
まず io_ports.c を counter8.c にリネームし,ファイル末尾付近のIOの番号を 0~7 から 8~15 に変えます.これは io_out[15:8] に対応します.

        // Configure lower 8-IOs as user output
        // Observe counter value in the testbench
        reg_mprj_io_8 =  GPIO_MODE_USER_STD_OUTPUT;
        reg_mprj_io_9 =  GPIO_MODE_USER_STD_OUTPUT;
        reg_mprj_io_10 =  GPIO_MODE_USER_STD_OUTPUT;
        reg_mprj_io_11 =  GPIO_MODE_USER_STD_OUTPUT;
        reg_mprj_io_12 =  GPIO_MODE_USER_STD_OUTPUT;
        reg_mprj_io_13 =  GPIO_MODE_USER_STD_OUTPUT;
        reg_mprj_io_14 =  GPIO_MODE_USER_STD_OUTPUT;
        reg_mprj_io_15 =  GPIO_MODE_USER_STD_OUTPUT;

次に io_ports_tb.v を counter8_tb.v にリネームし,ファイル内の "io_ports" をすべて "counter8" に置き換えます.
モジュール名,dumpfile,dumpvars,spiflash の4箇所です.

また,IOの番号を 15:8 に変更します.以下の箇所です.

        assign mprj_io_0 = mprj_io[15:8];

これで準備は完了です.

2.2 RTLシミュレーションと結果の確認

トップディレクトリ (caravel_tutorial/) に移動し,make verify-counter8-rtl を実行します.パスするはずです.

make verify-counter8-rtl

これで verilog/dv/counter8/ の下にいくつかのファイルが生成されます.

verify-rtl 実行後

RTL-counter8.vcd  が波形ファイルで,gtkwave で波形を確認できます.gtkwave RTL-counter8.vcd  で起動します.

gtkwave を起動

counter8_tb を選択するとピンが全部表示されるので,とりあえず全部選択して Append を押します.右側のペインに波形が表示されます.

ピンを選んで波形を表示

この波形ファイルは電源が立ち上がるシーケンスがすべて含まれているので,カウンターの信号が変化するのは波形の最後の方だけです.最後の部分を拡大すると,カウンターとして動作していることが確認できます.

カウンター動作

3.合成

動作が確認できたので,OpenLane を使って GDS を作成します.ここからは openlane/ ディレクトリの下の作業になります.

3.1 counter8 の合成

まず counter8 のマクロを作成します.

openlane/user_proj_example/ を openlane/counter8/ の名前でコピーし,その中の config.tcl  ファイルを編集します."user_proj_example" を "counter8" に置換します.DESIGN_NAME と,VERILOG_FILES の2箇所です.また,PL_TARGET_DENSITY を 0.4 に変えておきます.この値が小さいままだと,OpenLANE が合成に失敗します.diff を取るとこんな感じです.

@@ -18,11 +18,11 @@

 set script_dir [file dirname [file normalize [info script]]]

-set ::env(DESIGN_NAME) user_proj_example
+set ::env(DESIGN_NAME) counter8

 set ::env(VERILOG_FILES) "\
        $::env(CARAVEL_ROOT)/verilog/rtl/defines.v \
-       $script_dir/../../verilog/rtl/user_proj_example.v"
+       $script_dir/../../verilog/rtl/counter8.v"

 set ::env(DESIGN_IS_CORE) 0

@@ -36,7 +36,7 @@
 set ::env(FP_PIN_ORDER_CFG) $script_dir/pin_order.cfg

 set ::env(PL_BASIC_PLACEMENT) 0
-set ::env(PL_TARGET_DENSITY) 0.05
+set ::env(PL_TARGET_DENSITY) 0.4

 # Maximum layer used for routing is metal 4.
 # This is because this macro will be inserted in a top level (user_project_wrapper)

これでトップディレクトリに戻り,make counter8 を実行すると counter8 の GDS ができあがります.klayout で確認すると,下図のようになります.単純な 8ビットカウンタなので,user_proj_example よりさらにスカスカです.

counter8.gds

3.2 user_project_wrapper の合成

前の記事で説明した通り,テープアウトするには counter8 を user_project_wrapper に組み込む必要があります.counter8 の合成と同様に,openlane/user_project_wrapper/config.tcl を編集します."user_proj_example" を "counter8" に置き換えます.VERILOG_FILES_BLACKBOX,EXTRA_LEF,EXTRA_GDS_FILES の3箇所です.
また,CLOCK_NET,FP_PDN_MACRO_HOOKS の2箇所については "mprj" を "counter8" に置き換えます.diff をとるとこんな感じ.

@@ -39,14 +39,14 @@

 ## Clock configurations
 set ::env(CLOCK_PORT) "user_clock2"
-set ::env(CLOCK_NET) "mprj.clk"
+set ::env(CLOCK_NET) "counter8.clk"

 set ::env(CLOCK_PERIOD) "10"

 ## Internal Macros
 ### Macro PDN Connections
 set ::env(FP_PDN_MACRO_HOOKS) "\
-       mprj vccd1 vssd1 vccd1 vssd1"
+       counter8 vccd1 vssd1 vccd1 vssd1"

 ### Macro Placement
 set ::env(MACRO_PLACEMENT_CFG) $script_dir/macro.cfg
@@ -54,13 +54,13 @@
 ### Black-box verilog and views
 set ::env(VERILOG_FILES_BLACKBOX) "\
        $::env(CARAVEL_ROOT)/verilog/rtl/defines.v \
-       $script_dir/../../verilog/rtl/user_proj_example.v"
+       $script_dir/../../verilog/rtl/counter8.v"

 set ::env(EXTRA_LEFS) "\
-       $script_dir/../../lef/user_proj_example.lef"
+       $script_dir/../../lef/counter8.lef"

 set ::env(EXTRA_GDS_FILES) "\
-       $script_dir/../../gds/user_proj_example.gds"
+       $script_dir/../../gds/counter8.gds"

 # set ::env(GLB_RT_MAXLAYER) 5
 set ::env(RT_MAX_LAYER) {met4}

次に,macro.cfg  も counter8 に書き換えます.

counter8 1175 1690 N

これで準備完了です.トップディレクトリに戻り,make user_project_wrapper を実行すれば counter8 を組み込んだ user_project_wrapper が生成されます.

4.precheck,テープアウト

あとは make run-precheck を通してテープアウトするだけです.


この記事が気に入ったらサポートをしてみませんか?