-1

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

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Tropical_Peach
  • 1,143
  • 3
  • 16
  • 29
  • In system verilog you have parameterized interfaces which could potentially be used here. You can probably use modules and or structs as well. Regular arrays can be of help. It is difficult to say what you need based on the example. What verilog cannot do is to generate textual variable names on the fly (unless with text macros). You need generic names for all operations which could be augmented by the interface instance names. If this does not work, your best bet will be a verilog generator written in a scripting language. – Serge Jul 02 '20 at 02:29

1 Answers1

0

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);
Tropical_Peach
  • 1,143
  • 3
  • 16
  • 29