LSI Jiu-Jitsu

電子工作とブラジリアン柔術

Cortex-M0 RTLで遊ぶ (1) - Sim環境整備

ARM Cortex-M0のRTLシミュレーション向けモデルが無料公開されていると言うのを最近知りました。
ちょうど今月から始まった新規のお仕事がCortex-M0+を使用する案件だったので、予習目的でダウンロードして遊んでみました。

シミュレーションはRaspberryPi Zero2上でIcarus Verilogで実行しました。
波形確認はGtkWaveをXmingを通してWindowsに表示しています。
Icarus VerilogとGtkWaveは、aptに登録されているのでRaspberryPiからコマンド1つでインストールできました。

$ sudo apt install iverilog
$ sudo apt install gtkwave


https://developer.arm.com/downloads/view/AT511

RTLモデルパッケージはARMのサイトで「AT511-Cortex-M0 DesignStart Eval」と言う名称で公開されています。
ダウンロードするにはユーザー登録が必須であり、スマホ認証による電話番号入力など多くの個人情報が必要でした(笑)

ダウンロード後の .tar.gz を解凍すると多くのファイルが生成されますが、M0コアは下記の2ファイルから構成されているようです。

cores/cortexm0_designstart_r2p0/logical/cortexm0_integration/verilog/CORTEXM0INTEGRATION.v
cores/cortexm0_designstart_r2p0/logical/cortexm0_integration/verilog/cortexm0ds_logic.v

M0コアはリセット解除後AHBバス経由で0x00番地からプログラムのリードを開始します。
AHBバス接続のメモリモデルもパッケージに含まれておりましたのでこちらも使用しました。

logical/models/memories/cmsdk_ahb_ram_beh.v

M0コアとメモリモデルを接続したテストベンチ(my_test.v)を記述して実行してみます。
リセット解除後、1000サイクルで終了する単純なテストです。

`timescale 1ns/1ns

module my_test();

  reg          clk;
  reg          reset_n;

  wire [31:0]  HADDR;
  wire [2:0]   HSIZE;
  wire [1:0]   HTRANS;
  wire [31:0]  HWDATA;
  wire         HWRITE;
  wire [31:0]  HRDATA;
  wire         HREADY;
  wire         HRESP;

  CORTEXM0INTEGRATION CORTEXM0INTEGRATION(
     .FCLK          ( clk           )  // input
    ,.SCLK          ( clk           )  // input
    ,.HCLK          ( clk           )  // input
    ,.DCLK          ( 1'b0          )  // input
    ,.PORESETn      ( reset_n       )  // input
    ,.DBGRESETn     ( reset_n       )  // input
    ,.HRESETn       ( reset_n       )  // input
    ,.SWCLKTCK      ( 1'b0          )  // input
    ,.nTRST         ( 1'b0          )  // input
    ,.HADDR         ( HADDR         )  // output [31:0]
    ,.HBURST        (               )  // output [2:0]
    ,.HMASTLOCK     (               )  // output
    ,.HPROT         (               )  // output [3:0]
    ,.HSIZE         ( HSIZE         )  // output [2:0]
    ,.HTRANS        ( HTRANS        )  // output [1:0]
    ,.HWDATA        ( HWDATA        )  // output [31:0]
    ,.HWRITE        ( HWRITE        )  // output
    ,.HRDATA        ( HRDATA        )  // input  [31:0]
    ,.HREADY        ( HREADY        )  // input
    ,.HRESP         ( HRESP         )  // input
    ,.HMASTER       (               )  // output
    ,.CODENSEQ      (               )  // output
    ,.CODEHINTDE    (               )  // output [2:0]
    ,.SPECHTRANS    (               )  // output
    ,.SWDITMS       ( 1'b0          )  // input
    ,.TDI           ( 1'b0          )  // input
    ,.SWDO          (               )  // output
    ,.SWDOEN        (               )  // output
    ,.TDO           (               )  // output
    ,.nTDOEN        (               )  // output
    ,.DBGRESTART    ( 1'b0          )  // input
    ,.DBGRESTARTED  (               )  // output
    ,.EDBGRQ        ( 1'b0          )  // input
    ,.HALTED        (               )  // output
    ,.NMI           ( 1'b0          )  // input
    ,.IRQ           ( {32{1'b0}}    )  // input  [31:0]
    ,.TXEV          (               )  // output
    ,.RXEV          ( 1'b0          )  // input
    ,.LOCKUP        (               )  // output
    ,.SYSRESETREQ   (               )  // output
    ,.STCALIB       ( {26{1'b0}}    )  // input  [25:0]
    ,.STCLKEN       ( 1'b0          )  // input
    ,.IRQLATENCY    ( {8{1'b0}}     )  // input  [7:0]
    ,.ECOREVNUM     ( {28{1'b0}}    )  // input  [27:0]
    ,.GATEHCLK      (               )  // output
    ,.SLEEPING      (               )  // output
    ,.SLEEPDEEP     (               )  // output
    ,.WAKEUP        (               )  // output
    ,.WICSENSE      (               )  // output [33:0]
    ,.SLEEPHOLDREQn ( 1'b1          )  // input
    ,.SLEEPHOLDACKn (               )  // output
    ,.WICENREQ      ( 1'b0          )  // input
    ,.WICENACK      (               )  // output
    ,.CDBGPWRUPREQ  (               )  // output
    ,.CDBGPWRUPACK  ( 1'b0          )  // input
    ,.SE            ( 1'b0          )  // input
    ,.RSTBYPASS     ( 1'b0          )  // input
  );

  cmsdk_ahb_ram_beh cmsdk_ahb_ram_beh(
     .HCLK       ( clk         )  // input
    ,.HRESETn    ( reset_n     )  // input
    ,.HSEL       ( 1'b1        )  // input
    ,.HADDR      ( HADDR[15:0] )  // input  [15:0]
    ,.HTRANS     ( HTRANS      )  // input  [1:0]
    ,.HSIZE      ( HSIZE       )  // input  [2:0]
    ,.HWRITE     ( HWRITE      )  // input
    ,.HWDATA     ( HWDATA      )  // input  [31:0]
    ,.HREADY     ( 1'b1        )  // input
    ,.HREADYOUT  ( HREADY      )  // output
    ,.HRDATA     ( HRDATA      )  // output [31:0]
    ,.HRESP      ( HRESP       )  // output
  );

  always #100 clk = ~clk;

  initial
    begin
      clk     = 1'b0;
      reset_n = 1'b0;

      #250 reset_n = 1'b1;

      repeat(1000) @(posedge clk);

      $display("*** Simulation finish... ***");
      $finish;
    end

    initial
      begin
        $dumpvars();
      end

endmodule

メモリモデルはデフォルトの構成ではアドレス16bitバスになっているので、M0コアが出力するHADDRの下位16bitを接続しています。
また、AHBスレーブはメモリモデルだけなのでHSELとHREADY(input)はHigh固定にしています。

  cmsdk_ahb_ram_beh cmsdk_ahb_ram_beh(
     .HCLK       ( clk         )  // input
    ,.HRESETn    ( reset_n     )  // input
    ,.HSEL       ( 1'b1        )  // input
    ,.HADDR      ( HADDR[15:0] )  // input  [15:0]

Makefileに実行コマンドを書いて make で実行開始です。

RTL = AT510-MN-80001-r2p0-00rel0/cores/cortexm0_designstart_r2p0/logical/cortexm0_integration/verilog/CORTEXM0INTEGRATION.v \
      AT510-MN-80001-r2p0-00rel0/cores/cortexm0_designstart_r2p0/logical/cortexm0_integration/verilog/cortexm0ds_logic.v \
      AT510-MN-80001-r2p0-00rel0/logical/models/memories/cmsdk_ahb_ram_beh.v

all:
	iverilog my_test.v $(RTL) -o simv
	./simv

エラー無く終了すると波形ファイルの dump.vcd が生成されていますので、GtkWaveから開いて確認します。

文字が小さくて非常に見難いですが、M0コアからAHBリードを開始しているようなので成功です。

次回はプログラムをメモリモデルの初期値に展開して動かしてみようと思います。