FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

LiteXによるSoC環境構築を試行する (14. AXI Wrapper階層の作り直し)

https://raw.githubusercontent.com/enjoy-digital/litex/master/doc/litex.png

LiteXの続き。SoC階層に書き込みができていない問題があったのだが、これはAXIを正しく接続していなかったせいだった。

問題は、今のCPUインタフェースがAXIのようなAWとWの非同期動作をサポートしていないということ。SoC側が非同期にReadyを動かす場合、うまく動かなくなってしまう。 そこで、SoC階層をAXIに変換するWrapper階層を再定義して、AXIインタフェースを再定義した。

この階層を使用してLiteXに接続した。Pythonの接続状態は以下の通り。

        # CPU Instance.
        self.cpu_params = dict(
            # Clk / Rst.
            i_i_clk       = ClockSignal("sys"),
            i_i_reset_n   = ~ResetSignal("sys") | self.reset,

            # # Interrupts
            # i_irq_sources = self.interrupt,

            # AXI interface.
            o_axi_if_aw_valid   = axi_if.aw.valid     ,
            i_axi_if_aw_ready   = axi_if.aw.ready     ,
            o_axi_if_aw_last    = axi_if.aw.last      ,
            o_axi_if_aw_addr    = axi_if.aw.addr      ,
            o_axi_if_aw_burst   = axi_if.aw.burst     ,
            o_axi_if_aw_len     = axi_if.aw.len       ,
            o_axi_if_aw_size    = axi_if.aw.size      ,
            o_axi_if_aw_lock    = axi_if.aw.lock      ,
            o_axi_if_aw_prot    = axi_if.aw.prot      ,
            o_axi_if_aw_cache   = axi_if.aw.cache     ,
/* ... 途中省略 ... */
            o_axi_if_ar_prot    = axi_if.ar.prot      ,
            o_axi_if_ar_cache   = axi_if.ar.cache     ,
            o_axi_if_ar_qos     = axi_if.ar.qos       ,
            o_axi_if_ar_region  = axi_if.ar.region    ,
            o_axi_if_ar_id      = axi_if.ar.id        ,

            i_axi_if_r_valid    = axi_if.r.valid      ,
            o_axi_if_r_ready    = axi_if.r.ready      ,
            i_axi_if_r_last     = axi_if.r.last       ,
            i_axi_if_r_resp     = axi_if.r.resp       ,
            i_axi_if_r_data     = axi_if.r.data       ,
            i_axi_if_r_id       = axi_if.r.id         ,
        )

生成されたVerilogコードは以下のようになる。

scariv_subsystem_axi_wrapper scariv_subsystem_axi_wrapper(
    .axi_if_ar_ready(main_axi_if_ar_ready),
    .axi_if_aw_ready(main_axi_if_aw_ready),
    .axi_if_b_id(main_axi_if_b_param_id),
    .axi_if_b_resp(main_axi_if_b_payload_resp),
    .axi_if_b_valid(main_axi_if_b_valid),
    .axi_if_r_data(main_axi_if_r_payload_data),
    .axi_if_r_id(main_axi_if_r_param_id),
    .axi_if_r_last(main_axi_if_r_last),
    .axi_if_r_resp(main_axi_if_r_payload_resp),
    .axi_if_r_valid(main_axi_if_r_valid),
    .axi_if_w_ready(main_axi_if_w_ready),
    .i_clk(sys_clk_1),
    .i_reset_n(((~sys_rst) | main_reset)),
    .axi_if_ar_addr(main_axi_if_ar_payload_addr),
    .axi_if_ar_burst(main_axi_if_ar_payload_burst),
    .axi_if_ar_cache(main_axi_if_ar_payload_cache),
    .axi_if_ar_id(main_axi_if_ar_param_id),
    .axi_if_ar_last(main_axi_if_ar_last),
    .axi_if_ar_len(main_axi_if_ar_payload_len),
    .axi_if_ar_lock(main_axi_if_ar_payload_lock),
    .axi_if_ar_prot(main_axi_if_ar_payload_prot),
    .axi_if_ar_qos(main_axi_if_ar_payload_qos),
    .axi_if_ar_region(main_axi_if_ar_payload_region),
    .axi_if_ar_size(main_axi_if_ar_payload_size),
    .axi_if_ar_valid(main_axi_if_ar_valid),
    .axi_if_aw_addr(main_axi_if_aw_payload_addr),
    .axi_if_aw_burst(main_axi_if_aw_payload_burst),
    .axi_if_aw_cache(main_axi_if_aw_payload_cache),
    .axi_if_aw_id(main_axi_if_aw_param_id),
    .axi_if_aw_last(main_axi_if_aw_last),
    .axi_if_aw_len(main_axi_if_aw_payload_len),
    .axi_if_aw_lock(main_axi_if_aw_payload_lock),
    .axi_if_aw_prot(main_axi_if_aw_payload_prot),
    .axi_if_aw_qos(main_axi_if_aw_payload_qos),
    .axi_if_aw_region(main_axi_if_aw_payload_region),
    .axi_if_aw_size(main_axi_if_aw_payload_size),
    .axi_if_aw_valid(main_axi_if_aw_valid),
    .axi_if_b_ready(main_axi_if_b_ready),
    .axi_if_r_ready(main_axi_if_r_ready),
    .axi_if_w_data(main_axi_if_w_payload_data),
    .axi_if_w_last(main_axi_if_w_last),
    .axi_if_w_strb(main_axi_if_w_payload_strb),
    .axi_if_w_valid(main_axi_if_w_valid)
);