是否有可综合的任务或端口接口方式来更好地将 AXI 信号分配给本地模块?

Is there a synthesizeable task or port interface way to better assign AXI signals to local modules?

目前我的设计中有一个横杆,我正在以不同的偏移量连接几个不同的模块(xbarAWADDR 和其他模块根据总线名称增加 32 或 40 或 4 或 1)。我将交叉开关信号传递给各个模块,如下所示。不过,这让我开始思考,是否有更易读或更有效的方式来多次编写此代码?

我 运行 关注的问题是,由于其 AXI,总线长度随输入和输出而变化。我想也许有两个结构会起作用,但我认为偏移地址和数据行之类的东西会更难,而且最终可能会产生更多代码。但我平均这样做 5 到 10 次。它很大,可能会很痛苦。也许一个虚拟任务需要四个结构输入、一个迭代次数并输出两个新结构?

也许有一些我不知道的结构可以更好地做到这一点?

为了进一步说明,我想做的是

localBusAssign( crossbarAxiBus, regBus, 0 );
localBusAssign( crossbarAxiBus, bramBus, 1);

而不是这个

  // Map CTRL REGS
  wire  [ 39: 0 ]  ctrlRegAWADDR  ;
  wire  [2  : 0 ]  ctrlRegAWPROT  ;
  wire             ctrlRegAWVALID ;
  wire             ctrlRegAWREADY ;
  wire  [31 : 0 ]  ctrlRegWDATA   ;
  wire  [3  : 0 ]  ctrlRegWSTRB   ;
  wire             ctrlRegWVALID  ;
  wire             ctrlRegWREADY  ;
  wire  [ 1 : 0 ]  ctrlRegBRESP   ;
  wire             ctrlRegBVALID  ;
  wire             ctrlRegBREADY  ;
  wire  [ 39: 0 ]  ctrlRegARADDR  ;
  wire  [ 2 : 0 ]  ctrlRegARPROT  ;
  wire             ctrlRegARVALID ;
  wire             ctrlRegARREADY ;
  wire  [31 : 0 ]  ctrlRegRDATA   ;
  wire  [1  : 0 ]  ctrlRegRRESP   ;
  wire             ctrlRegRVALID  ;
  wire             ctrlRegRREADY  ;

  //ctrl reg mappings
  assign ctrlRegAWADDR     = xbarAWADDR[39 : 0];
  assign ctrlRegAWPROT     = xbarAWPROT[ 2 : 0];
  assign ctrlRegAWVALID    = xbarAWVALID[0];
  assign xbarAWREADY[0]    = ctrlRegAWREADY;
  assign ctrlRegWDATA      = xbarWDATA[31 : 0];
  assign ctrlRegWSTRB      = xbarWSTRB[3 : 0];
  assign ctrlRegWVALID     = xbarWVALID[0];
  assign xbarWREADY[0]     = ctrlRegWREADY;
  assign xbarBRESP[1 : 0]  = ctrlRegBRESP;
  assign xbarBVALID[0]     = ctrlRegBVALID;
  assign ctrlRegBREADY     = xbarBREADY[0];
  assign ctrlRegARADDR     = xbarARADDR[39 : 0];
  assign ctrlRegARPROT     = xbarARPROT[2 : 0];
  assign ctrlRegARVALID    = xbarARVALID[0];
  assign xbarARREADY[0]    = ctrlRegARREADY;
  assign xbarRDATA[31 : 0] = ctrlRegRDATA;
  assign xbarRRESP[1 : 0]  = ctrlRegRRESP;
  assign xbarRVALID[0]     = ctrlRegRVALID;
  assign ctrlRegRREADY     = xbarRREADY[0];

  wire [39 : 0] bramCtrlAWADDR  ;
  wire [2 : 0]  bramCtrlAWPROT  ;
  wire          bramCtrlAWVALID ;
  wire          bramCtrlAWREADY ;
  wire [31 : 0] bramCtrlWDATA   ;
  wire [3 : 0]  bramCtrlWSTRB   ;
  wire          bramCtrlWVALID  ;
  wire          bramCtrlWREADY  ;
  wire [1 : 0]  bramCtrlBRESP   ;
  wire          bramCtrlBVALID  ;
  wire          bramCtrlBREADY  ;
  wire [39 : 0] bramCtrlARADDR  ;
  wire [2 : 0]  bramCtrlARPROT  ;
  wire          bramCtrlARVALID ;
  wire          bramCtrlARREADY ;
  wire [31 : 0] bramCtrlRDATA   ;
  wire [1 : 0]  bramCtrlRRESP   ;
  wire          bramCtrlRVALID  ;
  wire          bramCtrlRREADY  ;

  assign bramCtrlAWADDR    = xbarAWADDR[79 :40];
  assign bramCtrlAWPROT    = xbarAWPROT[ 5 : 3];
  assign bramCtrlAWVALID   = xbarAWVALID[0];
  assign xbarAWREADY[1]    = bramCtrlAWREADY;
  assign bramCtrlWDATA     = xbarWDATA[63 :32];
  assign bramCtrlWSTRB     = xbarWSTRB[7 : 4];
  assign bramCtrlWVALID    = xbarWVALID[1];
  assign xbarWREADY[1]     = bramCtrlWREADY;
  assign xbarBRESP[3 : 2]  = bramCtrlBRESP;
  assign xbarBVALID[1]     = bramCtrlBVALID;
  assign bramCtrlBREADY    = xbarBREADY[1];
  assign bramCtrlARADDR    = xbarARADDR[79 :40];
  assign bramCtrlARPROT    = xbarARPROT[5 : 3];
  assign bramCtrlARVALID   = xbarARVALID[1];
  assign xbarARREADY[1]    = bramCtrlARREADY;
  assign xbarRDATA[63 :32] = bramCtrlRDATA;
  assign xbarRRESP[3 : 2]  = bramCtrlRRESP;
  assign xbarRVALID[1]     = bramCtrlRVALID;
  assign bramCtrlRREADY    = xbarRREADY[1];

对于任何需要它的人,这就是我想出的解决方案。

package axiutils;

  import sysdefs_lib::*;



  typedef struct {
    reg [ A_AXIF_WIDTH*NUMIFACE-1 : 0 ] AWADDR  ;
    reg [ NUMIFACE*3-1            : 0 ] AWPROT  ;
    reg [ NUMIFACE-1              : 0 ] AWVALID ;
    reg [ NUMIFACE-1              : 0 ] AWREADY ;
    reg [ A_DATA_WIDTH*NUMIFACE-1 : 0 ] WDATA   ;
    reg [ NUMIFACE*4-1            : 0 ] WSTRB   ;
    reg [ NUMIFACE-1              : 0 ] WVALID  ;
    reg [ NUMIFACE-1              : 0 ] WREADY  ;
    reg [ NUMIFACE*2-1            : 0 ] BRESP   ;
    reg [ NUMIFACE-1              : 0 ] BVALID  ;
    reg [ NUMIFACE-1              : 0 ] BREADY  ;
    reg [ A_AXIF_WIDTH*NUMIFACE-1 : 0 ] ARADDR  ;
    reg [ NUMIFACE*3-1            : 0 ] ARPROT  ;
    reg [ NUMIFACE-1              : 0 ] ARVALID ;
    reg [ NUMIFACE-1              : 0 ] ARREADY ;
    reg [ A_DATA_WIDTH*NUMIFACE-1 : 0 ] RDATA   ;
    reg [ NUMIFACE*2-1            : 0 ] RRESP   ;
    reg [ NUMIFACE-1              : 0 ] RVALID  ;
    reg [ NUMIFACE-1              : 0 ] RREADY  ;
  } xbarRegIface;


  typedef struct {
    logic [A_AXIF_WIDTH-1 : 0    ] AWADDR  ;
    logic [2  : 0                ] AWPROT  ;
    logic                          AWVALID ;
    logic                          AWREADY ;
    logic [A_DATA_WIDTH-1 : 0    ] WDATA   ;
    logic [3  : 0                ] WSTRB   ;
    logic                          WVALID  ;
    logic                          WREADY  ;
    logic [1  : 0                ] BRESP   ;
    logic                          BVALID  ;
    logic                          BREADY  ;
    logic [A_AXIF_WIDTH-1 : 0    ] ARADDR  ;
    logic [2  : 0                ] ARPROT  ;
    logic                          ARVALID ;
    logic                          ARREADY ;
    logic [A_DATA_WIDTH-1  : 0   ] RDATA   ;
    logic [1  : 0                ] RRESP   ;
    logic                          RVALID  ;
    logic                          RREADY  ;
  } axiLiteIface;

  `define xbarData(liteIface, xbarIface, i) \
    begin \
      assign liteIface.AWADDR                                         = xbarIface.AWADDR[(i+1)*(A_AXIF_WIDTH-1) : A_AXIF_WIDTH*i] ; \
      assign liteIface.AWPROT                                         = xbarIface.AWPROT[ 3*i+1 : 3*i]                            ; \
      assign liteIface.AWVALID                                        = xbarIface.AWVALID[i]                                      ; \
      assign xbarIface.AWREADY[i]                                     = liteIface.AWREADY                                         ; \
      assign liteIface.WDATA                                          = xbarIface.WDATA[(i+1)*(A_DATA_WIDTH-1) : A_DATA_WIDTH*i]  ; \
      assign liteIface.WSTRB                                          = xbarIface.WSTRB[4*i+3 : 4*i]                              ; \
      assign liteIface.WVALID                                         = xbarIface.WVALID[i]                                       ; \
      assign xbarIface.WREADY[i]                                      = liteIface.WREADY                                          ; \
      assign xbarIface.BRESP[2*i+1 : 2*i]                             = liteIface.BRESP                                           ; \
      assign xbarIface.BVALID[i]                                      = liteIface.BVALID                                          ; \
      assign liteIface.BREADY                                         = xbarIface.BREADY[i]                                       ; \
      assign liteIface.ARADDR                                         = xbarIface.ARADDR[(i+1)*(A_AXIF_WIDTH-1) : A_AXIF_WIDTH*i] ; \
      assign liteIface.ARPROT                                         = xbarIface.ARPROT[3*i+1 : 3*i]                             ; \
      assign liteIface.ARVALID                                        = xbarIface.ARVALID[i]                                      ; \
      assign xbarIface.ARREADY[i]                                     = liteIface.ARREADY                                         ; \
      assign xbarIface.RDATA[(i+1)*(A_DATA_WIDTH-1) : A_DATA_WIDTH*i] = liteIface.RDATA                                           ; \
      assign xbarIface.RRESP[2*i+1 : 2*i]                             = liteIface.RRESP                                           ; \
      assign xbarIface.RVALID[i]                                      = liteIface.RVALID                                          ; \
      assign liteIface.RREADY                                         = xbarIface.RREADY[i]                                       ; \
    end

endpackage : axiutils

然后包含包并像这样使用

import axiutils::*;
xbarRegIface xbarReg;
axiLiteIface bus1, bus2, bus3;
`xbarData(bus1, xbarReg, 0);
`xbarData(bus2, xbarReg, 1);
`xbarData(bus3, xbarReg, 2);