Search code examples
verilogsystem-veriloghdl

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


Currently I have a cross bar in my design and I am wiring up several different modules at various offsets (xbarAWADDR and others increment by either 32 or 40 or 4 or 1 depending on the bus name). I am passing the cross bar signals to he various modules as shown below. This got me thinking though, is there a more readable or efficient way to write this many many times?

The issue I am running into is that because its AXI, the bus lengths vary as do the inputs and outputs. I thought maybe having two structures would work, but I think it would be harder to offset things like the address and data lines and may end up with more code. But I do this on average 5 to 10 times. It's massive and can get to be a pain. Maybe a virtual task that takes four structure inputs, an iteration number, and outputs two new structures?

Maybe there is some construct I am not aware of that can better do this?

For extra clarification, what I'd like to do is something like

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

instead of this

  // 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];


Solution

  • For whoever needs it, this is the solution I came up with.

    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
    

    Then include the package and use like this

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