Line 1... |
Line 1... |
/*
|
/*
|
* Bridge from SPARC Core to Wishbone Master
|
* Bridge from SPARC Core to Wishbone Master
|
*
|
*
|
* (C) 2007 Simply RISC LLP
|
* (C) 2006-2007 Simply RISC LLP
|
* AUTHOR: Fabrizio Fazzino <fabrizio.fazzino@srisc.com>
|
* AUTHOR: Fabrizio Fazzino <fabrizio.fazzino@srisc.com>
|
*
|
*
|
* LICENSE:
|
* LICENSE:
|
* This is a Free Hardware Design; you can redistribute it and/or
|
* This is a Free Hardware Design; you can redistribute it and/or
|
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
Line 22... |
Line 22... |
* For informations about OpenCores' Wishbone interconnect
|
* For informations about OpenCores' Wishbone interconnect
|
* please refer to the web site http://www.opencores.org
|
* please refer to the web site http://www.opencores.org
|
*/
|
*/
|
|
|
`include "s1_defs.h"
|
`include "s1_defs.h"
|
|
`define SPC_REGION_HI 4
|
|
`define SPC_REGION_LO 0
|
|
`define SPC_REGION_WIDTH (`SPC_REGION_HI-`SPC_REGION_LO+1)
|
|
`define SPC_INFO_WIDTH (`SPC_REGION_WIDTH+1)
|
|
|
module spc2wbm (
|
module spc2wbm (
|
|
|
/*
|
/*
|
* Inputs
|
* Inputs
|
Line 35... |
Line 39... |
input sys_clock_i, // System Clock
|
input sys_clock_i, // System Clock
|
input sys_reset_i, // System Reset
|
input sys_reset_i, // System Reset
|
input[5:0] sys_interrupt_source_i, // Encoded Interrupt Source
|
input[5:0] sys_interrupt_source_i, // Encoded Interrupt Source
|
|
|
// SPARC-side inputs connected to the PCX (Processor-to-Cache Xbar) outputs of the SPARC Core
|
// SPARC-side inputs connected to the PCX (Processor-to-Cache Xbar) outputs of the SPARC Core
|
input[4:0] spc_req_i, // Request
|
input[`SPC_REGION_WIDTH-1:0] spc_req_i, // Request Region
|
input spc_atom_i, // Atomic Request
|
input spc_atom_i, // Atomic Request
|
input[(`PCX_WIDTH-1):0] spc_packetout_i, // Outgoing Packet
|
input[(`PCX_WIDTH-1):0] spc_packetout_i, // Outgoing Packet
|
|
|
// Wishbone Master interface inputs
|
// Wishbone Master interface inputs
|
input wbm_ack_i, // Ack
|
input wbm_ack_i, // Ack
|
Line 48... |
Line 52... |
/*
|
/*
|
* Outputs
|
* Outputs
|
*/
|
*/
|
|
|
// SPARC-side outputs connected to the CPX (Cache-to-Processor Xbar) inputs of the SPARC Core
|
// SPARC-side outputs connected to the CPX (Cache-to-Processor Xbar) inputs of the SPARC Core
|
output reg[4:0] spc_grant_o, // Grant
|
output logic[4:0] spc_grant_o, // Grant
|
output reg spc_ready_o, // Ready
|
output reg spc_ready_o, // Ready
|
output reg[`CPX_WIDTH-1:0] spc_packetin_o, // Incoming Packet
|
output reg[`CPX_WIDTH-1:0] spc_packetin_o, // Incoming Packet
|
output reg spc_stall_o, // Stall Requests
|
|
output reg spc_resume_o, // Resume Requests
|
|
|
|
// Wishbone Master interface outputs
|
// Wishbone Master interface outputs
|
output reg wbm_cycle_o, // Cycle Start
|
output reg wbm_cycle_o, // Cycle Start
|
output reg wbm_strobe_o, // Strobe Request
|
output reg wbm_strobe_o, // Strobe Request
|
output reg wbm_we_o, // Write Enable
|
output reg wbm_we_o, // Write Enable
|
Line 64... |
Line 66... |
output reg[`WB_DATA_WIDTH-1:0] wbm_data_o, // Data Out
|
output reg[`WB_DATA_WIDTH-1:0] wbm_data_o, // Data Out
|
output reg[`WB_DATA_WIDTH/8-1:0] wbm_sel_o // Select Output
|
output reg[`WB_DATA_WIDTH/8-1:0] wbm_sel_o // Select Output
|
|
|
);
|
);
|
|
|
|
|
/*
|
|
* Registers
|
|
*/
|
|
|
|
// Registers to latch requests from SPARC Core to Wishbone Master
|
|
reg[3:0] state;
|
|
reg[4:0] spc2wbm_region; // Target region number (one-hot encoded)
|
|
reg spc2wbm_atomic; // Request is Atomic
|
|
reg[(`PCX_WIDTH-1):0] spc2wbm_packet; // Latched Packet
|
|
|
|
// Wishbone Master to SPARC Core info used to encode the return packet
|
|
reg wbm2spc_valid; // Valid
|
|
reg[(`CPX_RQ_HI-`CPX_RQ_LO):0] wbm2spc_type; // Request type
|
|
reg wbm2spc_miss; // L2 Miss
|
|
reg[(`CPX_ERR_HI-`CPX_ERR_LO-1):0] wbm2spc_error; // Error
|
|
reg wbm2spc_nc; // Non-Cacheable
|
|
reg[(`CPX_TH_HI-`CPX_TH_LO):0] wbm2spc_thread; // Thread
|
|
reg wbm2spc_way_valid; // L2 Way Valid
|
|
reg[(`CPX_WY_HI-`CPX_WY_LO):0] wbm2spc_way; // Replaced L2 Way
|
|
reg wbm2spc_boot_fetch; // Fetch for Boot
|
|
reg wbm2spc_atomic; // Atomic LD/ST or 2nd IFill packet
|
|
reg wbm2spc_pfl; // PFL
|
|
reg[(`CPX_DA_HI-`CPX_DA_LO):0] wbm2spc_data; // Load Data
|
|
reg[6:0] wbm2spc_interrupt_source; // Encoded Interrupt Source
|
|
reg wbm2spc_interrupt_new; // New Interrupt Pending
|
|
|
|
/*
|
|
* Wires
|
|
*/
|
|
|
|
// Decoded SPARC Core to Wishbone Master info
|
|
wire spc2wbm_req; // Request
|
|
wire spc2wbm_valid; // Valid
|
|
wire[(`PCX_RQ_HI-`PCX_RQ_LO):0] spc2wbm_type; // Request type
|
|
wire spc2wbm_nc; // Non-Cacheable
|
|
wire[(`PCX_CP_HI-`PCX_CP_LO):0] spc2wbm_cpu_id; // CPU ID
|
|
wire[(`PCX_TH_HI-`PCX_TH_LO):0] spc2wbm_thread; // Thread
|
|
wire spc2wbm_invalidate; // Invalidate all
|
|
wire[(`PCX_WY_HI-`PCX_WY_LO):0] spc2wbm_way; // Replaced L1 Way
|
|
wire[(`PCX_SZ_HI-`PCX_SZ_LO):0] spc2wbm_size; // Load/Store size
|
|
wire[(`PCX_AD_HI-`PCX_AD_LO):0] spc2wbm_addr; // Address
|
|
wire[(`PCX_DA_HI-`PCX_DA_LO):0] spc2wbm_data; // Store Data
|
|
|
|
// Return packets assembled with various fields
|
|
wire[`CPX_WIDTH-1:0] wbm2spc_packet; // Incoming Packet
|
|
|
|
/*
|
/*
|
* Encode/decode incoming info
|
* Packet Structures
|
*
|
|
* Legenda: available constants for some of the PCX/CPX fields.
|
|
*
|
|
* spc2wbm_size (3 bits) is one of:
|
|
* - PCX_SZ_1B
|
|
* - PCX_SZ_2B
|
|
* - PCX_SZ_4B
|
|
* - PCX_SZ_8B
|
|
* - PCX_SZ_16B (Read accesses only)
|
|
*
|
|
* spc2wbm_type (5 bits) is one of:
|
|
* { LOAD_RQ, IMISS_RQ, STORE_RQ, CAS1_RQ, CAS2_RQ, SWAP_RQ, STRLOAD_RQ, STRST_RQ, STQ_RQ,
|
|
* INT_RQ, FWD_RQ, FWD_RPY, RSVD_RQ }
|
|
*
|
|
* wbm2spc_type (4 bits) is one of:
|
|
* { LOAD_RET, INV_RET, ST_ACK, AT_ACK, INT_RET, TEST_RET, FP_RET, IFILL_RET, EVICT_REQ,
|
|
* ERR_RET, STRLOAD_RET, STRST_ACK, FWD_RQ_RET, FWD_RPY_RET, RSVD_RET }
|
|
*
|
|
*/
|
*/
|
|
|
// Decode info arriving from the SPC side
|
// Processor-to-Cache Xbar request region and atomic info
|
assign spc2wbm_req = ( spc_req_i[4] | spc_req_i[3] | spc_req_i[2] | spc_req_i[1] | spc_req_i[0] );
|
typedef struct packed {
|
assign spc2wbm_valid = spc2wbm_packet[`PCX_VLD];
|
logic [`SPC_REGION_WIDTH-1:0] region; // info[5:1] Region
|
assign spc2wbm_type = spc2wbm_packet[`PCX_RQ_HI:`PCX_RQ_LO];
|
logic atomic; // info[0] Atomicity
|
assign spc2wbm_nc = spc2wbm_packet[`PCX_NC];
|
} pcx_info_t;
|
assign spc2wbm_cpu_id = spc2wbm_packet[`PCX_CP_HI:`PCX_CP_LO];
|
|
assign spc2wbm_thread = spc2wbm_packet[`PCX_TH_HI:`PCX_TH_LO];
|
// Processor-to-Cache Xbar request packet type (PCX payload 124-bit)
|
assign spc2wbm_invalidate = spc2wbm_packet[`PCX_INVALL];
|
typedef struct packed {
|
assign spc2wbm_way = spc2wbm_packet[`PCX_WY_HI:`PCX_WY_LO];
|
logic valid; // pcx[123] Packet Valid
|
assign spc2wbm_size = spc2wbm_packet[`PCX_SZ_HI:`PCX_SZ_LO];
|
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)
|
assign spc2wbm_addr = spc2wbm_packet[`PCX_AD_HI:`PCX_AD_LO];
|
logic noncache_rnw; // pcx[117] Non-Cacheable, or ReadNotWrite
|
assign spc2wbm_data = spc2wbm_packet[`PCX_DA_HI:`PCX_DA_LO];
|
logic [`PCX_CP_HI-`PCX_CP_LO:0] cpu_id; // pcx[116:114] CPU ID
|
|
logic [`PCX_TH_HI-`PCX_TH_LO:0] thread_id; // pcx[113:112] Thread ID
|
// Encode info going to the SPC side assembling return packets
|
logic [`PCX_BF_HI-`PCX_BF_LO:0] buffer_id; // pcx[111:109] Buffer ID
|
assign wbm2spc_packet = { wbm2spc_valid, wbm2spc_type, wbm2spc_miss, wbm2spc_error, wbm2spc_nc, wbm2spc_thread,
|
logic [`PCX_WY_HI-`PCX_WY_LO:0] l1way_packetid;// pcx[108:107] L1 Way Replaced, or Packet ID
|
wbm2spc_way_valid, wbm2spc_way, wbm2spc_boot_fetch, wbm2spc_atomic, wbm2spc_pfl, wbm2spc_data };
|
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
|
|
logic [`PCX_AD_HI-`PCX_AD_LO:0] address; // pcx[103:64] Address
|
|
logic [`PCX_DA_HI-`PCX_DA_LO:0] store_data; // pcx[63:0] Store Data
|
|
} pcx_packet_t;
|
|
|
|
// Cache-to-Processor Xbar return packet type (CPX payload 145-bit)
|
|
typedef struct packed {
|
|
logic valid; // cpx[144] Packet Valid
|
|
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)
|
|
logic [`CPX_ERR_HI-`CPX_ERR_LO:0] error; // cpx[139:137] Error
|
|
logic noncache_rnw;// cpx[136] Non-Cacheable, or ReadNotWrite
|
|
logic [`CPX_TH_HI-`CPX_TH_LO:0] thread_id; // cpx[135:134] Thread ID
|
|
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.
|
|
logic [`CPX_DA_HI-`CPX_DA_LO:0] load_data; // cpx[127:0] Load Data
|
|
} cpx_packet_t;
|
|
|
/*
|
/*
|
* State Machine
|
* Useful Function
|
*/
|
*/
|
|
|
always @(posedge sys_clock_i) begin
|
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);
|
|
case(access_size)
|
// Initialization
|
`PCX_SZ_1B: return (1'b1 << address[2:0]);
|
if(sys_reset_i==1) begin
|
`PCX_SZ_2B: return (2'b11 << (address[2:1] << 1));
|
|
`PCX_SZ_4B: return (4'b1111 << (address[2] << 2));
|
// Clear outputs going to SPARC Core inputs
|
`PCX_SZ_8B: return 8'b11111111;
|
spc_grant_o <= 5'b00000;
|
`PCX_SZ_16B: return 8'b11111111; // Requires a 2nd access
|
spc_ready_o <= 0;
|
default: return 8'b00000000;
|
spc_packetin_o <= 0;
|
endcase // case (access_size)
|
spc_stall_o <= 0;
|
endfunction
|
spc_resume_o <= 0;
|
|
|
|
// Clear Wishbone Master interface outputs
|
// synopsys translate_off
|
wbm_cycle_o <= 0;
|
`ifdef SIMPLY_RISC_DEBUG
|
wbm_strobe_o <= 0;
|
|
wbm_we_o <= 0;
|
|
wbm_addr_o <= 64'b0;
|
|
wbm_data_o <= 64'b0;
|
|
wbm_sel_o <= 8'b0;
|
|
|
|
// Prepare wakeup packet for SPARC Core, the resulting output is
|
|
// spc_packetin_o <= `CPX_WIDTH'h1700000000000000000000000000000010001;
|
|
wbm2spc_valid <= 1;
|
|
wbm2spc_type <= `INT_RET;
|
|
wbm2spc_miss <= 0;
|
|
wbm2spc_error <= 0;
|
|
wbm2spc_nc <= 0;
|
|
wbm2spc_thread <= 0;
|
|
wbm2spc_way_valid <= 0;
|
|
wbm2spc_way <= 0;
|
|
wbm2spc_boot_fetch <= 0;
|
|
wbm2spc_atomic <= 0;
|
|
wbm2spc_pfl <= 0;
|
|
wbm2spc_data <= 64'h10001;
|
|
wbm2spc_interrupt_source <= 7'h0;
|
|
wbm2spc_interrupt_new <= 1'b0;
|
|
|
|
// Clear state machine
|
|
state <= `STATE_WAKEUP;
|
|
|
|
end else begin
|
|
|
|
// FSM State 0: STATE_WAKEUP
|
task automatic print_pcx_packet(pcx_info_t _pcx_info, pcx_packet_t _pcx_packet);
|
// Send to the SPARC Core the wakeup packet
|
string str_region, str_type, str_size;
|
if(state==`STATE_WAKEUP) begin
|
case(_pcx_info.region)
|
|
5'b00001: str_region = "RAM_Bank_0";
|
|
5'b00010: str_region = "RAM_Bank_1";
|
|
5'b00100: str_region = "RAM_Bank_2";
|
|
5'b01000: str_region = "RAM Bank_3";
|
|
5'b10000: str_region = "IO_Block";
|
|
default: str_region = "Unknown";
|
|
endcase
|
|
case(_pcx_packet.request_type)
|
|
`LOAD_RQ: str_type = "LOAD_RQ";
|
|
`IMISS_RQ: str_type = "IMISS_RQ";
|
|
`STORE_RQ: str_type = "STORE_RQ";
|
|
`CAS1_RQ: str_type = "CAS1_RQ";
|
|
`CAS2_RQ: str_type = "CAS2_RQ";
|
|
`SWAP_RQ: str_type = "SWAP_RQ";
|
|
`STRLOAD_RQ: str_type = "STRLOAD_RQ";
|
|
`STRST_RQ: str_type = "STRST_RQ";
|
|
`STQ_RQ: str_type = "STQ_RQ";
|
|
`INT_RQ: str_type = "INT_RQ";
|
|
`FWD_RQ: str_type = "FWD_RQ";
|
|
`FWD_RPY: str_type = "FWD_RPY";
|
|
`RSVD_RQ: str_type = "RSVD_RQ";
|
|
default: str_type = "Unknown";
|
|
endcase
|
|
case(_pcx_packet.access_size)
|
|
`PCX_SZ_1B: str_size = "1B";
|
|
`PCX_SZ_2B: str_size = "2B";
|
|
`PCX_SZ_4B: str_size = "4B";
|
|
`PCX_SZ_8B: str_size = "8B";
|
|
`PCX_SZ_16B: str_size = "16B";
|
|
default: str_size = "Unknown";
|
|
endcase
|
|
$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);
|
|
endtask
|
|
|
// Send wakeup packet
|
task automatic print_cpx_packet(cpx_packet_t _cpx_packet);
|
spc_ready_o <= 1;
|
string str_type;
|
spc_packetin_o <= wbm2spc_packet;
|
case(_cpx_packet.return_type)
|
|
`IFILL_RET: str_type = "IFILL_RET";
|
|
`LOAD_RET: str_type = "LOAD_RET";
|
|
`ST_ACK: str_type = "ST_ACK";
|
|
default: str_type = "Unknown";
|
|
endcase
|
|
$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);
|
|
endtask
|
|
|
// synopsys translate_off
|
|
// Display comment
|
|
`ifdef DEBUG
|
|
$display("INFO: SPC2WBM: SPARC Core to Wishbone Master bridge starting...");
|
|
$display("INFO: SPC2WBM: Wakeup packet sent to SPARC Core");
|
|
`endif
|
`endif
|
// synopsys translate_on
|
// synopsys translate_on
|
|
|
// Unconditional state change
|
/*
|
state <= `STATE_IDLE;
|
* Signal declarations
|
|
*/
|
// FSM State 1: STATE_IDLE
|
|
// Wait for a request from the SPARC Core
|
|
// If available send an interrupt packet to the Core
|
|
end else if(state==`STATE_IDLE) begin
|
|
|
|
// Check if there's an incoming request
|
|
if(spc2wbm_req==1) begin
|
|
|
|
// Clear previously modified outputs
|
|
spc_ready_o <= 0;
|
|
spc_packetin_o <= 0;
|
|
|
|
// Stall other requests from the SPARC Core
|
// Delayed signals
|
spc_stall_o <= 1;
|
logic [`SPC_REGION_WIDTH-1:0] spc_req_dly1;
|
|
logic [`SPC_REGION_WIDTH-1:0] spc_req_dly2;
|
|
logic spc_atom_dly1;
|
|
logic spc_atom_dly2;
|
|
|
|
// PCX FIFO
|
|
logic [`PCX_WIDTH+`SPC_INFO_WIDTH-1:0] pcx_fifo_data_in;
|
|
logic [`PCX_WIDTH+`SPC_INFO_WIDTH-1:0] pcx_fifo_data_out;
|
|
logic pcx_fifo_read;
|
|
logic pcx_fifo_write;
|
|
logic pcx_fifo_empty;
|
|
logic pcx_fifo_full;
|
|
|
|
// CPX FIFO
|
|
logic [`CPX_WIDTH-1:0] cpx_fifo_data_in;
|
|
logic [`CPX_WIDTH-1:0] cpx_fifo_data_out;
|
|
logic cpx_fifo_read;
|
|
logic cpx_fifo_write;
|
|
logic cpx_fifo_empty;
|
|
logic cpx_fifo_full;
|
|
|
// Latch target region and atomicity
|
/*
|
spc2wbm_region <= spc_req_i;
|
* Tasks
|
spc2wbm_atomic <= spc_atom_i;
|
*/
|
|
|
// Jump to next state
|
// wbm_clean
|
state <= `STATE_REQUEST_LATCHED;
|
task wbm_clean();
|
|
wbm_cycle_o = 1'b0;
|
|
wbm_strobe_o = 1'b0;
|
|
wbm_we_o = 1'b0;
|
|
wbm_addr_o = 'h0;
|
|
wbm_data_o = 'h0;
|
|
wbm_sel_o = 'h0;
|
|
endtask // wbm_clean
|
|
|
// See if the interrupt vector has changed
|
/*
|
end else if(sys_interrupt_source_i!=wbm2spc_interrupt_source) begin
|
* FIFO instances
|
|
*/
|
|
|
// Set the flag for next cycle
|
simple_fifo #(
|
wbm2spc_interrupt_new <= 1;
|
.name("pcx_fifo"),
|
|
.fifo_depth(4),
|
|
.data_width(`PCX_WIDTH+`SPC_INFO_WIDTH)
|
|
) pcx_fifo (
|
|
// System inputs
|
|
.sys_clock_i(sys_clock_i),
|
|
.sys_reset_i(sys_reset_i),
|
|
|
// Prepare the interrupt packet for the SPARC Core
|
// FIFO inputs
|
wbm2spc_valid <= 1;
|
.read(pcx_fifo_read),
|
wbm2spc_type <= `INT_RET;
|
.write(pcx_fifo_write),
|
wbm2spc_miss <= 0;
|
.data_in(pcx_fifo_data_in),
|
wbm2spc_error <= 0;
|
|
wbm2spc_nc <= 0;
|
// FIFO outputs
|
wbm2spc_thread <= 0;
|
.empty(pcx_fifo_empty),
|
wbm2spc_way_valid <= 0;
|
.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
|
wbm2spc_way <= 0;
|
.data_out(pcx_fifo_data_out)
|
wbm2spc_boot_fetch <= 0;
|
);
|
wbm2spc_atomic <= 0;
|
|
wbm2spc_pfl <= 0;
|
|
|
|
// Next cycle see if there's an int to be forwarded to the Core
|
simple_fifo #(
|
end else if(wbm2spc_interrupt_source!=6'b000000 && wbm2spc_interrupt_new) begin
|
.name("cpx_fifo"),
|
|
.fifo_depth(4),
|
|
.data_width(`CPX_WIDTH)
|
|
) cpx_fifo (
|
|
// System inputs
|
|
.sys_clock_i(sys_clock_i),
|
|
.sys_reset_i(sys_reset_i),
|
|
|
// Clean the flag
|
// FIFO inputs
|
wbm2spc_interrupt_new <= 0;
|
.read(cpx_fifo_read),
|
|
.write(cpx_fifo_write),
|
|
.data_in(cpx_fifo_data_in),
|
|
|
|
// FIFO outputs
|
|
.empty(cpx_fifo_empty),
|
|
.full(cpx_fifo_full),
|
|
.data_out(cpx_fifo_data_out)
|
|
);
|
|
|
// Send the interrupt packet to the Core
|
/*
|
spc_ready_o <= 1;
|
* PCX sampling logic:
|
spc_packetin_o <= wbm2spc_packet;
|
* - SPC Logic: Drives SPARC Cores signals related with the PCX interface
|
|
* - PCX FIFO Write Logic: Drives pcx_fifo_write and pcx_fifo_data_in
|
|
*/
|
|
|
// Stay in this state
|
always @(posedge sys_clock_i) begin
|
state <= `STATE_IDLE;
|
|
|
|
// Nothing to do, stay idle
|
// Create delayed version of request and atom
|
|
if (sys_reset_i == 1) begin
|
|
spc_req_dly1 <= 'h0;
|
|
spc_req_dly2 <= 'h0;
|
|
spc_atom_dly1 <= 1'b0;
|
|
spc_atom_dly2 <= 1'b0;
|
end else begin
|
end else begin
|
|
spc_req_dly1 <= spc_req_i;
|
// Clear previously modified outputs
|
spc_req_dly2 <= spc_req_dly1;
|
spc_ready_o <= 0;
|
spc_atom_dly1 <= spc_atom_i;
|
spc_packetin_o <= 0;
|
spc_atom_dly2 <= spc_atom_dly1;
|
|
|
// Clear stall/resume signals
|
|
spc_stall_o <= 0;
|
|
spc_resume_o <= 0;
|
|
|
|
// Stay in this state
|
|
state <= `STATE_IDLE;
|
|
|
|
end
|
end
|
|
|
// FSM State 2: STATE_REQUEST_LATCHED
|
// One cycle delay required to sample into the PCX FIFO
|
// We've just latched the request
|
if (sys_reset_i == 1'b1 || |spc_req_dly1 == 1'b0) begin
|
// Now we latch the packet
|
pcx_fifo_write <= 1'b0;
|
// Start granting the request
|
pcx_fifo_data_in <= 'h0;
|
end else if(state==`STATE_REQUEST_LATCHED) begin
|
end else if (|spc_req_dly1 == 1'b1) begin
|
|
pcx_fifo_write <= 1'b1;
|
// Latch the incoming packet
|
pcx_fifo_data_in <= {spc_req_dly1, spc_atom_dly1, spc_packetout_i};
|
spc2wbm_packet <= spc_packetout_i;
|
|
|
|
// Grant the request to the SPARC Core
|
|
spc_grant_o <= spc2wbm_region;
|
|
|
|
// Clear the stall signal
|
|
spc_stall_o <= 0;
|
|
|
|
// synopsys translate_off
|
// synopsys translate_off
|
|
`ifdef SIMPLY_RISC_DEBUG
|
// Print details of SPARC Core request
|
// Print details of SPARC Core request
|
`ifdef DEBUG
|
print_pcx_packet({spc_req_dly1, spc_atom_dly1}, spc_packetout_i);
|
$display("INFO: SPC2WBM: *** NEW REQUEST FROM SPARC CORE ***");
|
|
if(spc2wbm_region[0]==1) $display("INFO: SPC2WBM: Request to RAM Bank 0");
|
|
else if(spc2wbm_region[1]==1) $display("INFO: SPC2WBM: Request to RAM Bank 1");
|
|
else if(spc2wbm_region[2]==1) $display("INFO: SPC2WBM: Request to RAM Bank 2");
|
|
else if(spc2wbm_region[3]==1) $display("INFO: SPC2WBM: Request to RAM Bank 3");
|
|
else if(spc2wbm_region[4]==1) $display("INFO: SPC2WBM: Request targeted to I/O Block");
|
|
else $display("INFO: SPC2WBM: Request to target region unknown");
|
|
if(spc2wbm_atomic==1) $display("INFO: SPC2WBM: Request is ATOMIC");
|
|
else $display("INFO: SPC2WBM: Request is not atomic");
|
|
`endif
|
`endif
|
// synopsys translate_on
|
// synopsys translate_on
|
|
end
|
|
|
// Unconditional state change
|
end // always @ (posedge sys_clock_i)
|
state <= `STATE_PACKET_LATCHED;
|
|
|
|
// FSM State 3: STATE_PACKET_LATCHED
|
// Two cycles delay required to return the grant
|
// The packet has already been latched
|
assign spc_grant_o = spc_req_dly2;
|
// Decode this packet to build the request for the Wishbone bus
|
|
// The grant of the request to the SPARC Core has been completed
|
|
end else if(state==`STATE_PACKET_LATCHED) begin
|
|
|
|
// Clear previously modified outputs
|
/*
|
spc_grant_o <= 5'b0;
|
* PCX-to-WBM-to-CPX:
|
|
* - PCX FIFO Read Logic: Drives pcx_fifo_read and reads pcx_fifo_data_out
|
|
* - WBM Logic: Drives all Wishbone signals
|
|
* - CPX FIFO Write Logic: Drives cpx_fifo_write and cpx_data_in
|
|
*/
|
|
|
|
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;
|
|
fsm_state_t fsm_state;
|
|
pcx_info_t pcx_info;
|
|
pcx_packet_t pcx_packet;
|
|
cpx_packet_t cpx_packet;
|
|
|
// Issue a request on the Wishbone bus
|
always @(posedge sys_clock_i) begin
|
|
if (sys_reset_i == 1) begin
|
|
// Clear outputs connected to FIFOs
|
|
pcx_fifo_read <= 1'b0;
|
|
cpx_fifo_write <= 1'b0;
|
|
cpx_fifo_data_in <= 'h0;
|
|
// Clear Wishbone outputs
|
|
wbm_clean();
|
|
// Initialize the first FSM state
|
|
fsm_state <= FSM_WAKEUP;
|
|
// Prepare the wakeup packet for SPARC Core: `CPX_WIDTH'h1700000000000000000000000000000010001;
|
|
cpx_packet.valid <= 1;
|
|
cpx_packet.return_type <= `INT_RET;
|
|
cpx_packet.error <= 0;
|
|
cpx_packet.noncache_rnw <= 0;
|
|
cpx_packet.thread_id <= 0;
|
|
cpx_packet.intsrc_etc <= 7'h0;
|
|
cpx_packet.load_data <= 128'h10001;
|
|
end else begin
|
|
case(fsm_state)
|
|
// Send the wakeup packet to the SPARC Core
|
|
FSM_WAKEUP: begin
|
|
cpx_fifo_write <= 1'b1;
|
|
cpx_fifo_data_in <= cpx_packet;
|
|
fsm_state <= FSM_IDLE;
|
|
end
|
|
// Wait for a new request to be available in the PCX FIFO and read it
|
|
FSM_IDLE: begin
|
|
cpx_fifo_write <= 1'b0;
|
|
cpx_fifo_data_in <= 'h0;
|
|
if (pcx_fifo_empty != 1'b1) begin
|
|
pcx_fifo_read <= 1'b1;
|
|
{ pcx_info, pcx_packet } <= pcx_fifo_data_out;
|
|
fsm_state <= FSM_WBM_BEGIN1;
|
|
end
|
|
end
|
|
// Start a request on the Wishbone bus
|
|
FSM_WBM_BEGIN1: begin
|
|
if (pcx_info.region == 5'b10000)
|
|
pcx_packet.address[3] = 0; // Smells fishy, I may just load half (64b / 8B / 2instr)
|
|
pcx_fifo_read <= 1'b0;
|
wbm_cycle_o <= 1;
|
wbm_cycle_o <= 1;
|
wbm_strobe_o <= 1;
|
wbm_strobe_o <= 1;
|
wbm_addr_o <= { spc2wbm_region, 19'b0, spc2wbm_addr[`PCX_AD_HI-`PCX_AD_LO:3], 3'b000 };
|
wbm_addr_o <= { pcx_info.region, 19'b0, pcx_packet.address[`PCX_AD_HI-`PCX_AD_LO:3], 3'b000 };
|
wbm_data_o <= spc2wbm_data;
|
wbm_data_o <= pcx_packet.store_data;
|
|
case(pcx_packet.request_type)
|
// Handle write enable and byte select
|
`IMISS_RQ: begin
|
if(spc2wbm_type==`IMISS_RQ) begin
|
|
|
|
// For instruction miss always read memory
|
// For instruction miss always read memory
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
if(spc2wbm_region==5'b10000)
|
|
// For accesses to SSI ROM only 32 bits are required
|
|
wbm_sel_o <= (4'b1111<<(spc2wbm_addr[2]<<2));
|
|
else
|
|
// For accesses to RAM 256 bits are expected (2 ret packets)
|
|
wbm_sel_o <= 8'b11111111;
|
wbm_sel_o <= 8'b11111111;
|
|
end // case: `IMISS_RQ
|
end else if(spc2wbm_type==`LOAD_RQ) begin
|
`LOAD_RQ: begin
|
|
|
// For data load use the provided data
|
// For data load use the provided data
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
case(spc2wbm_size)
|
wbm_sel_o <= pcxsize2wbmsel(pcx_packet.access_size, pcx_packet.address);
|
`PCX_SZ_1B: wbm_sel_o <= (1'b1<<spc2wbm_addr[2:0]);
|
end // case: `LOAD_RQ
|
`PCX_SZ_2B: wbm_sel_o <= (2'b11<<(spc2wbm_addr[2:1]<<1));
|
`STORE_RQ: begin
|
`PCX_SZ_4B: wbm_sel_o <= (4'b1111<<(spc2wbm_addr[2]<<2));
|
|
`PCX_SZ_8B: wbm_sel_o <= 8'b11111111;
|
|
`PCX_SZ_16B: wbm_sel_o <= 8'b11111111; // Requires a 2nd access
|
|
default: wbm_sel_o <= 8'b00000000;
|
|
endcase
|
|
|
|
end else if(spc2wbm_type==`STORE_RQ) begin
|
|
|
|
// For data store use the provided data
|
// For data store use the provided data
|
wbm_we_o <= 1;
|
wbm_we_o <= 1;
|
case(spc2wbm_size)
|
wbm_sel_o <= pcxsize2wbmsel(pcx_packet.access_size, pcx_packet.address);
|
`PCX_SZ_1B: wbm_sel_o <= (1'b1<<spc2wbm_addr[2:0]);
|
end // case: `STORE_RQ
|
`PCX_SZ_2B: wbm_sel_o <= (2'b11<<(spc2wbm_addr[2:1]<<1));
|
default: begin
|
`PCX_SZ_4B: wbm_sel_o <= (4'b1111<<(spc2wbm_addr[2]<<2));
|
$fatal(1, "Entered default condition of PCX FSM as request_type=0x%02X", pcx_packet.request_type);
|
`PCX_SZ_8B: wbm_sel_o <= 8'b11111111;
|
|
`PCX_SZ_16B: wbm_sel_o <= 8'b11111111; // Requires a 2nd access
|
|
default: wbm_sel_o <= 8'b00000000;
|
|
endcase
|
|
|
|
end else begin
|
|
|
|
wbm_we_o <= 1;
|
wbm_we_o <= 1;
|
wbm_sel_o <= 8'b00000000;
|
wbm_sel_o <= 8'b00000000;
|
|
|
end
|
end
|
|
|
// synopsys translate_off
|
|
// Print details of request packet
|
|
`ifdef DEBUG
|
|
$display("INFO: SPC2WBM: Valid bit is %X", spc2wbm_valid);
|
|
case(spc2wbm_type)
|
|
`LOAD_RQ: $display("INFO: SPC2WBM: Request of Type LOAD_RQ");
|
|
`IMISS_RQ: $display("INFO: SPC2WBM: Request of Type IMISS_RQ");
|
|
`STORE_RQ: $display("INFO: SPC2WBM: Request of Type STORE_RQ");
|
|
`CAS1_RQ: $display("INFO: SPC2WBM: Request of Type CAS1_RQ");
|
|
`CAS2_RQ: $display("INFO: SPC2WBM: Request of Type CAS2_RQ");
|
|
`SWAP_RQ: $display("INFO: SPC2WBM: Request of Type SWAP_RQ");
|
|
`STRLOAD_RQ: $display("INFO: SPC2WBM: Request of Type STRLOAD_RQ");
|
|
`STRST_RQ: $display("INFO: SPC2WBM: Request of Type STRST_RQ");
|
|
`STQ_RQ: $display("INFO: SPC2WBM: Request of Type STQ_RQ");
|
|
`INT_RQ: $display("INFO: SPC2WBM: Request of Type INT_RQ");
|
|
`FWD_RQ: $display("INFO: SPC2WBM: Request of Type FWD_RQ");
|
|
`FWD_RPY: $display("INFO: SPC2WBM: Request of Type FWD_RPY");
|
|
`RSVD_RQ: $display("INFO: SPC2WBM: Request of Type RSVD_RQ");
|
|
default: $display("INFO: SPC2WBM: Request of Type Unknown");
|
|
endcase
|
endcase
|
$display("INFO: SPC2WBM: Non-Cacheable bit is %X", spc2wbm_nc);
|
fsm_state <= FSM_WBM_END1;
|
$display("INFO: SPC2WBM: CPU-ID is %X", spc2wbm_cpu_id);
|
end // case: FSM_WBM_BEGIN1
|
$display("INFO: SPC2WBM: Thread is %X", spc2wbm_thread);
|
// Wait for the ack from the Wishbone bus and latch the incoming data
|
$display("INFO: SPC2WBM: Invalidate All is %X", spc2wbm_invalidate);
|
FSM_WBM_END1: begin
|
$display("INFO: SPC2WBM: Replaced L1 Way is %X", spc2wbm_way);
|
|
case(spc2wbm_size)
|
|
`PCX_SZ_1B: $display("INFO: SPC2WBM: Request size is 1 Byte");
|
|
`PCX_SZ_2B: $display("INFO: SPC2WBM: Request size is 2 Bytes");
|
|
`PCX_SZ_4B: $display("INFO: SPC2WBM: Request size is 4 Bytes");
|
|
`PCX_SZ_8B: $display("INFO: SPC2WBM: Request size is 8 Bytes");
|
|
`PCX_SZ_16B: $display("INFO: SPC2WBM: Request size is 16 Bytes");
|
|
default: $display("INFO: SPC2WBM: Request size is Unknown");
|
|
endcase
|
|
$display("INFO: SPC2WBM: Address is %X", spc2wbm_addr);
|
|
$display("INFO: SPC2WBM: Data is %X", spc2wbm_data);
|
|
`endif
|
|
// synopsys translate_on
|
|
|
|
// Unconditional state change
|
|
state <= `STATE_REQUEST_GRANTED;
|
|
|
|
// FSM State 4: STATE_REQUEST_GRANTED
|
|
// Wishbone access completed, latch the incoming data
|
|
end else if(state==`STATE_REQUEST_GRANTED) begin
|
|
|
|
// Wait until Wishbone access completes
|
|
if(wbm_ack_i==1) begin
|
if(wbm_ack_i==1) begin
|
|
if (pcx_info.atomic == 0) wbm_cycle_o <= 0;
|
// Clear previously modified outputs
|
|
if(spc2wbm_atomic==0) wbm_cycle_o <= 0;
|
|
wbm_strobe_o <= 0;
|
wbm_strobe_o <= 0;
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
wbm_addr_o <= 64'b0;
|
wbm_addr_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_sel_o <= 8'b0;
|
wbm_sel_o <= 8'b0;
|
|
|
// Latch the data and set up the return packet for the SPARC Core
|
// Encode the CPX return packet and store it in the second FIFO
|
wbm2spc_valid <= 1;
|
cpx_packet.valid = 1;
|
case(spc2wbm_type)
|
case(pcx_packet.request_type)
|
`IMISS_RQ: begin
|
`IMISS_RQ: begin
|
wbm2spc_type <= `IFILL_RET; // I-Cache Miss
|
cpx_packet.return_type = `IFILL_RET; // I-Cache Miss
|
wbm2spc_atomic <= 0;
|
|
end
|
end
|
`LOAD_RQ: begin
|
`LOAD_RQ: begin
|
wbm2spc_type <= `LOAD_RET; // Load
|
cpx_packet.return_type = `LOAD_RET; // Load
|
wbm2spc_atomic <= spc2wbm_atomic;
|
|
end
|
end
|
`STORE_RQ: begin
|
`STORE_RQ: begin
|
wbm2spc_type <= `ST_ACK; // Store
|
cpx_packet.return_type = `ST_ACK; // Store
|
wbm2spc_atomic <= spc2wbm_atomic;
|
|
end
|
end
|
endcase
|
endcase
|
wbm2spc_miss <= 0;
|
cpx_packet.error = 0;
|
wbm2spc_error <= 0;
|
cpx_packet.noncache_rnw = pcx_packet.noncache_rnw;
|
wbm2spc_nc <= spc2wbm_nc;
|
cpx_packet.thread_id = pcx_packet.thread_id;
|
wbm2spc_thread <= spc2wbm_thread;
|
cpx_packet.intsrc_etc = 6'b000100;
|
wbm2spc_way_valid <= 0;
|
if (pcx_packet.address[3] == 0)
|
wbm2spc_way <= 0;
|
cpx_packet.load_data = { wbm_data_i, 64'b0 };
|
if(spc2wbm_region==5'b10000) wbm2spc_boot_fetch <= 1;
|
else
|
else wbm2spc_boot_fetch <= 0;
|
cpx_packet.load_data = { 64'b0, wbm_data_i };
|
wbm2spc_pfl <= 0;
|
|
if(spc2wbm_addr[3]==0) wbm2spc_data <= { wbm_data_i, 64'b0 };
|
|
else wbm2spc_data <= { 64'b0, wbm_data_i };
|
|
|
|
// See if other 64-bit Wishbone accesses are required
|
// See if other 64-bit Wishbone accesses are required
|
if(
|
if ( (pcx_packet.request_type == `IMISS_RQ) ||
|
// Instruction miss directed to RAM expects 256 bits
|
// Instruction miss directed to RAM expects 256 bits
|
( (spc2wbm_type==`IMISS_RQ)&&(spc2wbm_region!=5'b10000) ) ||
|
( (pcx_packet.request_type == `LOAD_RQ) && (pcx_packet.access_size == `PCX_SZ_16B) )
|
// Data access of 128 bits
|
// Data access of 128 bits
|
( (spc2wbm_type==`LOAD_RQ)&&(spc2wbm_size==`PCX_SZ_16B) )
|
) begin
|
)
|
fsm_state <= FSM_WBM_BEGIN2;
|
state <= `STATE_ACCESS2_BEGIN;
|
end else begin
|
else
|
fsm_state <= FSM_CPX_FIFO_WRITE;
|
state <= `STATE_PACKET_READY;
|
end
|
|
|
end else state <= `STATE_REQUEST_GRANTED;
|
|
|
|
// FSM State 5: STATE_ACCESS2_BEGIN
|
end
|
|
end // case: FSM_WBM_END1
|
// If needed start a second read access to the Wishbone bus
|
// If needed start a second read access to the Wishbone bus
|
end else if(state==`STATE_ACCESS2_BEGIN) begin
|
FSM_WBM_BEGIN2: begin
|
|
|
// Issue a second request on the Wishbone bus
|
// Issue a second request on the Wishbone bus
|
wbm_cycle_o <= 1;
|
wbm_cycle_o <= 1;
|
wbm_strobe_o <= 1;
|
wbm_strobe_o <= 1;
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
wbm_addr_o <= { spc2wbm_region, 19'b0, spc2wbm_addr[`PCX_AD_HI-`PCX_AD_LO:4], 4'b1000 }; // 2nd doubleword inside the same quadword
|
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
|
wbm_data_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_sel_o <= 8'b11111111;
|
wbm_sel_o <= 8'b11111111;
|
|
|
// Unconditional state change
|
// Unconditional state change
|
state <= `STATE_ACCESS2_END;
|
fsm_state <= FSM_WBM_END2;
|
|
|
|
end // case: FSM_WBM_BEGIN2
|
|
|
// FSM State 6: STATE_ACCESS2_END
|
|
// Latch the second data returning from Wishbone when ready
|
// Latch the second data returning from Wishbone when ready
|
end else if(state==`STATE_ACCESS2_END) begin
|
FSM_WBM_END2: begin
|
|
|
// Wait until Wishbone access completes
|
// Wait until Wishbone access completes
|
if(wbm_ack_i==1) begin
|
if(wbm_ack_i==1) begin
|
|
|
// Clear previously modified outputs
|
// Clear previously modified outputs
|
if(spc2wbm_atomic==0) wbm_cycle_o <= 0;
|
if (pcx_info.atomic == 0) wbm_cycle_o <= 0;
|
wbm_strobe_o <= 0;
|
wbm_strobe_o <= 0;
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
wbm_addr_o <= 64'b0;
|
wbm_addr_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_sel_o <= 8'b0;
|
wbm_sel_o <= 8'b0;
|
|
|
// Latch the data and set up the return packet for the SPARC Core
|
// Latch the data and set up the return packet for the SPARC Core (this is the second half)
|
wbm2spc_data[63:0] <= wbm_data_i;
|
if (pcx_packet.address[3] == 1)
|
|
cpx_packet.load_data = { wbm_data_i, cpx_packet.load_data[63:0] };
|
// See if two return packets are required or just one
|
|
if(spc2wbm_type==`IMISS_RQ && spc2wbm_region==5'b10000)
|
|
state <= `STATE_PACKET_READY;
|
|
else
|
else
|
state <= `STATE_ACCESS3_BEGIN;
|
cpx_packet.load_data = { cpx_packet.load_data[127:64], wbm_data_i };
|
|
|
|
// synopsys translate_off
|
|
`ifdef SIMPLY_RISC_DEBUG
|
|
// Print details of return packet
|
|
print_cpx_packet(cpx_packet);
|
|
`endif
|
|
// synopsys translate_on
|
|
|
|
// See if two return packets are required or just one - TODO checkme
|
|
// if (pcx_packet.request_type == `IMISS_RQ && pcx_info.region == 5'b10000)
|
|
fsm_state <= FSM_CPX_FIFO_WRITE;
|
|
// else
|
|
// fsm_state <= FSM_WBM_BEGIN3;
|
|
|
end else state <= `STATE_ACCESS2_END;
|
end // else fsm_state <= FSM_WBM_END2;
|
|
end // case: FSM_WBM_END2
|
|
|
// FSM State 7: STATE_ACCESS3_BEGIN
|
|
// If needed start a third read access to the Wishbone bus
|
// If needed start a third read access to the Wishbone bus
|
// In the meanwhile we can return the first 128-bit packet
|
// In the meanwhile we can return the first 128-bit packet
|
end else if(state==`STATE_ACCESS3_BEGIN) begin
|
FSM_WBM_BEGIN3: begin
|
|
|
// Return the packet to the SPARC Core
|
|
spc_ready_o <= 1;
|
|
spc_packetin_o <= wbm2spc_packet;
|
|
|
|
// Issue a third request on the Wishbone bus
|
// Issue a third request on the Wishbone bus
|
wbm_cycle_o <= 1;
|
wbm_cycle_o <= 1;
|
wbm_strobe_o <= 1;
|
wbm_strobe_o <= 1;
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
wbm_addr_o <= { spc2wbm_region, 19'b0, spc2wbm_addr[`PCX_AD_HI-`PCX_AD_LO:5], 5'b10000 }; // 3nd doubleword inside the same 256-bit data
|
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
|
wbm_data_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_sel_o <= 8'b11111111;
|
wbm_sel_o <= 8'b11111111;
|
|
|
// synopsys translate_off
|
|
// Print details of return packet
|
|
`ifdef DEBUG
|
|
$display("INFO: WBM2SPC: *** RETURN PACKET TO SPARC CORE ***");
|
|
$display("INFO: WBM2SPC: Valid bit is %X", wbm2spc_valid);
|
|
case(wbm2spc_type)
|
|
`IFILL_RET: $display("INFO: WBM2SPC: Return Packet of Type IFILL_RET");
|
|
`LOAD_RET: $display("INFO: WBM2SPC: Return Packet of Type LOAD_RET");
|
|
`ST_ACK: $display("INFO: WBM2SPC: Return Packet of Type ST_ACK");
|
|
default: $display("INFO: WBM2SPC: Return Packet of Type Unknown");
|
|
endcase
|
|
$display("INFO: WBM2SPC: L2 Miss is %X", wbm2spc_miss);
|
|
$display("INFO: WBM2SPC: Error is %X", wbm2spc_error);
|
|
$display("INFO: WBM2SPC: Non-Cacheable bit is %X", wbm2spc_nc);
|
|
$display("INFO: WBM2SPC: Thread is %X", wbm2spc_thread);
|
|
$display("INFO: WBM2SPC: Way Valid is %X", wbm2spc_way_valid);
|
|
$display("INFO: WBM2SPC: Replaced L2 Way is %X", wbm2spc_way);
|
|
$display("INFO: WBM2SPC: Fetch for Boot is %X", wbm2spc_boot_fetch);
|
|
$display("INFO: WBM2SPC: Atomic LD/ST or 2nd IFill Packet is %X", wbm2spc_atomic);
|
|
$display("INFO: WBM2SPC: PFL is %X", wbm2spc_pfl);
|
|
$display("INFO: WBM2SPC: Data is %X", wbm2spc_data);
|
|
`endif
|
|
// synopsys translate_on
|
|
|
|
// Unconditional state change
|
// Unconditional state change
|
state <= `STATE_ACCESS3_END;
|
fsm_state <= FSM_WBM_END3;
|
|
|
// FSM State 8: STATE_ACCESS3_END
|
end // case: FSM_WBM_BEGIN3
|
// Latch the second data returning from Wishbone when ready
|
|
end else if(state==`STATE_ACCESS3_END) begin
|
|
|
|
// Clear previously modified outputs
|
// Latch the second data returning from Wishbone when ready
|
spc_ready_o <= 0;
|
FSM_WBM_END3: begin
|
|
|
// Wait until Wishbone access completes
|
// Wait until Wishbone access completes
|
if(wbm_ack_i==1) begin
|
if(wbm_ack_i==1) begin
|
|
|
// Clear previously modified outputs
|
// Clear previously modified outputs
|
if(spc2wbm_atomic==0) wbm_cycle_o <= 0;
|
if (pcx_info.atomic == 0) wbm_cycle_o <= 0;
|
wbm_strobe_o <= 0;
|
wbm_strobe_o <= 0;
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
wbm_addr_o <= 64'b0;
|
wbm_addr_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_sel_o <= 8'b0;
|
wbm_sel_o <= 8'b0;
|
|
|
// Latch the data and set up the return packet for the SPARC Core
|
// Latch the data and set up the return packet for the SPARC Core - TODO CHECKME
|
wbm2spc_data <= { wbm_data_i, 64'b0 };
|
// cpx_packet.load_data = { wbm_data_i, 64'b0 };
|
|
|
// Jump to next state
|
// Jump to next state
|
state <= `STATE_ACCESS4_BEGIN;
|
fsm_state <= FSM_WBM_BEGIN4;
|
|
|
end else state <= `STATE_ACCESS3_END;
|
end // else fsm_state <= FSM_WBM_END3; // if (wbm_ack_i == 1)
|
|
end // case: FSM_WBM_END3
|
|
|
// FSM State 9: STATE_ACCESS4_BEGIN
|
|
// If needed start a second read access to the Wishbone bus
|
// If needed start a second read access to the Wishbone bus
|
end else if(state==`STATE_ACCESS4_BEGIN) begin
|
FSM_WBM_BEGIN4: begin
|
|
|
// Issue a fourth request on the Wishbone bus
|
// Issue a fourth request on the Wishbone bus
|
wbm_cycle_o <= 1;
|
wbm_cycle_o <= 1;
|
wbm_strobe_o <= 1;
|
wbm_strobe_o <= 1;
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
wbm_addr_o <= { spc2wbm_region, 19'b0, spc2wbm_addr[`PCX_AD_HI-`PCX_AD_LO:5], 5'b11000 }; // 4th doubleword inside the same 256-bit data
|
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
|
wbm_data_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_sel_o <= 8'b11111111;
|
wbm_sel_o <= 8'b11111111;
|
|
|
// Unconditional state change
|
// Unconditional state change
|
state <= `STATE_ACCESS4_END;
|
fsm_state <= FSM_WBM_END4;
|
|
end // case: FSM_WBM_BEGIN4
|
|
|
// FSM State 10: STATE_ACCESS4_END
|
|
// Latch the second data returning from Wishbone when ready
|
// Latch the second data returning from Wishbone when ready
|
end else if(state==`STATE_ACCESS4_END) begin
|
FSM_WBM_END4: begin
|
|
|
// Wait until Wishbone access completes
|
// Wait until Wishbone access completes
|
if(wbm_ack_i==1) begin
|
if(wbm_ack_i==1) begin
|
|
|
// Clear previously modified outputs
|
// Clear previously modified outputs
|
if(spc2wbm_atomic==0) wbm_cycle_o <= 0;
|
if (pcx_info.atomic == 0) wbm_cycle_o <= 0;
|
wbm_strobe_o <= 0;
|
wbm_strobe_o <= 0;
|
wbm_we_o <= 0;
|
wbm_we_o <= 0;
|
wbm_addr_o <= 64'b0;
|
wbm_addr_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_data_o <= 64'b0;
|
wbm_sel_o <= 8'b0;
|
wbm_sel_o <= 8'b0;
|
|
|
// Latch the data and set up the return packet for the SPARC Core
|
// Latch the data and set up the return packet for the SPARC Core
|
wbm2spc_atomic <= 1;
|
// cpx_packet.load_data = { 64'h0, wbm_data_i};
|
wbm2spc_data[63:0] <= wbm_data_i;
|
|
|
|
// Jump to next state
|
// Jump to next state
|
state <= `STATE_PACKET_READY;
|
fsm_state <= FSM_CPX_FIFO_WRITE;
|
|
|
end else state <= `STATE_ACCESS4_END;
|
end // else fsm_state <= FSM_WBM_END4; // if (wbm_ack_i == 1)
|
|
end // case: FSM_WBM_END4
|
|
|
// FSM State 11: STATE_PACKET_READY
|
|
// We can start returning the packet to the SPARC Core
|
// We can start returning the packet to the SPARC Core
|
end else if(state==`STATE_PACKET_READY) begin
|
FSM_CPX_FIFO_WRITE: begin
|
|
|
// Return the packet to the SPARC Core
|
|
spc_ready_o <= 1;
|
|
spc_packetin_o <= wbm2spc_packet;
|
|
|
|
// Resume requests
|
// Write the packet to the CPX FIFO
|
spc_resume_o <= 1;
|
cpx_fifo_write <= 1'b1;
|
|
cpx_fifo_data_in <= cpx_packet;
|
|
|
// Unconditional state change
|
// Unconditional state change
|
state <= `STATE_IDLE;
|
fsm_state <= FSM_IDLE;
|
|
|
// synopsys translate_off
|
// synopsys translate_off
|
|
`ifdef SIMPLY_RISC_DEBUG
|
// Print details of return packet
|
// Print details of return packet
|
`ifdef DEBUG
|
print_cpx_packet(cpx_packet);
|
$display("INFO: WBM2SPC: *** RETURN PACKET TO SPARC CORE ***");
|
|
$display("INFO: WBM2SPC: Valid bit is %X", wbm2spc_valid);
|
|
case(wbm2spc_type)
|
|
`IFILL_RET: $display("INFO: WBM2SPC: Return Packet of Type IFILL_RET");
|
|
`LOAD_RET: $display("INFO: WBM2SPC: Return Packet of Type LOAD_RET");
|
|
`ST_ACK: $display("INFO: WBM2SPC: Return Packet of Type ST_ACK");
|
|
default: $display("INFO: WBM2SPC: Return Packet of Type Unknown");
|
|
endcase
|
|
$display("INFO: WBM2SPC: L2 Miss is %X", wbm2spc_miss);
|
|
$display("INFO: WBM2SPC: Error is %X", wbm2spc_error);
|
|
$display("INFO: WBM2SPC: Non-Cacheable bit is %X", wbm2spc_nc);
|
|
$display("INFO: WBM2SPC: Thread is %X", wbm2spc_thread);
|
|
$display("INFO: WBM2SPC: Way Valid is %X", wbm2spc_way_valid);
|
|
$display("INFO: WBM2SPC: Replaced L2 Way is %X", wbm2spc_way);
|
|
$display("INFO: WBM2SPC: Fetch for Boot is %X", wbm2spc_boot_fetch);
|
|
$display("INFO: WBM2SPC: Atomic LD/ST or 2nd IFill Packet is %X", wbm2spc_atomic);
|
|
$display("INFO: WBM2SPC: PFL is %X", wbm2spc_pfl);
|
|
$display("INFO: WBM2SPC: Data is %X", wbm2spc_data);
|
|
`endif
|
`endif
|
// synopsys translate_on
|
// synopsys translate_on
|
|
end // case: FSM_CPX_FIFO_WRITE
|
|
|
|
endcase // case (fsm_state)
|
end
|
end
|
end
|
end
|
|
|
|
/*
|
|
* CPX FIFO handler
|
|
* - SPARC Core Logic: Drives SPARC Core signals related with the CPX interface
|
|
* - CPX FIFO Read Logic: Drives cpx_fifo_read and reads cpx_data_out
|
|
*/
|
|
|
|
typedef enum logic[2:0] {CPX_IDLE, CPX_DRIVE_CORE} cpx_state_t;
|
|
cpx_state_t cpx_state;
|
|
cpx_packet_t cpx_packet_2;
|
|
|
|
always @(posedge sys_clock_i) begin
|
|
if (sys_reset_i == 1) begin
|
|
spc_ready_o <= 0;
|
|
spc_packetin_o <= 0;
|
|
cpx_fifo_read <= 1'b0;
|
|
cpx_state <= CPX_IDLE;
|
|
end else begin
|
|
case (cpx_state)
|
|
CPX_IDLE: begin
|
|
spc_ready_o <= 0;
|
|
spc_packetin_o <= 'h0;
|
|
if (cpx_fifo_empty) begin
|
|
cpx_fifo_read <= 1'b0;
|
|
end else begin
|
|
cpx_fifo_read <= 1'b1;
|
|
cpx_packet_2 <= cpx_fifo_data_out;
|
|
cpx_state <= CPX_DRIVE_CORE;
|
|
end
|
|
end
|
|
CPX_DRIVE_CORE: begin
|
|
cpx_fifo_read <= 1'b0;
|
|
spc_ready_o <= 1;
|
|
spc_packetin_o <= cpx_packet_2;
|
|
cpx_state <= CPX_IDLE;
|
end
|
end
|
|
endcase // case (cpx_state)
|
|
end // else: !if (sys_reset_i == 1)
|
|
end // always @ (posedge sys_clock_i)
|
|
|
endmodule
|
endmodule
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|