Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / niu_smx_resp_sio.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: niu_smx_resp_sio.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
//
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This 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.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
//
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
// ========== Copyright Header End ============================================
module niu_smx_resp_sio(
/*AUTOARG*/
// Outputs
resp_cmdff_wr, resp_cmdff_wdata, resp_dataff_wr,
resp_dataff_wdata, niu_ncu_ctag_ue, niu_ncu_ctag_ce, niu_ncu_d_pe,
// Inputs
clk, reset_l, sio_niu_hdr_vld, sio_niu_datareq, sio_niu_data,
sio_niu_parity, resp_cmdff_full, resp_dataff_full,
ncu_niu_ctag_uei, ncu_niu_ctag_cei, ncu_niu_d_pei, reg_ras_cfg
);
input clk;
input reset_l;
// sio if
input sio_niu_hdr_vld;
input sio_niu_datareq;
input [127:0] sio_niu_data;
input [7:0] sio_niu_parity;
// output niu_sio_dq; // this one comes from niu_smx_resp_dmc
// resp_cmdff if
output resp_cmdff_wr;
output [21:0] resp_cmdff_wdata;
input resp_cmdff_full; // not use??
// resp_dataff if
output resp_dataff_wr;
output [143:0] resp_dataff_wdata;
input resp_dataff_full; // not use??
// ncu ras if
input ncu_niu_ctag_uei;
input ncu_niu_ctag_cei;
input ncu_niu_d_pei;
output niu_ncu_ctag_ue;
output niu_ncu_ctag_ce;
output niu_ncu_d_pe;
// pio if
input [1:0] reg_ras_cfg; // [0] - disable(0)/enable(1) ras detect
// [1] - disable(0)/enable(1) ras inject
// xtb if -> this one in niu_smx_resp_dmc?
// just read and put in ff
// register in
reg [127:0] sio_niu_data_r1;
reg [7:0] sio_niu_parity_r1;
reg [127:0] sio_niu_data_r2;
reg [7:0] sio_niu_parity_r2;
reg [127:0] sio_niu_data_r;
reg [7:0] sio_niu_parity_r;
reg sio_niu_hdr_vld_r1;
reg sio_niu_datareq_r1;
reg sio_niu_hdr_vld_r2;
reg sio_niu_datareq_r2;
reg sio_niu_hdr_vld_r;
reg sio_niu_datareq_r;
reg ncu_niu_ctag_uei_r;
reg ncu_niu_ctag_cei_r;
// reg ncu_niu_d_pei_r;
reg [3:0] datawr_shift_r2; // one cycle after hdr
reg [3:0] datawr_shift; // one cycle after hdr
reg [127:0] hdr_data_r;
reg hdr_datareq_r;
reg hdr_err_r;
reg niu_ncu_data_parity;
reg niu_ncu_ctag_ue;
reg niu_ncu_ctag_ce;
wire niu_ncu_d_pe= niu_ncu_data_parity;
wire err_inject_enable= reg_ras_cfg[1];
wire [15:0] tid_r1= sio_niu_data_r1[`SMX_SICMD_POS_ID];
wire tid_r1_0= (err_inject_enable & (ncu_niu_ctag_cei_r | ncu_niu_ctag_uei_r))?
~tid_r1[0] : tid_r1[0];
wire tid_r1_1= (err_inject_enable & ncu_niu_ctag_uei_r)? ~tid_r1[1] : tid_r1[1];
wire [5:0] tidecc_checkbit= sio_niu_data_r1[`SMX_SICMD_POS_ID_ECC];
wire [5:0] genpar_checkbit;
wire genpar_cor_p5;
niu_smx_ecc16_genpar ecc_genpar(
.data ({tid_r1[15:2],tid_r1_1, tid_r1_0}),
.chkbit (tidecc_checkbit[4:0]),
.parity (genpar_checkbit[5:0]),
.cor_parity_5 (genpar_cor_p5)
);
reg [5:0] tidecc_syn_r2;
// cc 061405 flipped order of bits
wire [5:0] tidecc_syn_n= { // e=p^c in ras
genpar_cor_p5 ^ tidecc_checkbit[5],
genpar_checkbit[4] ^ tidecc_checkbit[4],
genpar_checkbit[3] ^ tidecc_checkbit[3],
genpar_checkbit[2] ^ tidecc_checkbit[2],
genpar_checkbit[1] ^ tidecc_checkbit[1],
genpar_checkbit[0] ^ tidecc_checkbit[0]
};
reg [15:0] ecc_corr_tid_r;
// reg ecc_ok_r;
// reg ecc_corr_r;
reg ecc_uncorr_r;
wire [15:0] ecc_corr_tid_n;
wire ecc_ok_n;
wire ecc_corr_n;
wire ecc_uncorr_n;
wire [15:0] tid_r2= sio_niu_data_r2[`SMX_SICMD_POS_ID];
wire tid_r2_0= (err_inject_enable & (ncu_niu_ctag_cei_r | ncu_niu_ctag_uei_r))?
~tid_r2[0] : tid_r2[0];
wire tid_r2_1= (err_inject_enable & ncu_niu_ctag_uei_r)? ~tid_r2[1] : tid_r2[1];
wire err_detect_enable= reg_ras_cfg[0];
niu_smx_ecc16_corr ecc_corr(
.enable (err_detect_enable),
.data ({tid_r2[15:2],tid_r2_1, tid_r2_0}),
.syn (tidecc_syn_r2[5:0]),
.corr_data (ecc_corr_tid_n[15:0]),
.good (ecc_ok_n),
.corr_error (ecc_corr_n),
.uncorr_error (ecc_uncorr_n)
);
wire [7:0] sio_niu_parity_n; // parity to go into dataff
// parity of incoming data for cmp purpose
reg [7:0] gen_data_parity_r2;
wire [7:0] gen_data_parity_n;
wire data_r1_0= (err_inject_enable & ncu_niu_d_pei)? ~sio_niu_data_r1[0] : sio_niu_data_r1[0];
niu_smx_gen_siudp gen_siudp( // gen parity per N2 ras
.data ({sio_niu_data_r1 [127:1], data_r1_0}),
.parity (gen_data_parity_n [7:0])
);
wire data_parity_err_n= |(sio_niu_parity_r2^gen_data_parity_r2);
reg dp_err_r;
wire dp_err_n= dp_err_r | (data_parity_err_n &
(|datawr_shift_r2)); // sample at data wr cycle
always @(posedge clk) begin
if(!reset_l) begin
dp_err_r<= `SMX_PD 1'b0;
niu_ncu_data_parity<= `SMX_PD 1'b0;
end
else begin
if(sio_niu_hdr_vld_r2) // reset at hdr
dp_err_r<= `SMX_PD 1'b0;
else
dp_err_r<= `SMX_PD dp_err_n;
// strobe
if(datawr_shift_r2 == 4'b0001)
niu_ncu_data_parity<= `SMX_PD dp_err_n;
else
niu_ncu_data_parity<= `SMX_PD 1'b0;
end
end
always @(posedge clk) begin
if(!reset_l)
datawr_shift_r2<= `SMX_PD 4'h0;
else begin
if(sio_niu_datareq_r2 & sio_niu_hdr_vld_r2) // qualify with hdrvld
datawr_shift_r2<= `SMX_PD 4'hf; // ld 4cy write
else
datawr_shift_r2<= `SMX_PD (datawr_shift_r2>>1);
end
end
always @(posedge clk) begin
sio_niu_data_r1<= `SMX_PD sio_niu_data;
sio_niu_parity_r1<= `SMX_PD sio_niu_parity;
// gen ecc check bits
sio_niu_data_r2<= `SMX_PD sio_niu_data_r1;
sio_niu_parity_r2<= `SMX_PD sio_niu_parity_r1;
gen_data_parity_r2<= `SMX_PD gen_data_parity_n;
tidecc_syn_r2<= `SMX_PD tidecc_syn_n;
// calc syndrome
// syn= p^c (p=regen, c=siu's)
sio_niu_data_r<= `SMX_PD sio_niu_data_r2;
sio_niu_parity_r<= `SMX_PD sio_niu_parity_n;
// new generated parity to store in dataff
// gen parity on lend_convered sio_niu_data_r2
// flop in hdr data
// keep until next hdr cycle
if(sio_niu_hdr_vld_r2) begin
ecc_corr_tid_r<= `SMX_PD ecc_corr_tid_n; // corrected TID
hdr_data_r<= `SMX_PD sio_niu_data_r2;
hdr_datareq_r<= `SMX_PD sio_niu_datareq_r2;
end
end
always @(posedge clk) begin
if(!reset_l) begin
// ecc_ok_r<= `SMX_PD 1'b0;
// ecc_corr_r<= `SMX_PD 1'b0;
ecc_uncorr_r<= `SMX_PD 1'b0;
hdr_err_r<= 1'b0;
niu_ncu_ctag_ue<= `SMX_PD 1'b0;
niu_ncu_ctag_ce<= `SMX_PD 1'b0;
end
else begin
// TID ecc status, siu_hdr_ueORde flop in
// remain until next hdr cycle
if(sio_niu_hdr_vld_r2) begin
// ecc_ok_r<= `SMX_PD ecc_ok_n;
// ecc_corr_r<= `SMX_PD ecc_corr_n;
ecc_uncorr_r<= `SMX_PD ecc_uncorr_n;
hdr_err_r<= `SMX_PD |sio_niu_data_r2[`SMX_SICMD_POS_HERR];
end
// strobe
if(sio_niu_hdr_vld_r2) begin
niu_ncu_ctag_ue<= `SMX_PD ecc_uncorr_n & !(sio_niu_data_r2[81] | sio_niu_data_r2[80]); // cc 052005 ecc_corr_n;
// cc 061305 no ecc_uncorr if SIO already reporting
niu_ncu_ctag_ce<= `SMX_PD ecc_corr_n; // cc 052005 ecc_uncorr_n;
end
else begin
niu_ncu_ctag_ue<= `SMX_PD 1'b0;
niu_ncu_ctag_ce<= `SMX_PD 1'b0;
end
end
end
always @(posedge clk) begin
if(!reset_l) begin
sio_niu_hdr_vld_r1<= `SMX_PD 1'b0;
sio_niu_datareq_r1<= `SMX_PD 1'b0;
sio_niu_hdr_vld_r2<= `SMX_PD 1'b0;
sio_niu_datareq_r2<= `SMX_PD 1'b0;
sio_niu_hdr_vld_r<= `SMX_PD 1'b0;
sio_niu_datareq_r<= `SMX_PD 1'b0;
ncu_niu_ctag_uei_r<= `SMX_PD 1'b0;
ncu_niu_ctag_cei_r<= `SMX_PD 1'b0;
// ncu_niu_d_pei_r<= `SMX_PD 1'b0;
end
else begin
sio_niu_hdr_vld_r1<= `SMX_PD sio_niu_hdr_vld;
sio_niu_datareq_r1<= `SMX_PD sio_niu_datareq;
sio_niu_hdr_vld_r2<= `SMX_PD sio_niu_hdr_vld_r1;
sio_niu_datareq_r2<= `SMX_PD sio_niu_datareq_r1;
sio_niu_hdr_vld_r<= `SMX_PD sio_niu_hdr_vld_r2;
sio_niu_datareq_r<= `SMX_PD sio_niu_datareq_r2;
ncu_niu_ctag_uei_r<= `SMX_PD ncu_niu_ctag_uei;
ncu_niu_ctag_cei_r<= `SMX_PD ncu_niu_ctag_cei;
// ncu_niu_d_pei_r<= `SMX_PD ncu_niu_d_pei;
end
end
always @(posedge clk) begin
if(!reset_l)
datawr_shift<= `SMX_PD 4'h0;
else begin
if(sio_niu_datareq_r & sio_niu_hdr_vld_r) // qualify with hdrvld
datawr_shift<= `SMX_PD 4'hf; // ld 4cy write
else
datawr_shift<= `SMX_PD (datawr_shift>>1);
end
end
reg resp_cmdff_wr;
wire resp_cmdff_wr_n= (sio_niu_hdr_vld_r2 & ~sio_niu_datareq_r2) | // no data cycle
(datawr_shift_r2==4'b0001); // last data line
// resp cmdff wr
always @(posedge clk) begin
if(!reset_l) resp_cmdff_wr<= `SMX_PD 1'b0;
else resp_cmdff_wr<= `SMX_PD resp_cmdff_wr_n;
end
wire [21:0] resp_cmdff_wdata= { // hdr cycle
hdr_datareq_r, // in case rd w/o data (err case)
hdr_data_r[`SMX_SICMD_POS_RESP],
hdr_data_r[`SMX_SICMD_POS_RD],
// sio_niu_data_r[`SMX_SICMD_POS_ERR],
2'h0, ((ecc_uncorr_r | hdr_err_r | dp_err_r) & err_detect_enable),
ecc_corr_tid_r
};
// gen parity for dataff at r2 stage;
// use little endian to gen sio_niu_parity_r
// big endian -> little endian
wire [127:0] lend_data_r2_n= { sio_niu_data_r2[`SMX_BE_B15],
sio_niu_data_r2[`SMX_BE_B14],
sio_niu_data_r2[`SMX_BE_B13],
sio_niu_data_r2[`SMX_BE_B12],
sio_niu_data_r2[`SMX_BE_B11],
sio_niu_data_r2[`SMX_BE_B10],
sio_niu_data_r2[`SMX_BE_B9],
sio_niu_data_r2[`SMX_BE_B8],
sio_niu_data_r2[`SMX_BE_B7],
sio_niu_data_r2[`SMX_BE_B6],
sio_niu_data_r2[`SMX_BE_B5],
sio_niu_data_r2[`SMX_BE_B4],
sio_niu_data_r2[`SMX_BE_B3],
sio_niu_data_r2[`SMX_BE_B2],
sio_niu_data_r2[`SMX_BE_B1],
sio_niu_data_r2[`SMX_BE_B0]
};
niu_smx_gen_siudp genpar(
.data (lend_data_r2_n [127 :0]),
.parity (sio_niu_parity_n[7:0])
);
// resp dataff wr
wire resp_dataff_wr= datawr_shift[0];
// big endian -> little endian
wire [127:0] lend_data_n= { sio_niu_data_r[`SMX_BE_B15],
sio_niu_data_r[`SMX_BE_B14],
sio_niu_data_r[`SMX_BE_B13],
sio_niu_data_r[`SMX_BE_B12],
sio_niu_data_r[`SMX_BE_B11],
sio_niu_data_r[`SMX_BE_B10],
sio_niu_data_r[`SMX_BE_B9],
sio_niu_data_r[`SMX_BE_B8],
sio_niu_data_r[`SMX_BE_B7],
sio_niu_data_r[`SMX_BE_B6],
sio_niu_data_r[`SMX_BE_B5],
sio_niu_data_r[`SMX_BE_B4],
sio_niu_data_r[`SMX_BE_B3],
sio_niu_data_r[`SMX_BE_B2],
sio_niu_data_r[`SMX_BE_B1],
sio_niu_data_r[`SMX_BE_B0]
};
// wire resp_dataff_err= dp_err_r;
wire [143:0] resp_dataff_wdata= {8'h0, sio_niu_parity_r, lend_data_n};
endmodule