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.
180 lines
6.6 KiB
Verilog
180 lines
6.6 KiB
Verilog
// Wishbone-Wishbone Command Interface
|
|
|
|
// allow single- or dual-wb in/out:
|
|
// 1/1 : passthru
|
|
// 1/2 : route to proper - but this requires indicator in extcmd to distinguish i vs. d
|
|
// 2/1 : arbitrate
|
|
// 2/2 : passthru
|
|
//
|
|
// also handle special ops when possible (dcbz, ...)
|
|
|
|
// select one command per output bus
|
|
|
|
// ext_cmd is not tied to i/d, but does it need to have multiple outstanding (nop=0, and valid that require i/d info also must have that info provided)
|
|
// needs ext_tkn if not tied to i/d; needs to set q valid if tied to i/d (based on ext i or d type)
|
|
// seems like these are all tied to an i or d and require a response, so shouldn't need i+d+ext outstanding?
|
|
|
|
// possible extended command modifiers
|
|
// prefetch
|
|
// larx
|
|
// stcx
|
|
// lwsync
|
|
// hwsync
|
|
// tlbsync
|
|
// ici, icbi
|
|
// dci, dcbi, etc
|
|
// dcbtst
|
|
// dcbz
|
|
// tlbie, etc
|
|
|
|
// possible extended responses
|
|
// errors
|
|
// crit first, xfer# for larger bus width on core side
|
|
// credits
|
|
// resv valid
|
|
// stcx comp/pass
|
|
// sync ack
|
|
// back inv val/addr
|
|
|
|
// possible extra functions
|
|
// integrated L2
|
|
// doorbell/mailbox (peer/broadcast msg/rsp/intr side channel crossbar)
|
|
|
|
`include "defs.v"
|
|
|
|
module cmd_wb #(
|
|
parameter CORE_ID = 0,
|
|
parameter CORE_TYPE = `CORE_TYPE_WB2,
|
|
parameter BUS_TYPE = `BUS_TYPE_WB2
|
|
) (
|
|
input clk,
|
|
input rst,
|
|
input i_wb_cyc,
|
|
input i_wb_stb,
|
|
input [31:0] i_wb_adr,
|
|
input d_wb_cyc,
|
|
input d_wb_stb,
|
|
input d_wb_we,
|
|
input [3:0] d_wb_sel,
|
|
input [31:0] d_wb_adr,
|
|
input [31:0] d_wb_datw,
|
|
input [127:0] ext_cmd,
|
|
input [1:0] cmd_taken, // bit vector, one per queued cmd (could simultaneously occur in some designs)
|
|
input [1:0] cmd_complete, // bit vector, one per queued cmd (could simultaneously occur in some designs)
|
|
output [`CMD_SIZE-1:0] cmd_out_0,
|
|
output [`CMD_SIZE-1:0] cmd_out_1
|
|
);
|
|
|
|
reg [`CMD_SIZE-1:0] cmd_queue_q[0:1];
|
|
wire [`CMD_SIZE-1:0] cmd_queue_d[0:1];
|
|
wire [`CMD_SIZE-1:0] cmd_queue_in[0:1];
|
|
wire [`CMD_SIZE-1:0] cmd_queue_out;
|
|
reg [127:0] ext_queue_q;
|
|
wire [127:0] ext_queue_d;
|
|
wire [127:0] ext_queue_in;
|
|
|
|
genvar i;
|
|
|
|
// FF
|
|
always @(posedge clk) begin
|
|
|
|
if (rst) begin
|
|
|
|
cmd_queue_q[0] = 'h0;
|
|
cmd_queue_q[1] = 'h0;
|
|
ext_queue_q = 'h0;
|
|
|
|
end else begin
|
|
|
|
cmd_queue_q[0] = cmd_queue_d[0];
|
|
cmd_queue_q[1] = cmd_queue_d[1];
|
|
ext_queue_q = ext_queue_d;
|
|
|
|
end
|
|
end
|
|
|
|
case (CORE_TYPE)
|
|
`CORE_TYPE_WB1: begin
|
|
// q[0] = i or d
|
|
assign cmd_queue_in[0][`CMD_VALID] = d_wb_cyc & d_wb_stb; // valid - may need ext decode too
|
|
assign cmd_queue_in[0][`CMD_CORE_ID] = CORE_ID; // core id
|
|
assign cmd_queue_in[0][`CMD_RSVD_0] = 1'b0; // rsvd (possible cores > 4)
|
|
assign cmd_queue_in[0][`CMD_RSVD_1] = 1'b0; // rsvd (possible cores > 4)
|
|
assign cmd_queue_in[0][`CMD_TAKEN] = 1'b0; // taken
|
|
assign cmd_queue_in[0][`CMD_RSVD_2] = 1'b0; // rsp rcvd?
|
|
assign cmd_queue_in[0][`CMD_RSVD_3] = 1'b0;
|
|
assign cmd_queue_in[0][`CMD_WE] = d_wb_we;
|
|
assign cmd_queue_in[0][`CMD_SEL] = d_wb_sel;
|
|
assign cmd_queue_in[0][`CMD_ADR] = d_wb_adr;
|
|
assign cmd_queue_in[0][`CMD_SIZE-46:`CMD_SIZE-77] = d_wb_datw;
|
|
assign ext_queue_in[0] = ext_cmd;
|
|
end
|
|
`CORE_TYPE_WB2: begin
|
|
// q[0]=i, q[1]=d
|
|
assign cmd_queue_in[0][`CMD_VALID] = i_wb_cyc & i_wb_stb; // valid - may need ext decode too
|
|
assign cmd_queue_in[0][`CMD_CORE_ID] = CORE_ID; // core id
|
|
assign cmd_queue_in[0][`CMD_RSVD_0] = 1'b0; // rsvd (possible cores > 4)
|
|
assign cmd_queue_in[0][`CMD_RSVD_1] = 1'b0; // rsvd (possible cores > 4)
|
|
assign cmd_queue_in[0][`CMD_TAKEN] = 1'b0; // taken
|
|
assign cmd_queue_in[0][`CMD_RSVD_2] = 1'b0; // rsp rcvd?
|
|
assign cmd_queue_in[0][`CMD_RSVD_3] = 1'b0;
|
|
assign cmd_queue_in[0][`CMD_WE] = 1'b0;
|
|
assign cmd_queue_in[0][`CMD_SEL] = 4'b0;
|
|
assign cmd_queue_in[0][`CMD_ADR] = i_wb_adr;
|
|
assign cmd_queue_in[0][`CMD_DATW] = 32'b0;
|
|
|
|
assign cmd_queue_in[1][`CMD_VALID] = d_wb_cyc & d_wb_stb; // valid - may need ext decode too
|
|
assign cmd_queue_in[1][`CMD_CORE_ID] = CORE_ID; // core id
|
|
assign cmd_queue_in[0][`CMD_RSVD_0] = 1'b0; // rsvd (possible cores > 4)
|
|
assign cmd_queue_in[0][`CMD_RSVD_1] = 1'b0; // rsvd (possible cores > 4)
|
|
assign cmd_queue_in[0][`CMD_TAKEN] = 1'b0; // taken
|
|
assign cmd_queue_in[0][`CMD_RSVD_2] = 1'b0; // rsp rcvd?
|
|
assign cmd_queue_in[0][`CMD_RSVD_3] = 1'b0;
|
|
assign cmd_queue_in[1][`CMD_WE] = d_wb_we;
|
|
assign cmd_queue_in[1][`CMD_SEL] = d_wb_sel;
|
|
assign cmd_queue_in[1][`CMD_ADR] = d_wb_adr;
|
|
assign cmd_queue_in[1][`CMD_DATW] = d_wb_datw;
|
|
|
|
assign ext_queue_in = ext_cmd;
|
|
end
|
|
endcase
|
|
|
|
// queue routing/arbitration to cmd processing
|
|
|
|
case (CORE_TYPE)
|
|
`CORE_TYPE_WB1: begin
|
|
case (BUS_TYPE)
|
|
`BUS_TYPE_WB1: begin
|
|
assign cmd_out_0 = cmd_queue_q[0];
|
|
end
|
|
`BUS_TYPE_WB2: begin
|
|
assign cmd_out_0 = ext_queue_q[0] ? cmd_queue_q[1] : cmd_queue_q[7]; // select i vs d
|
|
end
|
|
endcase
|
|
end
|
|
`CORE_TYPE_WB2: begin
|
|
case (BUS_TYPE)
|
|
`BUS_TYPE_WB1:begin
|
|
// both valid: send d
|
|
// want selected bit; set first cycle; dont change once selected until not valid
|
|
assign cmd_out_0 = cmd_queue_q[1][`CMD_VALID] ? cmd_queue_q[1] : cmd_queue_q[0];
|
|
end
|
|
`BUS_TYPE_WB2: begin
|
|
assign cmd_out_0 = cmd_queue_q[0];
|
|
assign cmd_out_1 = cmd_queue_q[1];
|
|
end
|
|
endcase
|
|
end
|
|
endcase
|
|
|
|
for (i = 0; i < 2; i++) begin
|
|
// valid
|
|
assign cmd_queue_d[i][`CMD_VALID] = cmd_queue_q[i][`CMD_VALID] ? ~cmd_complete[i] : cmd_queue_in[i][`CMD_VALID];
|
|
// taken
|
|
assign cmd_queue_d[i][`CMD_TAKEN] = cmd_queue_q[i][`CMD_VALID] ? (cmd_queue_q[i][`CMD_TAKEN] | cmd_taken[i]) & ~cmd_complete[i] : 1'b0;
|
|
// rest
|
|
assign cmd_queue_d[i][`CMD_VALID-1:`CMD_TAKEN+1] = cmd_queue_q[i][`CMD_VALID] ? cmd_queue_q[i][`CMD_VALID-1:`CMD_TAKEN+1] : cmd_queue_in[i][`CMD_VALID-1:`CMD_TAKEN+1];
|
|
assign cmd_queue_d[i][`CMD_TAKEN-1:0] = cmd_queue_q[i][`CMD_VALID] ? cmd_queue_q[i][`CMD_TAKEN-1:0] : cmd_queue_in[i][`CMD_TAKEN-1:0];
|
|
end
|
|
|
|
endmodule |