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