| 1 |
4 |
fafa1971 |
/*
|
| 2 |
|
|
* Bridge from SPARC Core to Wishbone Master
|
| 3 |
|
|
*
|
| 4 |
114 |
albert.wat |
* (C) 2006-2007 Fabrizio Fazzino
|
| 5 |
4 |
fafa1971 |
*
|
| 6 |
|
|
* LICENSE:
|
| 7 |
|
|
* This is a Free Hardware Design; you can redistribute it and/or
|
| 8 |
|
|
* modify it under the terms of the GNU General Public License
|
| 9 |
|
|
* version 2 as published by the Free Software Foundation.
|
| 10 |
|
|
* The above named program is distributed in the hope that it will
|
| 11 |
|
|
* be useful, but WITHOUT ANY WARRANTY; without even the implied
|
| 12 |
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 13 |
|
|
* See the GNU General Public License for more details.
|
| 14 |
|
|
*
|
| 15 |
|
|
* DESCRIPTION:
|
| 16 |
|
|
* This block implements a bridge from one SPARC Core of the
|
| 17 |
|
|
* OpenSPARC T1 to a master interface that makes use of the
|
| 18 |
|
|
* Wishbone interconnect protocol.
|
| 19 |
|
|
* For informations about Sun Microsystems' OpenSPARC T1
|
| 20 |
|
|
* refer to the web site http://www.opensparc.net
|
| 21 |
|
|
* For informations about OpenCores' Wishbone interconnect
|
| 22 |
|
|
* please refer to the web site http://www.opencores.org
|
| 23 |
|
|
*/
|
| 24 |
|
|
|
| 25 |
|
|
`include "s1_defs.h"
|
| 26 |
113 |
albert.wat |
`define SPC_REGION_HI 4
|
| 27 |
|
|
`define SPC_REGION_LO 0
|
| 28 |
|
|
`define SPC_REGION_WIDTH (`SPC_REGION_HI-`SPC_REGION_LO+1)
|
| 29 |
|
|
`define SPC_INFO_WIDTH (`SPC_REGION_WIDTH+1)
|
| 30 |
4 |
fafa1971 |
|
| 31 |
|
|
module spc2wbm (
|
| 32 |
|
|
|
| 33 |
99 |
fafa1971 |
/*
|
| 34 |
|
|
* Inputs
|
| 35 |
|
|
*/
|
| 36 |
4 |
fafa1971 |
|
| 37 |
99 |
fafa1971 |
// System inputs
|
| 38 |
|
|
input sys_clock_i, // System Clock
|
| 39 |
|
|
input sys_reset_i, // System Reset
|
| 40 |
|
|
input[5:0] sys_interrupt_source_i, // Encoded Interrupt Source
|
| 41 |
4 |
fafa1971 |
|
| 42 |
99 |
fafa1971 |
// SPARC-side inputs connected to the PCX (Processor-to-Cache Xbar) outputs of the SPARC Core
|
| 43 |
113 |
albert.wat |
input[`SPC_REGION_WIDTH-1:0] spc_req_i, // Request Region
|
| 44 |
99 |
fafa1971 |
input spc_atom_i, // Atomic Request
|
| 45 |
|
|
input[(`PCX_WIDTH-1):0] spc_packetout_i, // Outgoing Packet
|
| 46 |
4 |
fafa1971 |
|
| 47 |
99 |
fafa1971 |
// Wishbone Master interface inputs
|
| 48 |
|
|
input wbm_ack_i, // Ack
|
| 49 |
|
|
input[(`WB_DATA_WIDTH-1):0] wbm_data_i, // Data In
|
| 50 |
4 |
fafa1971 |
|
| 51 |
99 |
fafa1971 |
/*
|
| 52 |
|
|
* Outputs
|
| 53 |
|
|
*/
|
| 54 |
4 |
fafa1971 |
|
| 55 |
99 |
fafa1971 |
// SPARC-side outputs connected to the CPX (Cache-to-Processor Xbar) inputs of the SPARC Core
|
| 56 |
113 |
albert.wat |
output logic[4:0] spc_grant_o, // Grant
|
| 57 |
99 |
fafa1971 |
output reg spc_ready_o, // Ready
|
| 58 |
|
|
output reg[`CPX_WIDTH-1:0] spc_packetin_o, // Incoming Packet
|
| 59 |
4 |
fafa1971 |
|
| 60 |
99 |
fafa1971 |
// Wishbone Master interface outputs
|
| 61 |
|
|
output reg wbm_cycle_o, // Cycle Start
|
| 62 |
|
|
output reg wbm_strobe_o, // Strobe Request
|
| 63 |
|
|
output reg wbm_we_o, // Write Enable
|
| 64 |
|
|
output reg[`WB_ADDR_WIDTH-1:0] wbm_addr_o, // Address Bus
|
| 65 |
|
|
output reg[`WB_DATA_WIDTH-1:0] wbm_data_o, // Data Out
|
| 66 |
|
|
output reg[`WB_DATA_WIDTH/8-1:0] wbm_sel_o // Select Output
|
| 67 |
4 |
fafa1971 |
|
| 68 |
99 |
fafa1971 |
);
|
| 69 |
|
|
|
| 70 |
4 |
fafa1971 |
/*
|
| 71 |
113 |
albert.wat |
* Packet Structures
|
| 72 |
4 |
fafa1971 |
*/
|
| 73 |
|
|
|
| 74 |
113 |
albert.wat |
// Processor-to-Cache Xbar request region and atomic info
|
| 75 |
|
|
typedef struct packed {
|
| 76 |
|
|
logic [`SPC_REGION_WIDTH-1:0] region; // info[5:1] Region
|
| 77 |
|
|
logic atomic; // info[0] Atomicity
|
| 78 |
|
|
} pcx_info_t;
|
| 79 |
4 |
fafa1971 |
|
| 80 |
113 |
albert.wat |
// Processor-to-Cache Xbar request packet type (PCX payload 124-bit)
|
| 81 |
|
|
typedef struct packed {
|
| 82 |
|
|
logic valid; // pcx[123] Packet Valid
|
| 83 |
|
|
logic [`PCX_RQ_HI-`PCX_RQ_LO:0] request_type; // pcx[122:118] Request Type (LOAD_/IMISS_/STORE_/CAS1_/CAS2_/SWAP_/STRLOAD_/STRST_/STQ_/INT_/FWD_/RSVD_RQ FWD_RPY)
|
| 84 |
|
|
logic noncache_rnw; // pcx[117] Non-Cacheable, or ReadNotWrite
|
| 85 |
|
|
logic [`PCX_CP_HI-`PCX_CP_LO:0] cpu_id; // pcx[116:114] CPU ID
|
| 86 |
|
|
logic [`PCX_TH_HI-`PCX_TH_LO:0] thread_id; // pcx[113:112] Thread ID
|
| 87 |
|
|
logic [`PCX_BF_HI-`PCX_BF_LO:0] buffer_id; // pcx[111:109] Buffer ID
|
| 88 |
|
|
logic [`PCX_WY_HI-`PCX_WY_LO:0] l1way_packetid;// pcx[108:107] L1 Way Replaced, or Packet ID
|
| 89 |
|
|
logic [`PCX_SZ_HI-`PCX_SZ_LO:0] access_size; // pcx{106:104] Access Size (PCX_SZ_1B/_2B/_4B/_8B/16B), or Error Field
|
| 90 |
|
|
logic [`PCX_AD_HI-`PCX_AD_LO:0] address; // pcx[103:64] Address
|
| 91 |
|
|
logic [`PCX_DA_HI-`PCX_DA_LO:0] store_data; // pcx[63:0] Store Data
|
| 92 |
|
|
} pcx_packet_t;
|
| 93 |
4 |
fafa1971 |
|
| 94 |
113 |
albert.wat |
// Cache-to-Processor Xbar return packet type (CPX payload 145-bit)
|
| 95 |
|
|
typedef struct packed {
|
| 96 |
|
|
logic valid; // cpx[144] Packet Valid
|
| 97 |
|
|
logic [`CPX_RQ_HI-`CPX_RQ_LO:0] return_type; // cpx[143:140] Return Type (LOAD_/INV_/INT_/TEST_/FP_/IFILL_/ERR_/STRLOAD_/FWD_RQ_/FWD_RPY_/RSVD_RET ST_/AT_/STRST_ACK EVICT_REQ)
|
| 98 |
|
|
logic [`CPX_ERR_HI-`CPX_ERR_LO:0] error; // cpx[139:137] Error
|
| 99 |
|
|
logic noncache_rnw;// cpx[136] Non-Cacheable, or ReadNotWrite
|
| 100 |
|
|
logic [`CPX_TH_HI-`CPX_TH_LO:0] thread_id; // cpx[135:134] Thread ID
|
| 101 |
|
|
logic [`CPX_IN_HI-`CPX_IN_LO:0] intsrc_etc; // cpx[133:128] Interrupt Source, or Way Replaced, or Buffer ID, or Packet ID, or Invalidates, etc.
|
| 102 |
|
|
logic [`CPX_DA_HI-`CPX_DA_LO:0] load_data; // cpx[127:0] Load Data
|
| 103 |
|
|
} cpx_packet_t;
|
| 104 |
4 |
fafa1971 |
|
| 105 |
|
|
/*
|
| 106 |
113 |
albert.wat |
* Useful Function
|
| 107 |
4 |
fafa1971 |
*/
|
| 108 |
|
|
|
| 109 |
113 |
albert.wat |
function automatic logic[`WB_DATA_WIDTH/8-1:0] pcxsize2wbmsel(logic [`PCX_SZ_HI-`PCX_SZ_LO:0] access_size, logic [`PCX_AD_HI-`PCX_AD_LO:0] address);
|
| 110 |
|
|
case(access_size)
|
| 111 |
|
|
`PCX_SZ_1B: return (1'b1 << address[2:0]);
|
| 112 |
|
|
`PCX_SZ_2B: return (2'b11 << (address[2:1] << 1));
|
| 113 |
|
|
`PCX_SZ_4B: return (4'b1111 << (address[2] << 2));
|
| 114 |
|
|
`PCX_SZ_8B: return 8'b11111111;
|
| 115 |
|
|
`PCX_SZ_16B: return 8'b11111111; // Requires a 2nd access
|
| 116 |
|
|
default: return 8'b00000000;
|
| 117 |
|
|
endcase // case (access_size)
|
| 118 |
|
|
endfunction
|
| 119 |
4 |
fafa1971 |
|
| 120 |
113 |
albert.wat |
// synopsys translate_off
|
| 121 |
|
|
`ifdef SIMPLY_RISC_DEBUG
|
| 122 |
4 |
fafa1971 |
|
| 123 |
113 |
albert.wat |
task automatic print_pcx_packet(pcx_info_t _pcx_info, pcx_packet_t _pcx_packet);
|
| 124 |
|
|
string str_region, str_type, str_size;
|
| 125 |
|
|
case(_pcx_info.region)
|
| 126 |
|
|
5'b00001: str_region = "RAM_Bank_0";
|
| 127 |
|
|
5'b00010: str_region = "RAM_Bank_1";
|
| 128 |
|
|
5'b00100: str_region = "RAM_Bank_2";
|
| 129 |
|
|
5'b01000: str_region = "RAM Bank_3";
|
| 130 |
|
|
5'b10000: str_region = "IO_Block";
|
| 131 |
|
|
default: str_region = "Unknown";
|
| 132 |
|
|
endcase
|
| 133 |
|
|
case(_pcx_packet.request_type)
|
| 134 |
|
|
`LOAD_RQ: str_type = "LOAD_RQ";
|
| 135 |
|
|
`IMISS_RQ: str_type = "IMISS_RQ";
|
| 136 |
|
|
`STORE_RQ: str_type = "STORE_RQ";
|
| 137 |
|
|
`CAS1_RQ: str_type = "CAS1_RQ";
|
| 138 |
|
|
`CAS2_RQ: str_type = "CAS2_RQ";
|
| 139 |
|
|
`SWAP_RQ: str_type = "SWAP_RQ";
|
| 140 |
|
|
`STRLOAD_RQ: str_type = "STRLOAD_RQ";
|
| 141 |
|
|
`STRST_RQ: str_type = "STRST_RQ";
|
| 142 |
|
|
`STQ_RQ: str_type = "STQ_RQ";
|
| 143 |
|
|
`INT_RQ: str_type = "INT_RQ";
|
| 144 |
|
|
`FWD_RQ: str_type = "FWD_RQ";
|
| 145 |
|
|
`FWD_RPY: str_type = "FWD_RPY";
|
| 146 |
|
|
`RSVD_RQ: str_type = "RSVD_RQ";
|
| 147 |
|
|
default: str_type = "Unknown";
|
| 148 |
|
|
endcase
|
| 149 |
|
|
case(_pcx_packet.access_size)
|
| 150 |
|
|
`PCX_SZ_1B: str_size = "1B";
|
| 151 |
|
|
`PCX_SZ_2B: str_size = "2B";
|
| 152 |
|
|
`PCX_SZ_4B: str_size = "4B";
|
| 153 |
|
|
`PCX_SZ_8B: str_size = "8B";
|
| 154 |
|
|
`PCX_SZ_16B: str_size = "16B";
|
| 155 |
|
|
default: str_size = "Unknown";
|
| 156 |
|
|
endcase
|
| 157 |
|
|
$display("INFO: PCX: REQUEST Region=%s Atomic=%0d Valid=%0d Type=%s NonCache_RnW=%0d PE=%0d.%0d Buffer=%0d L1Way_Packet=%0d Size=%s Address=0x%016X Store_Data=0x%016X", str_region, _pcx_info.atomic, _pcx_packet.valid, str_type, _pcx_packet.noncache_rnw, _pcx_packet.cpu_id, _pcx_packet.thread_id, _pcx_packet.buffer_id, _pcx_packet.l1way_packetid, str_size, _pcx_packet.address, _pcx_packet.store_data);
|
| 158 |
|
|
endtask
|
| 159 |
4 |
fafa1971 |
|
| 160 |
113 |
albert.wat |
task automatic print_cpx_packet(cpx_packet_t _cpx_packet);
|
| 161 |
|
|
string str_type;
|
| 162 |
|
|
case(_cpx_packet.return_type)
|
| 163 |
|
|
`IFILL_RET: str_type = "IFILL_RET";
|
| 164 |
|
|
`LOAD_RET: str_type = "LOAD_RET";
|
| 165 |
|
|
`ST_ACK: str_type = "ST_ACK";
|
| 166 |
|
|
default: str_type = "Unknown";
|
| 167 |
|
|
endcase
|
| 168 |
|
|
$display("INFO: CPX: RETURN Valid=%0d Type=%s Error=%0d NonCache_RnW=%0d Thread=%0d IntSrc_etc=0x%0X Load_Data=%016X", _cpx_packet.valid, str_type, _cpx_packet.error, _cpx_packet.noncache_rnw, _cpx_packet.thread_id, _cpx_packet.intsrc_etc, _cpx_packet.load_data);
|
| 169 |
|
|
endtask
|
| 170 |
4 |
fafa1971 |
|
| 171 |
51 |
fafa1971 |
`endif
|
| 172 |
4 |
fafa1971 |
// synopsys translate_on
|
| 173 |
|
|
|
| 174 |
113 |
albert.wat |
/*
|
| 175 |
|
|
* Signal declarations
|
| 176 |
|
|
*/
|
| 177 |
|
|
|
| 178 |
|
|
// Delayed signals
|
| 179 |
|
|
logic [`SPC_REGION_WIDTH-1:0] spc_req_dly1;
|
| 180 |
|
|
logic [`SPC_REGION_WIDTH-1:0] spc_req_dly2;
|
| 181 |
|
|
logic spc_atom_dly1;
|
| 182 |
|
|
logic spc_atom_dly2;
|
| 183 |
4 |
fafa1971 |
|
| 184 |
113 |
albert.wat |
// PCX FIFO
|
| 185 |
|
|
logic [`PCX_WIDTH+`SPC_INFO_WIDTH-1:0] pcx_fifo_data_in;
|
| 186 |
|
|
logic [`PCX_WIDTH+`SPC_INFO_WIDTH-1:0] pcx_fifo_data_out;
|
| 187 |
|
|
logic pcx_fifo_read;
|
| 188 |
|
|
logic pcx_fifo_write;
|
| 189 |
|
|
logic pcx_fifo_empty;
|
| 190 |
|
|
logic pcx_fifo_full;
|
| 191 |
4 |
fafa1971 |
|
| 192 |
113 |
albert.wat |
// CPX FIFO
|
| 193 |
|
|
logic [`CPX_WIDTH-1:0] cpx_fifo_data_in;
|
| 194 |
|
|
logic [`CPX_WIDTH-1:0] cpx_fifo_data_out;
|
| 195 |
|
|
logic cpx_fifo_read;
|
| 196 |
|
|
logic cpx_fifo_write;
|
| 197 |
|
|
logic cpx_fifo_empty;
|
| 198 |
|
|
logic cpx_fifo_full;
|
| 199 |
4 |
fafa1971 |
|
| 200 |
113 |
albert.wat |
/*
|
| 201 |
|
|
* Tasks
|
| 202 |
|
|
*/
|
| 203 |
4 |
fafa1971 |
|
| 204 |
113 |
albert.wat |
// wbm_clean
|
| 205 |
|
|
task wbm_clean();
|
| 206 |
|
|
wbm_cycle_o = 1'b0;
|
| 207 |
|
|
wbm_strobe_o = 1'b0;
|
| 208 |
|
|
wbm_we_o = 1'b0;
|
| 209 |
|
|
wbm_addr_o = 'h0;
|
| 210 |
|
|
wbm_data_o = 'h0;
|
| 211 |
|
|
wbm_sel_o = 'h0;
|
| 212 |
|
|
endtask // wbm_clean
|
| 213 |
4 |
fafa1971 |
|
| 214 |
113 |
albert.wat |
/*
|
| 215 |
|
|
* FIFO instances
|
| 216 |
|
|
*/
|
| 217 |
4 |
fafa1971 |
|
| 218 |
113 |
albert.wat |
simple_fifo #(
|
| 219 |
|
|
.name("pcx_fifo"),
|
| 220 |
|
|
.fifo_depth(4),
|
| 221 |
|
|
.data_width(`PCX_WIDTH+`SPC_INFO_WIDTH)
|
| 222 |
|
|
) pcx_fifo (
|
| 223 |
|
|
// System inputs
|
| 224 |
|
|
.sys_clock_i(sys_clock_i),
|
| 225 |
|
|
.sys_reset_i(sys_reset_i),
|
| 226 |
4 |
fafa1971 |
|
| 227 |
113 |
albert.wat |
// FIFO inputs
|
| 228 |
|
|
.read(pcx_fifo_read),
|
| 229 |
|
|
.write(pcx_fifo_write),
|
| 230 |
|
|
.data_in(pcx_fifo_data_in),
|
| 231 |
4 |
fafa1971 |
|
| 232 |
113 |
albert.wat |
// FIFO outputs
|
| 233 |
|
|
.empty(pcx_fifo_empty),
|
| 234 |
|
|
.full(pcx_fifo_full), // With the depth defined properly there is no need to handle the full condition - And an assertion in the FIFO would fire anyway on overflow
|
| 235 |
|
|
.data_out(pcx_fifo_data_out)
|
| 236 |
|
|
);
|
| 237 |
4 |
fafa1971 |
|
| 238 |
113 |
albert.wat |
simple_fifo #(
|
| 239 |
|
|
.name("cpx_fifo"),
|
| 240 |
|
|
.fifo_depth(4),
|
| 241 |
|
|
.data_width(`CPX_WIDTH)
|
| 242 |
|
|
) cpx_fifo (
|
| 243 |
|
|
// System inputs
|
| 244 |
|
|
.sys_clock_i(sys_clock_i),
|
| 245 |
|
|
.sys_reset_i(sys_reset_i),
|
| 246 |
4 |
fafa1971 |
|
| 247 |
113 |
albert.wat |
// FIFO inputs
|
| 248 |
|
|
.read(cpx_fifo_read),
|
| 249 |
|
|
.write(cpx_fifo_write),
|
| 250 |
|
|
.data_in(cpx_fifo_data_in),
|
| 251 |
4 |
fafa1971 |
|
| 252 |
113 |
albert.wat |
// FIFO outputs
|
| 253 |
|
|
.empty(cpx_fifo_empty),
|
| 254 |
|
|
.full(cpx_fifo_full),
|
| 255 |
|
|
.data_out(cpx_fifo_data_out)
|
| 256 |
|
|
);
|
| 257 |
4 |
fafa1971 |
|
| 258 |
113 |
albert.wat |
/*
|
| 259 |
|
|
* PCX sampling logic:
|
| 260 |
|
|
* - SPC Logic: Drives SPARC Cores signals related with the PCX interface
|
| 261 |
|
|
* - PCX FIFO Write Logic: Drives pcx_fifo_write and pcx_fifo_data_in
|
| 262 |
|
|
*/
|
| 263 |
4 |
fafa1971 |
|
| 264 |
113 |
albert.wat |
always @(posedge sys_clock_i) begin
|
| 265 |
4 |
fafa1971 |
|
| 266 |
113 |
albert.wat |
// Create delayed version of request and atom
|
| 267 |
|
|
if (sys_reset_i == 1) begin
|
| 268 |
|
|
spc_req_dly1 <= 'h0;
|
| 269 |
|
|
spc_req_dly2 <= 'h0;
|
| 270 |
|
|
spc_atom_dly1 <= 1'b0;
|
| 271 |
|
|
spc_atom_dly2 <= 1'b0;
|
| 272 |
|
|
end else begin
|
| 273 |
|
|
spc_req_dly1 <= spc_req_i;
|
| 274 |
|
|
spc_req_dly2 <= spc_req_dly1;
|
| 275 |
|
|
spc_atom_dly1 <= spc_atom_i;
|
| 276 |
|
|
spc_atom_dly2 <= spc_atom_dly1;
|
| 277 |
|
|
end
|
| 278 |
4 |
fafa1971 |
|
| 279 |
113 |
albert.wat |
// One cycle delay required to sample into the PCX FIFO
|
| 280 |
|
|
if (sys_reset_i == 1'b1 || |spc_req_dly1 == 1'b0) begin
|
| 281 |
|
|
pcx_fifo_write <= 1'b0;
|
| 282 |
|
|
pcx_fifo_data_in <= 'h0;
|
| 283 |
|
|
end else if (|spc_req_dly1 == 1'b1) begin
|
| 284 |
|
|
pcx_fifo_write <= 1'b1;
|
| 285 |
|
|
pcx_fifo_data_in <= {spc_req_dly1, spc_atom_dly1, spc_packetout_i};
|
| 286 |
4 |
fafa1971 |
// synopsys translate_off
|
| 287 |
113 |
albert.wat |
`ifdef SIMPLY_RISC_DEBUG
|
| 288 |
|
|
// Print details of SPARC Core request
|
| 289 |
|
|
print_pcx_packet({spc_req_dly1, spc_atom_dly1}, spc_packetout_i);
|
| 290 |
51 |
fafa1971 |
`endif
|
| 291 |
4 |
fafa1971 |
// synopsys translate_on
|
| 292 |
113 |
albert.wat |
end
|
| 293 |
4 |
fafa1971 |
|
| 294 |
113 |
albert.wat |
end // always @ (posedge sys_clock_i)
|
| 295 |
|
|
|
| 296 |
|
|
// Two cycles delay required to return the grant
|
| 297 |
|
|
assign spc_grant_o = spc_req_dly2;
|
| 298 |
4 |
fafa1971 |
|
| 299 |
113 |
albert.wat |
/*
|
| 300 |
|
|
* PCX-to-WBM-to-CPX:
|
| 301 |
|
|
* - PCX FIFO Read Logic: Drives pcx_fifo_read and reads pcx_fifo_data_out
|
| 302 |
|
|
* - WBM Logic: Drives all Wishbone signals
|
| 303 |
|
|
* - CPX FIFO Write Logic: Drives cpx_fifo_write and cpx_data_in
|
| 304 |
|
|
*/
|
| 305 |
4 |
fafa1971 |
|
| 306 |
113 |
albert.wat |
typedef enum logic[3:0] {FSM_WAKEUP, FSM_IDLE, FSM_WBM_BEGIN1, FSM_WBM_END1, FSM_WBM_BEGIN2, FSM_WBM_END2, FSM_WBM_BEGIN3, FSM_WBM_END3, FSM_WBM_BEGIN4, FSM_WBM_END4, FSM_CPX_FIFO_WRITE} fsm_state_t;
|
| 307 |
|
|
fsm_state_t fsm_state;
|
| 308 |
|
|
pcx_info_t pcx_info;
|
| 309 |
|
|
pcx_packet_t pcx_packet;
|
| 310 |
|
|
cpx_packet_t cpx_packet;
|
| 311 |
4 |
fafa1971 |
|
| 312 |
113 |
albert.wat |
always @(posedge sys_clock_i) begin
|
| 313 |
|
|
if (sys_reset_i == 1) begin
|
| 314 |
|
|
// Clear outputs connected to FIFOs
|
| 315 |
|
|
pcx_fifo_read <= 1'b0;
|
| 316 |
|
|
cpx_fifo_write <= 1'b0;
|
| 317 |
|
|
cpx_fifo_data_in <= 'h0;
|
| 318 |
|
|
// Clear Wishbone outputs
|
| 319 |
|
|
wbm_clean();
|
| 320 |
|
|
// Initialize the first FSM state
|
| 321 |
|
|
fsm_state <= FSM_WAKEUP;
|
| 322 |
|
|
// Prepare the wakeup packet for SPARC Core: `CPX_WIDTH'h1700000000000000000000000000000010001;
|
| 323 |
|
|
cpx_packet.valid <= 1;
|
| 324 |
|
|
cpx_packet.return_type <= `INT_RET;
|
| 325 |
|
|
cpx_packet.error <= 0;
|
| 326 |
|
|
cpx_packet.noncache_rnw <= 0;
|
| 327 |
|
|
cpx_packet.thread_id <= 0;
|
| 328 |
|
|
cpx_packet.intsrc_etc <= 7'h0;
|
| 329 |
|
|
cpx_packet.load_data <= 128'h10001;
|
| 330 |
|
|
end else begin
|
| 331 |
|
|
case(fsm_state)
|
| 332 |
|
|
// Send the wakeup packet to the SPARC Core
|
| 333 |
|
|
FSM_WAKEUP: begin
|
| 334 |
|
|
cpx_fifo_write <= 1'b1;
|
| 335 |
|
|
cpx_fifo_data_in <= cpx_packet;
|
| 336 |
|
|
fsm_state <= FSM_IDLE;
|
| 337 |
|
|
end
|
| 338 |
|
|
// Wait for a new request to be available in the PCX FIFO and read it
|
| 339 |
|
|
FSM_IDLE: begin
|
| 340 |
|
|
cpx_fifo_write <= 1'b0;
|
| 341 |
|
|
cpx_fifo_data_in <= 'h0;
|
| 342 |
|
|
if (pcx_fifo_empty != 1'b1) begin
|
| 343 |
|
|
pcx_fifo_read <= 1'b1;
|
| 344 |
|
|
{ pcx_info, pcx_packet } <= pcx_fifo_data_out;
|
| 345 |
|
|
fsm_state <= FSM_WBM_BEGIN1;
|
| 346 |
|
|
end
|
| 347 |
|
|
end
|
| 348 |
|
|
// Start a request on the Wishbone bus
|
| 349 |
|
|
FSM_WBM_BEGIN1: begin
|
| 350 |
|
|
if (pcx_info.region == 5'b10000)
|
| 351 |
|
|
pcx_packet.address[3] = 0; // Smells fishy, I may just load half (64b / 8B / 2instr)
|
| 352 |
|
|
pcx_fifo_read <= 1'b0;
|
| 353 |
|
|
wbm_cycle_o <= 1;
|
| 354 |
|
|
wbm_strobe_o <= 1;
|
| 355 |
|
|
wbm_addr_o <= { pcx_info.region, 19'b0, pcx_packet.address[`PCX_AD_HI-`PCX_AD_LO:3], 3'b000 };
|
| 356 |
|
|
wbm_data_o <= pcx_packet.store_data;
|
| 357 |
|
|
case(pcx_packet.request_type)
|
| 358 |
|
|
`IMISS_RQ: begin
|
| 359 |
|
|
// For instruction miss always read memory
|
| 360 |
|
|
wbm_we_o <= 0;
|
| 361 |
|
|
wbm_sel_o <= 8'b11111111;
|
| 362 |
|
|
end // case: `IMISS_RQ
|
| 363 |
|
|
`LOAD_RQ: begin
|
| 364 |
|
|
// For data load use the provided data
|
| 365 |
|
|
wbm_we_o <= 0;
|
| 366 |
|
|
wbm_sel_o <= pcxsize2wbmsel(pcx_packet.access_size, pcx_packet.address);
|
| 367 |
|
|
end // case: `LOAD_RQ
|
| 368 |
|
|
`STORE_RQ: begin
|
| 369 |
|
|
// For data store use the provided data
|
| 370 |
|
|
wbm_we_o <= 1;
|
| 371 |
|
|
wbm_sel_o <= pcxsize2wbmsel(pcx_packet.access_size, pcx_packet.address);
|
| 372 |
|
|
end // case: `STORE_RQ
|
| 373 |
|
|
default: begin
|
| 374 |
|
|
$fatal(1, "Entered default condition of PCX FSM as request_type=0x%02X", pcx_packet.request_type);
|
| 375 |
|
|
wbm_we_o <= 1;
|
| 376 |
|
|
wbm_sel_o <= 8'b00000000;
|
| 377 |
|
|
end
|
| 378 |
|
|
endcase
|
| 379 |
|
|
fsm_state <= FSM_WBM_END1;
|
| 380 |
|
|
end // case: FSM_WBM_BEGIN1
|
| 381 |
|
|
// Wait for the ack from the Wishbone bus and latch the incoming data
|
| 382 |
|
|
FSM_WBM_END1: begin
|
| 383 |
|
|
if (wbm_ack_i == 1) begin
|
| 384 |
|
|
if (pcx_info.atomic == 0) wbm_cycle_o <= 0;
|
| 385 |
|
|
wbm_strobe_o <= 0;
|
| 386 |
|
|
wbm_we_o <= 0;
|
| 387 |
|
|
wbm_addr_o <= 64'b0;
|
| 388 |
|
|
wbm_data_o <= 64'b0;
|
| 389 |
|
|
wbm_sel_o <= 8'b0;
|
| 390 |
4 |
fafa1971 |
|
| 391 |
113 |
albert.wat |
// Encode the CPX return packet and store it in the second FIFO
|
| 392 |
|
|
cpx_packet.valid = 1;
|
| 393 |
|
|
case(pcx_packet.request_type)
|
| 394 |
|
|
`IMISS_RQ: begin
|
| 395 |
|
|
cpx_packet.return_type = `IFILL_RET; // I-Cache Miss
|
| 396 |
|
|
end
|
| 397 |
|
|
`LOAD_RQ: begin
|
| 398 |
|
|
cpx_packet.return_type = `LOAD_RET; // Load
|
| 399 |
|
|
end
|
| 400 |
|
|
`STORE_RQ: begin
|
| 401 |
|
|
cpx_packet.return_type = `ST_ACK; // Store
|
| 402 |
|
|
end
|
| 403 |
|
|
endcase
|
| 404 |
|
|
cpx_packet.error = 0;
|
| 405 |
|
|
cpx_packet.noncache_rnw = pcx_packet.noncache_rnw;
|
| 406 |
|
|
cpx_packet.thread_id = pcx_packet.thread_id;
|
| 407 |
|
|
cpx_packet.intsrc_etc = 6'b000100;
|
| 408 |
|
|
if (pcx_packet.address[3] == 0)
|
| 409 |
|
|
cpx_packet.load_data = { wbm_data_i, 64'b0 };
|
| 410 |
|
|
else
|
| 411 |
|
|
cpx_packet.load_data = { 64'b0, wbm_data_i };
|
| 412 |
4 |
fafa1971 |
|
| 413 |
113 |
albert.wat |
// See if other 64-bit Wishbone accesses are required
|
| 414 |
|
|
if ( (pcx_packet.request_type == `IMISS_RQ) ||
|
| 415 |
|
|
// Instruction miss directed to RAM expects 256 bits
|
| 416 |
|
|
( (pcx_packet.request_type == `LOAD_RQ) && (pcx_packet.access_size == `PCX_SZ_16B) )
|
| 417 |
|
|
// Data access of 128 bits
|
| 418 |
|
|
) begin
|
| 419 |
|
|
fsm_state <= FSM_WBM_BEGIN2;
|
| 420 |
|
|
end else begin
|
| 421 |
|
|
fsm_state <= FSM_CPX_FIFO_WRITE;
|
| 422 |
|
|
end
|
| 423 |
4 |
fafa1971 |
|
| 424 |
113 |
albert.wat |
end
|
| 425 |
|
|
end // case: FSM_WBM_END1
|
| 426 |
|
|
// If needed start a second read access to the Wishbone bus
|
| 427 |
|
|
FSM_WBM_BEGIN2: begin
|
| 428 |
|
|
|
| 429 |
|
|
// Issue a second request on the Wishbone bus
|
| 430 |
|
|
wbm_cycle_o <= 1;
|
| 431 |
|
|
wbm_strobe_o <= 1;
|
| 432 |
51 |
fafa1971 |
wbm_we_o <= 0;
|
| 433 |
113 |
albert.wat |
wbm_addr_o <= { pcx_info.region, 19'b0, pcx_packet.address[`PCX_AD_HI-`PCX_AD_LO:4], 4'b1000 }; // 2nd doubleword inside the same quadword
|
| 434 |
|
|
wbm_data_o <= 64'b0;
|
| 435 |
|
|
wbm_sel_o <= 8'b11111111;
|
| 436 |
4 |
fafa1971 |
|
| 437 |
113 |
albert.wat |
// Unconditional state change
|
| 438 |
|
|
fsm_state <= FSM_WBM_END2;
|
| 439 |
11 |
fafa1971 |
|
| 440 |
113 |
albert.wat |
end // case: FSM_WBM_BEGIN2
|
| 441 |
4 |
fafa1971 |
|
| 442 |
113 |
albert.wat |
// Latch the second data returning from Wishbone when ready
|
| 443 |
|
|
FSM_WBM_END2: begin
|
| 444 |
11 |
fafa1971 |
|
| 445 |
113 |
albert.wat |
// Wait until Wishbone access completes
|
| 446 |
|
|
if (wbm_ack_i == 1) begin
|
| 447 |
11 |
fafa1971 |
|
| 448 |
113 |
albert.wat |
// Clear previously modified outputs
|
| 449 |
|
|
if (pcx_info.atomic == 0) wbm_cycle_o <= 0;
|
| 450 |
|
|
wbm_strobe_o <= 0;
|
| 451 |
|
|
wbm_we_o <= 0;
|
| 452 |
|
|
wbm_addr_o <= 64'b0;
|
| 453 |
|
|
wbm_data_o <= 64'b0;
|
| 454 |
|
|
wbm_sel_o <= 8'b0;
|
| 455 |
4 |
fafa1971 |
|
| 456 |
113 |
albert.wat |
// Latch the data and set up the return packet for the SPARC Core (this is the second half)
|
| 457 |
|
|
if (pcx_packet.address[3] == 1)
|
| 458 |
|
|
cpx_packet.load_data = { wbm_data_i, cpx_packet.load_data[63:0] };
|
| 459 |
|
|
else
|
| 460 |
|
|
cpx_packet.load_data = { cpx_packet.load_data[127:64], wbm_data_i };
|
| 461 |
|
|
|
| 462 |
4 |
fafa1971 |
// synopsys translate_off
|
| 463 |
113 |
albert.wat |
`ifdef SIMPLY_RISC_DEBUG
|
| 464 |
|
|
// Print details of return packet
|
| 465 |
|
|
print_cpx_packet(cpx_packet);
|
| 466 |
51 |
fafa1971 |
`endif
|
| 467 |
4 |
fafa1971 |
// synopsys translate_on
|
| 468 |
|
|
|
| 469 |
113 |
albert.wat |
// See if two return packets are required or just one - TODO checkme
|
| 470 |
|
|
// if (pcx_packet.request_type == `IMISS_RQ && pcx_info.region == 5'b10000)
|
| 471 |
|
|
fsm_state <= FSM_CPX_FIFO_WRITE;
|
| 472 |
|
|
// else
|
| 473 |
|
|
// fsm_state <= FSM_WBM_BEGIN3;
|
| 474 |
4 |
fafa1971 |
|
| 475 |
113 |
albert.wat |
end // else fsm_state <= FSM_WBM_END2;
|
| 476 |
|
|
end // case: FSM_WBM_END2
|
| 477 |
4 |
fafa1971 |
|
| 478 |
113 |
albert.wat |
// If needed start a third read access to the Wishbone bus
|
| 479 |
|
|
// In the meanwhile we can return the first 128-bit packet
|
| 480 |
|
|
FSM_WBM_BEGIN3: begin
|
| 481 |
4 |
fafa1971 |
|
| 482 |
113 |
albert.wat |
// Issue a third request on the Wishbone bus
|
| 483 |
|
|
wbm_cycle_o <= 1;
|
| 484 |
|
|
wbm_strobe_o <= 1;
|
| 485 |
51 |
fafa1971 |
wbm_we_o <= 0;
|
| 486 |
113 |
albert.wat |
wbm_addr_o <= { pcx_info.region, 19'b0, pcx_packet.address[`PCX_AD_HI-`PCX_AD_LO:5], 5'b10000 }; // 3nd doubleword inside the same 256-bit data
|
| 487 |
51 |
fafa1971 |
wbm_data_o <= 64'b0;
|
| 488 |
113 |
albert.wat |
wbm_sel_o <= 8'b11111111;
|
| 489 |
4 |
fafa1971 |
|
| 490 |
113 |
albert.wat |
// Unconditional state change
|
| 491 |
|
|
fsm_state <= FSM_WBM_END3;
|
| 492 |
4 |
fafa1971 |
|
| 493 |
113 |
albert.wat |
end // case: FSM_WBM_BEGIN3
|
| 494 |
4 |
fafa1971 |
|
| 495 |
113 |
albert.wat |
// Latch the second data returning from Wishbone when ready
|
| 496 |
|
|
FSM_WBM_END3: begin
|
| 497 |
4 |
fafa1971 |
|
| 498 |
113 |
albert.wat |
// Wait until Wishbone access completes
|
| 499 |
|
|
if (wbm_ack_i == 1) begin
|
| 500 |
4 |
fafa1971 |
|
| 501 |
113 |
albert.wat |
// Clear previously modified outputs
|
| 502 |
|
|
if (pcx_info.atomic == 0) wbm_cycle_o <= 0;
|
| 503 |
|
|
wbm_strobe_o <= 0;
|
| 504 |
|
|
wbm_we_o <= 0;
|
| 505 |
|
|
wbm_addr_o <= 64'b0;
|
| 506 |
|
|
wbm_data_o <= 64'b0;
|
| 507 |
|
|
wbm_sel_o <= 8'b0;
|
| 508 |
4 |
fafa1971 |
|
| 509 |
113 |
albert.wat |
// Latch the data and set up the return packet for the SPARC Core - TODO CHECKME
|
| 510 |
|
|
// cpx_packet.load_data = { wbm_data_i, 64'b0 };
|
| 511 |
4 |
fafa1971 |
|
| 512 |
113 |
albert.wat |
// Jump to next state
|
| 513 |
|
|
fsm_state <= FSM_WBM_BEGIN4;
|
| 514 |
4 |
fafa1971 |
|
| 515 |
113 |
albert.wat |
end // else fsm_state <= FSM_WBM_END3; // if (wbm_ack_i == 1)
|
| 516 |
|
|
end // case: FSM_WBM_END3
|
| 517 |
4 |
fafa1971 |
|
| 518 |
113 |
albert.wat |
// If needed start a second read access to the Wishbone bus
|
| 519 |
|
|
FSM_WBM_BEGIN4: begin
|
| 520 |
4 |
fafa1971 |
|
| 521 |
113 |
albert.wat |
// Issue a fourth request on the Wishbone bus
|
| 522 |
|
|
wbm_cycle_o <= 1;
|
| 523 |
|
|
wbm_strobe_o <= 1;
|
| 524 |
51 |
fafa1971 |
wbm_we_o <= 0;
|
| 525 |
113 |
albert.wat |
wbm_addr_o <= { pcx_info.region, 19'b0, pcx_packet.address[`PCX_AD_HI-`PCX_AD_LO:5], 5'b11000 }; // 4th doubleword inside the same 256-bit data
|
| 526 |
51 |
fafa1971 |
wbm_data_o <= 64'b0;
|
| 527 |
113 |
albert.wat |
wbm_sel_o <= 8'b11111111;
|
| 528 |
4 |
fafa1971 |
|
| 529 |
113 |
albert.wat |
// Unconditional state change
|
| 530 |
|
|
fsm_state <= FSM_WBM_END4;
|
| 531 |
|
|
end // case: FSM_WBM_BEGIN4
|
| 532 |
4 |
fafa1971 |
|
| 533 |
113 |
albert.wat |
// Latch the second data returning from Wishbone when ready
|
| 534 |
|
|
FSM_WBM_END4: begin
|
| 535 |
4 |
fafa1971 |
|
| 536 |
113 |
albert.wat |
// Wait until Wishbone access completes
|
| 537 |
|
|
if (wbm_ack_i == 1) begin
|
| 538 |
4 |
fafa1971 |
|
| 539 |
113 |
albert.wat |
// Clear previously modified outputs
|
| 540 |
|
|
if (pcx_info.atomic == 0) wbm_cycle_o <= 0;
|
| 541 |
|
|
wbm_strobe_o <= 0;
|
| 542 |
|
|
wbm_we_o <= 0;
|
| 543 |
|
|
wbm_addr_o <= 64'b0;
|
| 544 |
|
|
wbm_data_o <= 64'b0;
|
| 545 |
|
|
wbm_sel_o <= 8'b0;
|
| 546 |
4 |
fafa1971 |
|
| 547 |
113 |
albert.wat |
// Latch the data and set up the return packet for the SPARC Core
|
| 548 |
|
|
// cpx_packet.load_data = { 64'h0, wbm_data_i};
|
| 549 |
4 |
fafa1971 |
|
| 550 |
113 |
albert.wat |
// Jump to next state
|
| 551 |
|
|
fsm_state <= FSM_CPX_FIFO_WRITE;
|
| 552 |
4 |
fafa1971 |
|
| 553 |
113 |
albert.wat |
end // else fsm_state <= FSM_WBM_END4; // if (wbm_ack_i == 1)
|
| 554 |
|
|
end // case: FSM_WBM_END4
|
| 555 |
4 |
fafa1971 |
|
| 556 |
113 |
albert.wat |
// We can start returning the packet to the SPARC Core
|
| 557 |
|
|
FSM_CPX_FIFO_WRITE: begin
|
| 558 |
4 |
fafa1971 |
|
| 559 |
113 |
albert.wat |
// Write the packet to the CPX FIFO
|
| 560 |
|
|
cpx_fifo_write <= 1'b1;
|
| 561 |
|
|
cpx_fifo_data_in <= cpx_packet;
|
| 562 |
4 |
fafa1971 |
|
| 563 |
113 |
albert.wat |
// Unconditional state change
|
| 564 |
|
|
fsm_state <= FSM_IDLE;
|
| 565 |
4 |
fafa1971 |
|
| 566 |
113 |
albert.wat |
// synopsys translate_off
|
| 567 |
|
|
`ifdef SIMPLY_RISC_DEBUG
|
| 568 |
|
|
// Print details of return packet
|
| 569 |
|
|
print_cpx_packet(cpx_packet);
|
| 570 |
|
|
`endif
|
| 571 |
|
|
// synopsys translate_on
|
| 572 |
|
|
end // case: FSM_CPX_FIFO_WRITE
|
| 573 |
4 |
fafa1971 |
|
| 574 |
113 |
albert.wat |
endcase // case (fsm_state)
|
| 575 |
|
|
end
|
| 576 |
|
|
end
|
| 577 |
4 |
fafa1971 |
|
| 578 |
113 |
albert.wat |
/*
|
| 579 |
|
|
* CPX FIFO handler
|
| 580 |
|
|
* - SPARC Core Logic: Drives SPARC Core signals related with the CPX interface
|
| 581 |
|
|
* - CPX FIFO Read Logic: Drives cpx_fifo_read and reads cpx_data_out
|
| 582 |
|
|
*/
|
| 583 |
4 |
fafa1971 |
|
| 584 |
113 |
albert.wat |
typedef enum logic[2:0] {CPX_IDLE, CPX_DRIVE_CORE} cpx_state_t;
|
| 585 |
|
|
cpx_state_t cpx_state;
|
| 586 |
|
|
cpx_packet_t cpx_packet_2;
|
| 587 |
4 |
fafa1971 |
|
| 588 |
113 |
albert.wat |
always @(posedge sys_clock_i) begin
|
| 589 |
|
|
if (sys_reset_i == 1) begin
|
| 590 |
|
|
spc_ready_o <= 0;
|
| 591 |
|
|
spc_packetin_o <= 0;
|
| 592 |
|
|
cpx_fifo_read <= 1'b0;
|
| 593 |
|
|
cpx_state <= CPX_IDLE;
|
| 594 |
|
|
end else begin
|
| 595 |
|
|
case (cpx_state)
|
| 596 |
|
|
CPX_IDLE: begin
|
| 597 |
|
|
spc_ready_o <= 0;
|
| 598 |
|
|
spc_packetin_o <= 'h0;
|
| 599 |
|
|
if (cpx_fifo_empty) begin
|
| 600 |
|
|
cpx_fifo_read <= 1'b0;
|
| 601 |
|
|
end else begin
|
| 602 |
|
|
cpx_fifo_read <= 1'b1;
|
| 603 |
|
|
cpx_packet_2 <= cpx_fifo_data_out;
|
| 604 |
|
|
cpx_state <= CPX_DRIVE_CORE;
|
| 605 |
|
|
end
|
| 606 |
|
|
end
|
| 607 |
|
|
CPX_DRIVE_CORE: begin
|
| 608 |
|
|
cpx_fifo_read <= 1'b0;
|
| 609 |
|
|
spc_ready_o <= 1;
|
| 610 |
|
|
spc_packetin_o <= cpx_packet_2;
|
| 611 |
|
|
cpx_state <= CPX_IDLE;
|
| 612 |
|
|
end
|
| 613 |
|
|
endcase // case (cpx_state)
|
| 614 |
|
|
end // else: !if (sys_reset_i == 1)
|
| 615 |
|
|
end // always @ (posedge sys_clock_i)
|
| 616 |
99 |
fafa1971 |
|
| 617 |
4 |
fafa1971 |
endmodule
|
| 618 |
|
|
|