You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

411 lines
15 KiB
Verilog

// A2 Core Bridge
// adapt cores and buses with generic module
// one thread/core for now; multithread needs thread tag, deeper queues
// could include l2, or interface to wider bus to speed up cache line fetches
`include "defs.v"
module A2WB #(
parameter [0:15] CORE_TYPES = {`CORE_TYPE_NONE, `CORE_TYPE_NONE, `CORE_TYPE_NONE, `CORE_TYPE_NONE},
parameter [0:3] BUS_TYPE = `BUS_TYPE_WB2,
parameter MAX_CORES = 4
) (
input clk,
input rst,
input [(`WB2_WB_OUT_START+1)*4-1:0] cores_in,
output [(`WB2_WB_IN_START+1)*4-1:0] cores_out,
input [127:0] bus_in,
output [255:0] bus_out
);
integer NUM_CORES;
genvar i;
// ------------------------------------------------------------------------------------------------
// I/O Connections
// cores must be contiguous, starting at 0
// core inputs to bridge:
/* wb1 core out:
assign c0_out = {wb_stb_0, wb_cyc_0, wb_we_0, wb_sel_0, wb_adr_0, wb_dat_o_0, 1'b0, 32'b0, 27'b0, // 128
ext_in}; // 128
*/
/* wb2 core out:
assign c0_out = {i_wb_stb_0, i_wb_cyc_0, 1'b0 , 4'b0, {i_wb_adr_0, 2'b0}, 32'b0, 1'b0, 32'b0, 27'b0, // 128
d_wb_stb_0, d_wb_cyc_0, d_wb_we_0, d_wb_sel_0, d_wb_adr_0, d_wb_dat_o_0, 1'b0, 32'b0, 27'b0, // 128
ext_in}; // 128
*/
/* a2l2 core out:
assign c0_in = {i_wb_ack_0, i_wb_dat_i_0, 95'b0, // 128
ext_out}; // 128
*/
/*
bus out/in:
assign bus_out[102] = bus_i_wb_cyc;
assign bus_out[101] = bus_i_wb_stb;
assign bus_out[100:71] = bus_i_wb_adr;
assign bus_out[70] = bus_d_wb_cyc;
assign bus_out[69] = bus_d_wb_stb;
assign bus_out[68] = bus_d_wb_we;
assign bus_out[67:64] = bus_d_wb_sel;
assign bus_out[63:32] = bus_d_wb_adr;
assign bus_out[31:0] = bus_d_wb_datw;
assign bus_i_wb_ack = bus_in[65];
assign bus_i_wb_datr = bus_in[64:33];
assign bus_d_wb_ack = bus_in[32];
assign bus_d_wb_datr = bus_in[31:0];
*/
wire [`WB2_WB_OUT_START:0] core_in [0:3];
assign {core_in[0], core_in[1], core_in[2], core_in[3]} = cores_in;
wire [`WB2_WB_OUT_START:0] core_out [0:3];
assign cores_out = {core_out[0], core_out[1], core_out[2], core_out[3]};
wire i_wb_cyc [0:3];
wire i_wb_stb [0:3];
wire [31:0] i_wb_adr [0:3];
wire i_wb_ack [0:3];
wire [31:0] i_wb_datr[0:3];
wire d_wb_cyc [0:3];
wire d_wb_stb [0:3];
wire d_wb_we [0:3];
wire [3:0] d_wb_sel [0:3];
wire [31:0] d_wb_adr [0:3];
wire [31:0] d_wb_datw [0:3];
wire d_wb_ack [0:3];
wire [31:0] d_wb_datr [0:3];
wire [127:0] ext_cmd [0:3];
wire [127:0] ext_rsp [0:3];
wire [`CMD_SIZE-1:0] cmd_out_0[0:3];
wire [`CMD_SIZE-1:0] cmd_out_1[0:3];
wire [1:0] cmd_taken[0:3];
wire [1:0] cmd_complete[0:3];
wire [`CMD_SIZE-1:0] req_0;
wire [`CMD_SIZE-1:0] req_1;
wire [`RSP_SIZE-1:0] core_rsp_0[0:3];
wire [`RSP_SIZE-1:0] core_rsp_1[0:3];
wire [`RSP_SIZE-1:0] rsp_0;
wire [`RSP_SIZE-1:0] rsp_1;
// to do this, need to label scope and ref it
//if (BUS_TYPE == `BUS_TYPE_WB1) begin
wire bus_wb_cyc;
wire bus_wb_stb;
wire bus_wb_we;
wire [3:0] bus_wb_sel;
wire [31:0] bus_wb_adr;
wire [31:0] bus_wb_datw;
wire bus_wb_ack;
wire [31:0] bus_wb_datr;
//end
//if (BUS_TYPE == `BUS_TYPE_WB2) begin
wire bus_i_wb_cyc;
wire bus_i_wb_stb;
wire [31:0] bus_i_wb_adr;
wire bus_i_wb_ack;
wire [31:0] bus_i_wb_datr;
wire bus_i_rdy;
wire bus_d_wb_cyc;
wire bus_d_wb_stb;
wire bus_d_wb_we;
wire [3:0] bus_d_wb_sel;
wire [31:0] bus_d_wb_adr;
wire [31:0] bus_d_wb_datw;
wire bus_d_wb_ack;
wire [31:0] bus_d_wb_datr;
wire bus_d_rdy;
wire bus_i_wb_ack;
wire [31:0] bus_i_wb_datr;
wire bus_d_wb_ack;
wire [31:0] bus_d_wb_datr;
//end
generate
assign NUM_CORES = 0;
for (i = 0; i < MAX_CORES; i++) begin
case (CORE_TYPES[i*4:i*4+3])
`CORE_TYPE_NONE: begin
end
`CORE_TYPE_A2L2: begin
assign NUM_CORES = NUM_CORES + 1;
// a2l2
end
`CORE_TYPE_WB1: begin
assign NUM_CORES = NUM_CORES + 1;
assign d_wb_cyc[i] = core_in[i][`WB1_WB_OUT_START];
assign d_wb_stb[i] = core_in[i][`WB1_WB_OUT_START-1];
assign d_wb_we[i] = core_in[i][`WB1_WB_OUT_START-2];
assign d_wb_sel[i] = core_in[i][`WB1_WB_OUT_START-3:`WB1_WB_OUT_START-6];
assign d_wb_adr[i] = core_in[i][`WB1_WB_OUT_START-7:`WB1_WB_OUT_START-38];
assign d_wb_datw[i] = core_in[i][`WB1_WB_OUT_START-39:`WB1_WB_OUT_START-70];
assign ext_cmd[i] = core_in[i][`WB1_EXT_OUT_START:0];
assign core_out[i][`WB1_WB_IN_START] = core_rsp_0[i][`RSP_VALID];
assign core_out[i][`WB1_WB_IN_START-1:`WB1_WB_IN_START-32] = core_rsp_0[i][`RSP_DATA];
assign core_out[i][`WB1_EXT_IN_START:0] = ext_rsp[i];
end
`CORE_TYPE_WB2: begin
assign NUM_CORES = NUM_CORES + 1;
assign i_wb_cyc[i] = core_in[i][`WB2_I_WB_OUT_START];
assign i_wb_stb[i] = core_in[i][`WB2_I_WB_OUT_START-1];
assign i_wb_adr[i] = core_in[i][`WB2_I_WB_OUT_START-7:`WB2_I_WB_OUT_START-38];
assign d_wb_cyc[i] = core_in[i][`WB2_D_WB_OUT_START];
assign d_wb_stb[i] = core_in[i][`WB2_D_WB_OUT_START-1];
assign d_wb_we[i] = core_in[i][`WB2_D_WB_OUT_START-2];
assign d_wb_sel[i] = core_in[i][`WB2_D_WB_OUT_START-3:`WB2_D_WB_OUT_START-6];
assign d_wb_adr[i] = core_in[i][`WB2_D_WB_OUT_START-7:`WB2_D_WB_OUT_START-38];
assign d_wb_datw[i] = core_in[i][`WB2_D_WB_OUT_START-39:`WB2_D_WB_OUT_START-70];
assign ext_cmd[i] = core_in[i][`WB2_EXT_OUT_START:0];
assign core_out[i][`WB2_I_WB_IN_START] = core_rsp_0[i][`RSP_VALID];
assign core_out[i][`WB2_I_WB_IN_START-1:`WB2_I_WB_IN_START-32] = core_rsp_0[i][`RSP_DATA];
assign core_out[i][`WB2_D_WB_IN_START] = core_rsp_1[i][`RSP_VALID];
assign core_out[i][`WB2_D_WB_IN_START-1:`WB2_D_WB_IN_START-32] = core_rsp_1[i][`RSP_DATA];
assign core_out[i][`WB2_EXT_IN_START:0] = ext_rsp[i];
end
endcase
end
endgenerate
// ------------------------------------------------------------------------------------------------
// Command Interfaces
//
generate
for (i = 0; i < MAX_CORES; i++) begin: cmd
case (CORE_TYPES[i*4:i*4+3])
`CORE_TYPE_NONE: begin
end
`CORE_TYPE_A2L2: begin
// convert a2l2 to internal format
end
`CORE_TYPE_WB1: begin
cmd_wb #(.CORE_ID(i), .CORE_TYPE(CORE_TYPES[i*4:i*4+3]), .BUS_TYPE(BUS_TYPE)) cmd_wb1 (
.clk(clk),
.rst(rst),
.i_wb_cyc('b0),
.i_wb_stb('b0),
.i_wb_adr('h0),
.d_wb_cyc(d_wb_cyc[i]),
.d_wb_stb(d_wb_stb[i]),
.d_wb_we(d_wb_we[i]),
.d_wb_sel(d_wb_sel[i]),
.d_wb_adr(d_wb_adr[i]),
.d_wb_datw(d_wb_datw[i]),
.ext_cmd(ext_cmd[i]),
.cmd_taken(cmd_taken[i]),
.cmd_complete(cmd_complete[i]),
.cmd_out_0(cmd_out_0[i]),
.cmd_out_1(cmd_out_1[i])
);
end
`CORE_TYPE_WB2: begin
cmd_wb #(.CORE_ID(i), .CORE_TYPE(CORE_TYPES[i*4:i*4+3]), .BUS_TYPE(BUS_TYPE)) cmd_wb2 (
.clk(clk),
.rst(rst),
.i_wb_cyc(i_wb_cyc[i]),
.i_wb_stb(i_wb_stb[i]),
.i_wb_adr(i_wb_adr[i]),
.d_wb_cyc(d_wb_cyc[i]),
.d_wb_stb(d_wb_stb[i]),
.d_wb_we(d_wb_we[i]),
.d_wb_sel(d_wb_sel[i]),
.d_wb_adr(d_wb_adr[i]),
.d_wb_datw(d_wb_datw[i]),
.ext_cmd(ext_cmd[i]),
.cmd_taken(cmd_taken[i]),
.cmd_complete(cmd_complete[i]),
.cmd_out_0(cmd_out_0[i]),
.cmd_out_1(cmd_out_1[i])
);
end
endcase
end
endgenerate
// ------------------------------------------------------------------------------------------------
// Arbitration
//
// LRU, etc. select from pending cmds; also needs smp to stall some/all cmds
// do addr cmp here, if necessary? or could do in smp - important if multiple outstanding req's allowed
// by any bus, which means there will be cmd and rsp queues with ordering requirements
// also needs to block cmds when bus is busy
// cmds include valid indicator
// cmd_taken is bit vector for cmds 1,0
// cmd_out's go to the bus; rsp_in's have to be associated with requesting core
arb #() arb (
.clk(clk),
.rst(rst),
.cmd_in_0_0(cmd_out_0[0]),
.cmd_in_1_0(cmd_out_1[0]),
.cmd_tkn_0(cmd_taken[0]),
.cmd_in_0_1(cmd_out_0[1]),
.cmd_in_1_1(cmd_out_1[1]),
.cmd_tkn_1(cmd_taken[1]),
.cmd_in_0_2(cmd_out_0[2]),
.cmd_in_1_2(cmd_out_1[2]),
.cmd_tkn_2(cmd_taken[2]),
.cmd_in_0_3(cmd_out_0[3]),
.cmd_in_1_3(cmd_out_1[3]),
.cmd_tkn_3(cmd_taken[3]),
.bus_rdy_0(bus_i_rdy),
.bus_rdy_1(bus_d_rdy),
.cmd_out_0(req_0),
.cmd_out_1(req_1)
);
// ------------------------------------------------------------------------------------------------
// SMP
// special ops: track resv, stall pending cmds, gen rsp
smp #() smp (
);
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Bus interface and logic can be replaced for different buses
// ------------------------------------------------------------------------------------------------
// Bus Out
// requests to main bus
generate begin: bus_wire_out
case(BUS_TYPE)
`BUS_TYPE_WB1: begin
assign bus_out[`BUS_WB1_OUT_START] = bus_i_wb_cyc;
assign bus_out[`BUS_WB1_OUT_START-1] = bus_wb_stb;
assign bus_out[`BUS_WB1_OUT_START-2] = bus_wb_we;
assign bus_out[`BUS_WB1_OUT_START-3:`BUS_WB1_OUT_START-6] = bus_wb_sel;
assign bus_out[`BUS_WB1_OUT_START-7:`BUS_WB1_OUT_START-38] = bus_wb_adr;
assign bus_out[`BUS_WB1_OUT_START-39:`BUS_WB1_OUT_START-70] = bus_wb_datw;
end
`BUS_TYPE_WB2: begin
assign bus_out[`BUS_WB2_I_OUT_START] = bus_i_wb_cyc;
assign bus_out[`BUS_WB2_I_OUT_START-1] = bus_i_wb_stb;
assign bus_out[`BUS_WB2_I_OUT_START-7:`BUS_WB2_I_OUT_START-38] = bus_i_wb_adr;
assign bus_out[`BUS_WB2_D_OUT_START] = bus_d_wb_cyc;
assign bus_out[`BUS_WB2_D_OUT_START-1] = bus_d_wb_stb;
assign bus_out[`BUS_WB2_D_OUT_START-2] = bus_d_wb_we;
assign bus_out[`BUS_WB2_D_OUT_START-3:`BUS_WB2_D_OUT_START-6] = bus_d_wb_sel;
assign bus_out[`BUS_WB2_D_OUT_START-7:`BUS_WB2_D_OUT_START-38] = bus_d_wb_adr;
assign bus_out[`BUS_WB2_D_OUT_START-39:`BUS_WB2_D_OUT_START-70] = bus_d_wb_datw;
end
endcase
end
endgenerate
// ------------------------------------------------------------------------------------------------
// Bus In
// responses from main bus
generate begin: bus_wire_in
case(BUS_TYPE)
`BUS_TYPE_WB1: begin
assign bus_wb_ack = bus_in[`BUS_WB1_IN_START];
assign bus_wb_datr = bus_in[`BUS_WB1_IN_START-1:`BUS_WB1_IN_START-32];
end
`BUS_TYPE_WB2: begin
assign bus_i_wb_ack = bus_in[`BUS_WB2_I_IN_START];
assign bus_i_wb_datr = bus_in[`BUS_WB2_I_IN_START-1:`BUS_WB2_I_IN_START-32];
assign bus_d_wb_ack = bus_in[`BUS_WB2_D_IN_START];
assign bus_d_wb_datr = bus_in[`BUS_WB2_D_IN_START-1:`BUS_WB2_D_IN_START-32];
end
endcase
end
endgenerate
// ------------------------------------------------------------------------------------------------
// Bus Interface
// translate reqs and handle bus transactions
generate begin: bus
case(BUS_TYPE)
`BUS_TYPE_WB1: begin
bus_wb1 #() bus(
.clk(clk),
.rst(rst),
.rdy(bus_rdy),
.cmd(req_0),
.rsp(rsp_0),
.wb_stb(bus_wb_stb),
.wb_cyc(bus_wb_cyc),
.wb_we(bus_wb_we),
.wb_sel(bus_wb_sel),
.wb_adr(bus_wb_adr),
.wb_datw(bus_wb_datw),
.wb_ack(bus_wb_ack),
.wb_datr(bus_wb_datr)
);
end
`BUS_TYPE_WB2: begin
bus_wb2 #() bus(
.clk(clk),
.rst(rst),
.rdy_i(bus_i_rdy),
.rdy_d(bus_d_rdy),
.cmd_i(req_0),
.cmd_d(req_1),
.rsp_i(rsp_0),
.rsp_d(rsp_1),
.i_wb_cyc(bus_i_wb_cyc),
.i_wb_stb(bus_i_wb_stb),
.i_wb_adr(bus_i_wb_adr),
.i_wb_ack(bus_i_wb_ack),
.i_wb_datr(bus_i_wb_datr),
.d_wb_cyc(bus_d_wb_cyc),
.d_wb_stb(bus_d_wb_stb),
.d_wb_we(bus_d_wb_we),
.d_wb_sel(bus_d_wb_sel),
.d_wb_adr(bus_d_wb_adr),
.d_wb_datw(bus_d_wb_datw),
.d_wb_ack(bus_d_wb_ack),
.d_wb_datr(bus_d_wb_datr)
);
end
endcase
end
endgenerate
// ------------------------------------------------------------------------------------------------
// Response Queues
// responses for cores - just routing if no queues needed
// but should be component; rsp's are formatted differently based on core interface type, plus
// a2l2 could support queues even if wb doesn't
// also, rsp may be gen'd from other units like smp, config, mailbox, etc.
generate begin: rsp
for (i = 0; i < MAX_CORES; i++) begin
assign core_rsp_0[i][`RSP_VALID] = rsp_0[`RSP_VALID] & (rsp_0[`RSP_CORE_ID] == i);
assign core_rsp_0[i][`RSP_DATA] = rsp_0[`RSP_DATA];
assign cmd_complete[i][0] = core_rsp_0[i][`RSP_VALID];
assign core_rsp_1[i][`RSP_VALID] = rsp_1[`RSP_VALID] & (rsp_1[`RSP_CORE_ID] == i);
assign core_rsp_1[i][`RSP_DATA] = rsp_1[`RSP_DATA];
assign cmd_complete[i][1] = core_rsp_1[i][`RSP_VALID];
end
end
endgenerate
// ------------------------------------------------------------------------------------------------
// Misc/Errors/Debug
// stuff
/*
generate begin: misc
for (i = 0; i < MAX_CORES; i++) begin
end
end
endgenerate
*/
endmodule