* Bridge from SPARC Core to Wishbone Master
* (C) 2007 Simply RISC LLP
* AUTHOR: Fabrizio Fazzino <fabrizio.fazzino@srisc.com>
* This is a Free Hardware Design; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* This block implements a bridge from one SPARC Core of the
* OpenSPARC T1 to a master interface that makes use of the
* Wishbone interconnect protocol.
* For informations about Sun Microsystems' OpenSPARC T1
* refer to the web site http://www.opensparc.net
* For informations about OpenCores' Wishbone interconnect
* please refer to the web site http://www.opencores.org
module spc2wbm(sys_clock_i, sys_reset_i, sys_interrupt_source_i, spc_req_i,
spc_atom_i, spc_packetout_i, spc_grant_o, spc_ready_o, spc_packetin_o,
spc_stallreq_o, wbm_ack_i, wbm_data_i, wbm_cycle_o, wbm_strobe_o,
wbm_we_o, wbm_addr_o, wbm_data_o, wbm_sel_o);
input [5:0] sys_interrupt_source_i;
input [(130 - 1):0] spc_packetout_i;
input [(64 - 1):0] wbm_data_i;
output [4:0] spc_grant_o;
output [(146 - 1):0] spc_packetin_o;
output [(64 - 1):0] wbm_addr_o;
output [(64 - 1):0] wbm_data_o;
output [((64 / 8) - 1):0]
wire [(130 - 1):0] spc_packetout_w;
reg [(130 - 1):0] spc_packetout_i_save;
reg [(130 - 1):0] spc_packetout_i_save2;
reg [(146 - 1):0] spc_packetin_o;
reg [(146 - 1):0] spc_packetin_w;
reg [(64 - 1):0] wbm_addr_o;
reg [(64 - 1):0] wbm_data_o;
reg [4:0] spc2wbm_region;
reg [(130 - 1):0] spc2wbm_packet;
reg [(144 - 141):0] wbm2spc_type;
reg [(139 - 138):0] wbm2spc_error;
reg [(136 - 134):0] wbm2spc_thread;
reg [(132 - 131):0] wbm2spc_way;
reg [(127 - 0):0] wbm2spc_data;
reg [6:0] wbm2spc_interrupt_source;
reg wbm2spc_interrupt_new;
wire [(128 - 124):0] spc2wbm_type;
wire [(122 - 120):0] spc2wbm_cpu_id;
wire [(119 - 117):0] spc2wbm_thread;
wire [(113 - 112):0] spc2wbm_way;
wire [(111 - 104):0] spc2wbm_size;
wire [(103 - 64):0] spc2wbm_addr;
wire [(63 - 0):0] spc2wbm_data;
wire [(146 - 1):0] wbm2spc_packet;
wire [2:0] ic_dir_hit_way_enc;
wire [1:0] dc_dir_hit_way_enc;
reg spc2wbm_addr_subword;
wire [63:0] wbm_sel_o_bytemask = {{8 {spc2wbm_size[7]}}, {8
{spc2wbm_size[6]}}, {8 {spc2wbm_size[5]}}, {8
{spc2wbm_size[4]}}, {8 {spc2wbm_size[3]}}, {8
{spc2wbm_size[2]}}, {8 {spc2wbm_size[1]}}, {8 {spc2wbm_size[0]}}
wire [1:0] ic_dir_hit_way_enc0;
wire [1:0] ic_dir_hit_way_enc1;
assign spc2wbm_req = ((((spc_req_w[4] | spc_req_w[3]) | spc_req_w[2]) |
spc_req_w[1]) | spc_req_w[0]);
assign spc2wbm_valid = spc2wbm_packet[129];
assign spc2wbm_type = spc2wbm_packet[128:124];
assign spc2wbm_nc = spc2wbm_packet[123];
assign spc2wbm_cpu_id = spc2wbm_packet[122:120];
assign spc2wbm_thread = spc2wbm_packet[119:117];
assign spc2wbm_invalidate = spc2wbm_packet[116];
assign spc2wbm_way = spc2wbm_packet[113:112];
assign spc2wbm_size = spc2wbm_packet[111:104];
assign spc2wbm_addr = spc2wbm_packet[103:64];
assign spc2wbm_data = spc2wbm_packet[63:0];
assign wbm2spc_packet = {wbm2spc_valid, wbm2spc_type, wbm2spc_miss,
wbm2spc_error, wbm2spc_nc, wbm2spc_thread, wbm2spc_way_valid,
wbm2spc_way, wbm2spc_boot_fetch, wbm2spc_atomic, wbm2spc_pfl,
assign spc_grant_o = (spc_grant_w & (!spc_stallreq_o));
assign spc_atom_w = spc_atom_r;
assign spc_req_w = (spc_req_i | {4'b0, (fifo_vld & (~spc_stallreq_w))});
assign spc_stallreq_o = ((spc_stallreq_w | fifo_vld) | {(|spc_req_i)});
assign spc_packetout_w = ((fifo_vld | fifo_vld_d) ? spc_packetout_i_save
assign ic_dir_hit_way_enc = ((|ic_dir_hit[3:0]) ? {1'b0,
ic_dir_hit_way_enc0} : {1'b1, ic_dir_hit_way_enc1});
l2_dir l2_dird(sys_clock_i, sys_reset_i, spc2wbm_addr[38:11],
{spc2wbm_addr[10:5], spc2wbm_addr_subword}, dc_dir_wen, val_dc,
dc_dir_hit, dc_dir_hit_way_enc, dir_rd_en);
l2_dir l2_diri0(sys_clock_i, sys_reset_i, spc2wbm_addr[38:11],
{spc2wbm_addr[10:5], 1'b0}, ({4 {(~ic_dir_wen[4])}} &
ic_dir_wen[3:0]), val_ic, ic_dir_hit[3:0], ic_dir_hit_way_enc0,
l2_dir l2_diri1(sys_clock_i, sys_reset_i, spc2wbm_addr[38:11],
{spc2wbm_addr[10:5], 1'b0}, ({4 {ic_dir_wen[4]}} &
ic_dir_wen[3:0]), val_ic, ic_dir_hit[7:4], ic_dir_hit_way_enc1,
always @(posedge sys_clock_i) begin
spc_packetout_i_save <= (((spc_packetout_i[(130 - 1)] & spc_stallreq_d
) & (~fifo_vld)) ? spc_packetout_i : ((fifo_vld &
spc_stallreq_d) ? spc_packetout_i_save : spc_packetout_i_save2
spc_packetout_i_save2 <= ((spc_packetout_i[(130 - 1)] & fifo_vld) ?
spc_packetout_i : (fifo_vld2 ? spc_packetout_i_save2 : 0));
fifo_vld <= ((spc_packetout_i[(130 - 1)] & spc_stallreq_d) ? 1 : (
spc_stallreq_w ? fifo_vld : fifo_vld2));
fifo_vld2 <= ((spc_packetout_i[(130 - 1)] & fifo_vld) ? 1 : (
spc_stallreq_w ? fifo_vld2 : 0));
spc_stallreq_d <= spc_stallreq_w;
spc_atom_r <= (fifo_vld ? spc_atom_r : spc_atom_i);
always @(posedge sys_clock_i) begin
spc_packetin_o <= spc_packetin_w;
if (sys_reset_i == 1) begin
spc2wbm_addr_subword <= 0;
wbm2spc_data <= 64'h0000000000010001;
wbm2spc_interrupt_source <= 7'b0;
wbm2spc_interrupt_new <= 1'b0;
spc_packetin_w <= wbm2spc_packet;
else if (state == 4'b1) begin
if (spc2wbm_req == 1) begin
spc2wbm_region <= spc_req_w;
spc2wbm_atomic <= spc_atom_w;
else if (sys_interrupt_source_i != wbm2spc_interrupt_source)
wbm2spc_interrupt_new <= 1;
else if ((wbm2spc_interrupt_source != 6'b0) &&
wbm2spc_interrupt_new) begin
wbm2spc_interrupt_new <= 0;
spc_packetin_w <= wbm2spc_packet;
else if (state == 4'd2) begin
spc2wbm_addr_subword <= spc_packetout_w[4+64];
spc2wbm_packet <= spc_packetout_w;
spc_grant_w <= spc2wbm_region;
else if (state == 4'd3) begin
spc2wbm_addr_subword <= spc2wbm_addr[4];
if ((~spc2wbm_addr[39]) && ((spc2wbm_type == 5'b0) || (
spc2wbm_type == 5'b00010))) begin
wbm_addr_o <= {spc2wbm_region, 19'b0, spc2wbm_addr[(103 -
dc_dir_wen <= ({4 {(~spc2wbm_nc)}} & ((spc2wbm_way == 0) ?
4'b1 : ((spc2wbm_way == 1) ? 4'd2 : ((spc2wbm_way == 2
wbm_addr_o <= {spc2wbm_region, 19'b0, spc2wbm_addr[(103 -
wbm_data_o <= spc2wbm_data;
if (spc2wbm_type == 5'b10000) begin
ic_dir_wen <= ({5 {(~spc2wbm_nc)}} & {spc2wbm_packet[114],
((spc2wbm_way == 0) ? 4'b1 : ((spc2wbm_way == 1) ?
4'd2 : ((spc2wbm_way == 2) ? 4'd4 : 4'd8)))});
if (spc2wbm_region == 5'b10000) begin
wbm_sel_o <= (4'b1111 << (spc2wbm_addr[2] << 2));
wbm_sel_o <= 8'b11111111;
else if (spc2wbm_type == 5'b01000) begin
wbm_sel_o <= 8'b11111111;
else if (((spc2wbm_type == 5'b0) || (spc2wbm_type == 5'b00010))
|| (spc2wbm_type == 5'b00111)) begin
if (spc2wbm_addr[39]) begin
if (spc2wbm_type == 5'b0) begin
wbm_sel_o <= (1'b1 << spc2wbm_addr[2:0]);
wbm_sel_o <= (2'b11 << (spc2wbm_addr[2:1] << 1));
wbm_sel_o <= (4'b1111 << (spc2wbm_addr[2] << 2));
wbm_sel_o <= 8'b11111111;
wbm_sel_o <= 8'b11111111;
wbm_sel_o <= spc2wbm_size;
wbm_sel_o <= 8'b11111111;
else if ((spc2wbm_type == 5'b1) || ((spc2wbm_type == 5'b00011)
wbm_sel_o <= spc2wbm_size;
// synopsys translate_off
$display("INFO: SPC2WBM: Request of Type LOAD_RQ");
$display("INFO: SPC2WBM: Request of Type IMISS_RQ");
$display("INFO: SPC2WBM: Request of Type STORE_RQ");
$display("INFO: SPC2WBM: Request of Type MMU_RQ");
$display("INFO: SPC2WBM: Request of Type CAS1_RQ");
$display("INFO: SPC2WBM: Request of Type CAS2_RQ");
$display("INFO: SPC2WBM: Request of Type SWAP_RQ");
$display("INFO: SPC2WBM: Request of Type STRLOAD_RQ");
$display("INFO: SPC2WBM: Request of Type INT_RQ");
$display("INFO: SPC2WBM: Request of Type RSVD_RQ");
$display("INFO: SPC2WBM: ERROR!!! Request of Type Unknown"
$display("INFO: SPC2WBM: Address is %X", spc2wbm_addr);
$display("INFO: SPC2WBM: Data is %X", spc2wbm_data);
else if (state == 4'd4) begin
if (wbm_ack_i == 1) begin
if (spc2wbm_atomic == 0) begin
wbm2spc_way_valid <= (|dc_dir_hit);
wbm2spc_way <= dc_dir_hit_way_enc;
dc_dir_wen <= dc_dir_hit;
$display("%t, SWAP %x", $time, spc_packetin_w);
if (spc2wbm_addr[39]) begin
wbm2spc_pfl <= spc2wbm_packet[115];
wbm2spc_way_valid <= (|ic_dir_hit);
wbm2spc_way <= ic_dir_hit_way_enc[2:1];
wbm2spc_boot_fetch <= ic_dir_hit_way_enc[0];
ic_dir_wen <= ((|ic_dir_hit[3:0]) ? {1'b0,
ic_dir_hit[3:0]} : {1'b1, ic_dir_hit[7:4]});
wbm2spc_atomic <= spc2wbm_atomic;
wbm2spc_atomic <= spc2wbm_atomic;
wbm2spc_nc <= spc2wbm_nc;
wbm2spc_thread <= spc2wbm_thread;
if (spc2wbm_addr[39]) begin
if (spc2wbm_region == 5'b10000) begin
if ((spc2wbm_type == 5'b1) || (spc2wbm_type == 5'b00011))
wbm2spc_data[125] <= spc2wbm_packet[114];
wbm2spc_data[63:0] <= spc2wbm_data[63:0];
wbm2spc_data[67:64] <= {ic_dir_hit_way_enc, 1'b1};
ic_dir_wen <= ((|ic_dir_hit[3:0]) ? {1'b0, ic_dir_hit[3:0]
} : {1'b1, ic_dir_hit[7:4]});
wbm2spc_data[116:112] <= spc2wbm_addr[10:6];
wbm2spc_data[122:121] <= spc2wbm_addr[5:4];
wbm2spc_data[104] <= spc2wbm_addr[3];
wbm2spc_data[103:96] <= spc2wbm_size[7:0];
wbm2spc_data[116:112] <= spc2wbm_addr[10:6];
wbm2spc_data[122:121] <= spc2wbm_addr[5:4];
wbm2spc_data[104] <= spc2wbm_addr[3];
wbm2spc_data[103:96] <= spc2wbm_size[7:0];
wbm2spc_data[67:64] <= {dc_dir_hit_way_enc, 2'b10};
if (spc2wbm_type == 5'b00011) begin
dc_dir_wen <= dc_dir_hit;
begin //DW FIX FIX for mpgen problem
if ((spc2wbm_addr[3] == 0) || (spc2wbm_addr[39] == 0 && spc2wbm_type != 5'b00111))
wbm2spc_data <= {wbm_data_i, 64'b0};
wbm2spc_data <= {64'b0, wbm_data_i};
if (((((spc2wbm_type == 5'b10000) && (spc2wbm_region !=
5'b10000)) || (spc2wbm_type == 5'b01000)) || (
spc2wbm_type == 5'b00010)) || ((spc2wbm_type == 5'b0)
&& ((spc2wbm_size == 3'd7) || (spc2wbm_addr[39] == 0))
else if (spc2wbm_type == 5'b00111) begin
$display("%t, SWAP 2 %x", $time, spc_packetin_w);
else if (state == 4'd5) begin
wbm_addr_o <= {spc2wbm_region, 19'b0, spc2wbm_addr[(103 -
wbm_sel_o <= 8'b11111111;
else if (state == 4'd6) begin
if (wbm_ack_i == 1) begin
if (spc2wbm_atomic == 0) begin
wbm2spc_data[63:0] <= wbm_data_i;
if ((spc2wbm_type == 5'b10000) && (spc2wbm_region != 5'b10000)
else if (state == 4'd7) begin
spc2wbm_addr_subword <= 2'b1;
spc_packetin_w <= wbm2spc_packet;
wbm_addr_o <= {spc2wbm_region, 19'b0, spc2wbm_addr[(103 -
wbm_sel_o <= 8'b11111111;
// synopsys translate_off
$display("INFO: WBM2SPC: Return Packet of Type IFILL_RET");
$display("INFO: WBM2SPC: Return Packet of Type LOAD_RET");
$display("INFO: WBM2SPC: Return Packet of Type MMU_RET");
$display("INFO: WBM2SPC: Return Packet of Type ST_ACK");
$display("INFO: WBM2SPC: Return Packet of Type Unknown");
$display("INFO: WBM2SPC: Data is %X", wbm2spc_data);
else if (state == 4'd8) begin
dc_dir_wen <= dc_dir_hit;
wbm2spc_way_valid <= (|dc_dir_hit);
wbm2spc_way <= dc_dir_hit_way_enc;
if (wbm_ack_i == 1) begin
if (spc2wbm_atomic == 0) begin
wbm2spc_data <= {wbm_data_i, 64'b0};
wbm2spc_way_valid <= (|dc_dir_hit);
wbm2spc_way <= dc_dir_hit_way_enc;
else if (state == 4'd9) begin
if (spc2wbm_type == 5'b00111) begin
$display("%t, SWAP 3 %x", $time, spc_packetin_w);
spc_packetin_w <= wbm2spc_packet;
wbm_data_o <= spc2wbm_data;
wbm_sel_o <= spc2wbm_size;
wbm_addr_o <= {spc2wbm_region, 19'b0, spc2wbm_addr[(103 -
wbm_sel_o <= 8'b11111111;
wbm_addr_o <= {spc2wbm_region, 19'b0, spc2wbm_addr[(103 -
else if (state == 4'd10) begin
if (wbm_ack_i == 1) begin
if (spc2wbm_atomic == 0) begin
if (spc2wbm_type == 5'b00111) begin
wbm2spc_data[127:64] <= 64'b0;
wbm2spc_data[63:0] <= spc2wbm_data[63:0];
wbm2spc_data[67:64] <= {ic_dir_hit_way_enc, 1'b1};
ic_dir_wen <= ((|ic_dir_hit[3:0]) ? {1'b0, ic_dir_hit[3:0]
} : {1'b1, ic_dir_hit[7:4]});
wbm2spc_data[116:112] <= spc2wbm_addr[10:6];
wbm2spc_data[122:121] <= spc2wbm_addr[5:4];
wbm2spc_data[104] <= spc2wbm_addr[3];
wbm2spc_data[103:96] <= spc2wbm_size[7:0];
wbm2spc_data[67:64] <= {dc_dir_hit_way_enc, 2'b10};
wbm2spc_data[63:0] <= wbm_data_i;
else if (state == 4'b1011) begin
if (spc2wbm_type == 5'b00010) begin
if (((wbm2spc_data[63:0] & wbm_sel_o_bytemask) == (
spc2wbm_data[63:0] & wbm_sel_o_bytemask)) &
else if (((wbm2spc_data[127:64] & wbm_sel_o_bytemask) == (
spc2wbm_data[63:0] & wbm_sel_o_bytemask)) & (~
$display("%t, CAS failed pa:%x Act:%x Exp:%x Mask:%x",
$time, spc2wbm_addr, wbm_data_i, spc2wbm_data,
spc_packetin_w <= wbm2spc_packet;