使用SystemC实现完整的AXI4协议

作者:Jacky Gao,AMD工程师;来源:AMD开发者社区

前言

在之前的文章中,我们介绍了如何使用SystemC和VIP做C/C++/RTL的联合仿真,以及如何用SystemC实现AXI4-Lite Master做C/C++/RTLRTL的联合仿真。

在本文中,我们将继续探讨,介绍如何用SystemC实现完整的AXI4协议,以实现DMA的测试。

文中所涉及的所有代码均在Vivado和Modelsim/Questasim上做了验证

简介

在SystemC中实例化一个RTL的实体

在SystemC中实例化一个RTL的实体很直观,你只需要为其RTL实体手写一个对应的SystemC的外部模块,之后这个模块就可以在SystemC的环境被被其它类调用。

下面将举例说明如果在SystemC中构建一个VHDL的实体

示例 VHDL的设计

entity counter is
port(
  clk   : in std_logic;
  reset: in std_logic;
  count: std_logic_vector(7 downto 0)
  );
end;
 
architecture rtl of counter is
  …
end rtl;

 

对应的SystemC模块

class counter : public sc_foreign_module {
public:
  sc_in<sc_logic> clk;
  sc_in<sc_logic> reset;
  sc_out<sc_lv<8> > count;
  counter(sc_module_name nm) : sc_foreign_module(nm, "work.counter"),
    clk("clk"),
    reset("reset"),
    count("count") {
  }
};

 

实际的应用中,可以在编译完RTL模块之后,使用Modelsim/Qustasim提供的scgenmod工具自动生成对应的SystemC模块,具体使用办法请参考Modelsim手册。

用SystemC设计BFMs

我们参考ARM AMBA AXI Protocol Spec文档,使用SystemC实现完整的AXI4协议如下:

在SystemC中实现AXI4 Full的读操作,

uint32_t cmd_count = 0;
    bool cmd_done = false;
    uint32_t rsp_count = 0;
    bool rsp_done = false;
    bool wait_state = false;
    uint32_t wait_count = 0;
    uint32_t start_addr = addr;
    uint32_t num_transfers = size / 2;
    uint32_t index = 0;
 
    while (!cmd_done) {
      sc_core::wait(aclk_i.posedge_event());
 
      num_transfers = (size / 2 - cmd_count) > 256 ? 256 : (size / 2 - cmd_count);
      araddr = start_addr + cmd_count * 8;
      arlen = num_transfers - 1;
      arvalid = SC_LOGIC_1;
      rready = SC_LOGIC_0;
      arburst = INCR;
      arsize = WL64;
 
      while (1) {
        sc_core::wait(aclk_i.posedge_event());
 
        if (arready.read() == SC_LOGIC_1)
          break;
      }
 
      arvalid = SC_LOGIC_0;
      rready = SC_LOGIC_1;
 
      while (1) {
        sc_core::wait(aclk_i.posedge_event());
        if (rvalid.read() == SC_LOGIC_1) {
          *data = rdata.read().to_uint64();
          data++;
          index += 2;
          uint32_t rsp = rresp.read().to_uint();
          rc = checkAxiResponse(rsp);
 
          if (rlast.read() == SC_LOGIC_1) {
            cmd_count += num_transfers;
            if (cmd_count == size / 2)
              cmd_done = true;
            break;
          }
        }
      }
    }

在SystemC中实现AXI4 Full的写操作可以如下,

uint32_t cmd_count = 0;
    bool cmd_done = false;
    uint32_t start_addr = addr;
    uint32_t num_transfers = size / 2;
    uint32_t wait_count = 0;
    uint32_t index = 0;
 
    while (!cmd_done) {
      sc_core::wait(aclk_i.posedge_event());
 
      num_transfers = (size / 2 - cmd_count) > 256 ? 256 : (size / 2 - cmd_count);
      awaddr = start_addr + cmd_count * 8;
      awlen = num_transfers - 1;
      awvalid = SC_LOGIC_1;
      wdata = *data;
      wstrb = 0xFF;
      wvalid = SC_LOGIC_0;
      wlast = SC_LOGIC_0;
      awburst = INCR;
      awsize = WL64;
 
      while (1) {
        sc_core::wait(aclk_i.posedge_event());
 
        if (wready.read() == SC_LOGIC_1)
          break;
      }
 
      for (uint32_t i = 0; i < num_transfers; i++) {
        awaddr = start_addr + cmd_count * 8;
        awlen = num_transfers - 1;
        awvalid = SC_LOGIC_0;
        wdata = *(data + i);
        wstrb = 0xFF;
        wvalid = SC_LOGIC_1;
        wlast = (i == (num_transfers - 1)) ? SC_LOGIC_1 : SC_LOGIC_0;
 
        while (1) {
          sc_core::wait(aclk_i.posedge_event());
          if (wready.read() == SC_LOGIC_1)
            break;
        }
 
        index++;
        cmd_count++;
        if (cmd_count == size / 2)
          cmd_done = true;
      }
 
      wvalid = SC_LOGIC_0;
      wlast = SC_LOGIC_0;
 
      while (1) {
        if (bvalid.read() == SC_LOGIC_1) {
          rc = true;
          break;
        }
 
        sc_core::wait(aclk_i.posedge_event());
 
        wait_count++;
        if (wait_count == 10)
          break;
      }
    }

 示例工程

  • 打开Vivado,打开附件中的工程,查看DUT设计。

  • 打开Modelsim/Questasim,进入到sim/questa文件中

  • 执行do test.do

 测试结果

以下是Questasim的仿真结果,可以查看波形文件看到SystemC如何实现AXI4的Burst传输。

测试结果.png

最新文章

最新文章