Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / niu_smx_xtb.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: niu_smx_xtb.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_xtb(
/*AUTOARG*/
// Outputs
rdreq_rst_xtb_wr, wreq_rst_xtb_wr, xtb_rdata, xtb_rd_ack,
xtb_rdata_err, tid_valid_set, tid_valid_set_addr, tid_newarr_set,
tid_newarr_set_addr, tohdl_xtb_rdata, tohdl_xtb_rd_ack,
tohdl_xtb_rdata_err, mb0_smx_table_64x146_scan_out,
niu_mb0_smx_table_data_out,
// Inputs
clk, iol2clk, reset_l, rdreq_xtb_wr, rdreq_xtb_waddr, rdreq_xtb_wdata,
wreq_xtb_wr, wreq_xtb_waddr, wreq_xtb_wdata, xtb_rd, xtb_raddr,
xtb_rcvfile_update, xtb_rcvfile_update_addr, tohdl_xtb_rd,
tohdl_xtb_raddr, tcu_aclk, tcu_bclk,
tcu_se_scancollar_in,
tcu_array_wr_inhibit, mb0_smx_table_64x146_scan_in,
niu_mb0_smx_table_64x146_wdata, niu_mb0_smx_table_64x146_rd_addr,
niu_mb0_smx_table_64x146_wr_addr, niu_mb0_smx_table_64x146_wr_en,
niu_mb0_smx_table_64x146_rd_en, niu_mb0_run,
pio_xtb_err_inject_cfg
);
input clk;
input iol2clk;
input reset_l;
// rdreq if
input rdreq_xtb_wr;
input [5:0] rdreq_xtb_waddr;
input [127:0] rdreq_xtb_wdata;
output rdreq_rst_xtb_wr;
// wreq if
input wreq_xtb_wr;
input [5:0] wreq_xtb_waddr;
input [127:0] wreq_xtb_wdata;
output wreq_rst_xtb_wr;
// resp dmc sm if
input xtb_rd;
input [5:0] xtb_raddr;
output [128:0] xtb_rdata; // {rcvcnt, xtb_rdata}
output xtb_rd_ack; // rst client rd signal
output xtb_rdata_err;
input xtb_rcvfile_update;
input [5:0] xtb_rcvfile_update_addr;
// status if
output tid_valid_set; // set by req_cmd
output [5:0] tid_valid_set_addr;
output tid_newarr_set; // set by req_cmd
output [5:0] tid_newarr_set_addr;
// timeout handler; arb with resp dmc
input tohdl_xtb_rd;
input [5:0] tohdl_xtb_raddr;
output [118:0] tohdl_xtb_rdata; // {xtb_rdata}; rcvcnt not part of
output tohdl_xtb_rd_ack; // rst client rd signal
output tohdl_xtb_rdata_err;
// client must rst rd in next cycle
// mbist if
input tcu_aclk;
input tcu_bclk;
input tcu_se_scancollar_in;
input tcu_array_wr_inhibit;
input mb0_smx_table_64x146_scan_in;
output mb0_smx_table_64x146_scan_out;
input [7:0] niu_mb0_smx_table_64x146_wdata;
input [5:0] niu_mb0_smx_table_64x146_rd_addr;
input [5:0] niu_mb0_smx_table_64x146_wr_addr;
input niu_mb0_smx_table_64x146_wr_en;
input niu_mb0_smx_table_64x146_rd_en;
input niu_mb0_run;
output [145:0] niu_mb0_smx_table_data_out;
// pio i/f
input [2:0] pio_xtb_err_inject_cfg; // [0] - one pkt
// [1] - alt pkt
// [2] - all pkt
// wire [4:0] rdreq_xtb_raddr= xtb_raddr[4:0];
// wire [4:0] wreq_xtb_raddr= xtb_raddr[4:0];
// wire rdreq_xtb_rd= xtb_rd;
// wire wreq_xtb_rd= xtb_rd;
// wire [143:0] wreq_xtb_rdata;
// wire [143:0] rdreq_xtb_rdata;
wire [145:0] sel_xtb_rdata;
wire [145:0] niu_mb0_smx_table_data_out= sel_xtb_rdata;
// wire [143:0] sel_xtb_rdata;
// wire [143:0] sel_xtb_rdata= (xtb_raddr[5])? wreq_xtb_rdata : rdreq_xtb_rdata;
// or arb rd/wr, rd steal wr cycles
// during wr writes 4 data ???
// if use one ram 144bx64 ??
reg rdreq_rst_xtb_wr_n;
wire rdreq_rst_xtb_wr= rdreq_rst_xtb_wr_n;
reg wreq_rst_xtb_wr_n;
wire wreq_rst_xtb_wr= wreq_rst_xtb_wr_n;
reg first_choice;
reg first_choice_n;
always @(posedge clk) begin
if(!reset_l) begin
first_choice<= `SMX_PD 1'b0; // 0-wr, 1- rd
end
else begin
first_choice<= `SMX_PD first_choice_n; // 0-wr, 1- rd
end
end
always @(/*AUTOSENSE*/first_choice or rdreq_xtb_wr or wreq_xtb_wr) begin
first_choice_n= first_choice;
rdreq_rst_xtb_wr_n= 1'b0;
wreq_rst_xtb_wr_n= 1'b0;
case({first_choice, wreq_xtb_wr, rdreq_xtb_wr})
3'b000: begin
first_choice_n= first_choice;
rdreq_rst_xtb_wr_n= 1'b0;
wreq_rst_xtb_wr_n= 1'b0;
end
3'b001: begin // rd
first_choice_n= 1'b0; // wr first nxt
rdreq_rst_xtb_wr_n= 1'b1;
wreq_rst_xtb_wr_n= 1'b0;
end
3'b010: begin // wr
first_choice_n= 1'b1; // rd first nxt
rdreq_rst_xtb_wr_n= 1'b0;
wreq_rst_xtb_wr_n= 1'b1;
end
3'b011: begin // wr, rd; wr first
first_choice_n= 1'b1; // rd first nxt
rdreq_rst_xtb_wr_n= 1'b0;
wreq_rst_xtb_wr_n= 1'b1;
end
3'b100: begin //
first_choice_n= first_choice;
rdreq_rst_xtb_wr_n= 1'b0;
wreq_rst_xtb_wr_n= 1'b0;
end
3'b101: begin // rd
first_choice_n= 1'b0; // wr first nxt
rdreq_rst_xtb_wr_n= 1'b1;
wreq_rst_xtb_wr_n= 1'b0;
end
3'b110: begin // wr
first_choice_n= 1'b1; // rd first nxt
rdreq_rst_xtb_wr_n= 1'b0;
wreq_rst_xtb_wr_n= 1'b1;
end
3'b111: begin // rd, wr; rd first
first_choice_n= 1'b0; // wr first nxt
rdreq_rst_xtb_wr_n= 1'b1;
wreq_rst_xtb_wr_n= 1'b0;
end
endcase
end
wire xtb_rd_ack_n;
wire tohdl_xtb_rd_ack_n;
wire [5:0] sel_xtb_raddr;
reg xtb_busy;
reg xtb_rd_ack_r2; // ram data avail
reg xtb_rd_ack_r3; // extra stage for err check
reg xtb_rd_ack;
reg tohdl_xtb_rd_ack_r2;
reg tohdl_xtb_rd_ack_r3;
reg tohdl_xtb_rd_ack;
reg [145:0] xtb_rdata_r3;
reg [145:0] xtb_rdata_r4;
// move xtb_raddr_r1 one cycle earlier
//reg xtb_rd_ack_r1; // ram input
//reg tohdl_xtb_rd_ack_r1;
//reg [5:0] sel_xtb_raddr_r1; // ram input
wire xtb_rd_ack_r1= xtb_rd_ack_n;
wire tohdl_xtb_rd_ack_r1= tohdl_xtb_rd_ack_n;
wire [5:0] sel_xtb_raddr_r1= sel_xtb_raddr;
wire xtb_rd_n= (xtb_rd_ack_r1 | tohdl_xtb_rd_ack_r1);
reg xtb_rdata_perr;
wire xtb_rdata_err= xtb_rdata_perr;
reg tohdl_xtb_rdata_perr;
wire tohdl_xtb_rdata_err= tohdl_xtb_rdata_perr;
reg [145:0] tohdl_xtb_rdata_r4;
wire [118:0] tohdl_xtb_rdata= tohdl_xtb_rdata_r4[118:0];
niu_smx_arb_2c #(6) arb_xtb_rd(
.clk (clk),
.reset_l (reset_l),
.req_a (xtb_rd & ~xtb_busy),
.req_b (tohdl_xtb_rd & ~xtb_busy),
.muxin_a (xtb_raddr [5:0]),
.muxin_b (tohdl_xtb_raddr [5:0]),
.ack_a (xtb_rd_ack_n),
.ack_b (tohdl_xtb_rd_ack_n),
.selout (sel_xtb_raddr [5:0])
);
always @(posedge clk) begin
if(!reset_l) begin
xtb_busy<= `SMX_PD 1'b0;
end
else begin
if(xtb_rd_ack_n | tohdl_xtb_rd_ack_n) xtb_busy<= `SMX_PD 1'b1;
else if (xtb_rd_ack | tohdl_xtb_rd_ack) xtb_busy<= `SMX_PD 1'b0;
end
end
wire [5:0] sel_xtb_waddr= (rdreq_rst_xtb_wr_n)?
rdreq_xtb_waddr : wreq_xtb_waddr;
wire [127:0] sel_xtb_wdata= (rdreq_rst_xtb_wr_n)?
rdreq_xtb_wdata : wreq_xtb_wdata;
wire tid_valid_set= rdreq_rst_xtb_wr_n|wreq_rst_xtb_wr_n;
wire [5:0] tid_valid_set_addr= sel_xtb_waddr;
wire tid_newarr_set= rdreq_rst_xtb_wr_n|wreq_rst_xtb_wr_n;
wire [5:0] tid_newarr_set_addr= sel_xtb_waddr;
wire [7:0] xtb_parity_wdata_n;
niu_smx_gen_siudp gen_xtb_par_wdata(// gen parity per N2 ras
.data (sel_xtb_wdata [127:0]),
.parity (xtb_parity_wdata_n [7:0])
);
wire [145:0] concat_niu_mb0_smx_table_64x146_wdata={
niu_mb0_smx_table_64x146_wdata[1:0],
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata,
niu_mb0_smx_table_64x146_wdata
};
niu_ram_64_146 xtb_ram(
.tcu_aclk (tcu_aclk),
.tcu_bclk (tcu_bclk),
.tcu_se_scancollar_in (tcu_se_scancollar_in),
.tcu_array_wr_inhibit (tcu_array_wr_inhibit),
.scan_in (mb0_smx_table_64x146_scan_in),
.scan_out (mb0_smx_table_64x146_scan_out),
.mbi_wdata (concat_niu_mb0_smx_table_64x146_wdata [145:0]),
.mbi_rd_adr (niu_mb0_smx_table_64x146_rd_addr [5:0]),
.mbi_wr_adr (niu_mb0_smx_table_64x146_wr_addr [5:0]),
.mbi_wr_en (niu_mb0_smx_table_64x146_wr_en),
.mbi_rd_en (niu_mb0_smx_table_64x146_rd_en),
.mbi_run (niu_mb0_run),
.clk (iol2clk),
.wt_enable (rdreq_xtb_wr | wreq_xtb_wr),
.addr_wt (sel_xtb_waddr[5:0]),
.data_inp ({10'h0, xtb_parity_wdata_n, sel_xtb_wdata[127:0]}),
.cs_rd (xtb_rd_n),
.addr_rd (sel_xtb_raddr_r1[5:0]),
.data_out (sel_xtb_rdata[145:0])
);
wire err_inject_enable_n;
wire [127:0] xtb_rdata_r3_n= (err_inject_enable_n)?
{xtb_rdata_r3[127:1], ~xtb_rdata_r3[0]}:
xtb_rdata_r3[127:0];
wire [7:0] xtb_parity_rdata_n;
niu_smx_gen_siudp gen_xtb_par_rdata(// gen parity per N2 ras
.data (xtb_rdata_r3_n [127:0]),
.parity (xtb_parity_rdata_n [7:0])
);
wire xtb_rdata_perr_n= |(xtb_parity_rdata_n ^ xtb_rdata_r3[135:128]);
// move xtb_rd_r1 one cycle earlier
// xtb_rd_ack_r1<= `SMX_PD 1'b0;
// tohdl_xtb_rd_ack_r1<= `SMX_PD 1'b0;
// xtb_rd_ack_r1<= `SMX_PD xtb_rd_ack_n ;
// tohdl_xtb_rd_ack_r1<= `SMX_PD tohdl_xtb_rd_ack_n;
always @(posedge clk) begin
if(!reset_l) begin
xtb_rd_ack_r2<= `SMX_PD 1'b0;
xtb_rd_ack_r3<= `SMX_PD 1'b0;
xtb_rd_ack<= `SMX_PD 1'b0;
tohdl_xtb_rd_ack_r2<= `SMX_PD 1'b0;
tohdl_xtb_rd_ack_r3<= `SMX_PD 1'b0;
tohdl_xtb_rd_ack<= `SMX_PD 1'b0;
end
else begin
xtb_rd_ack_r2<= `SMX_PD xtb_rd_ack_r1 ; // rdata avail at r2
xtb_rd_ack_r3<= `SMX_PD xtb_rd_ack_r2 ; // extra cycle for ecc
xtb_rd_ack<= `SMX_PD xtb_rd_ack_r3;
tohdl_xtb_rd_ack_r2<= `SMX_PD tohdl_xtb_rd_ack_r1;
tohdl_xtb_rd_ack_r3<= `SMX_PD tohdl_xtb_rd_ack_r2;
tohdl_xtb_rd_ack<= `SMX_PD tohdl_xtb_rd_ack_r3;
end
end
always @(posedge clk) begin
// if(xtb_rd_ack_n | tohdl_xtb_rd_ack_n) sel_xtb_raddr_r1<= `SMX_PD sel_xtb_raddr;
xtb_rdata_r3<= `SMX_PD sel_xtb_rdata;
// wanna keep data constant after ack
if(xtb_rd_ack_r3) begin
xtb_rdata_r4<= `SMX_PD xtb_rdata_r3;
xtb_rdata_perr<= `SMX_PD xtb_rdata_perr_n;
end
if(tohdl_xtb_rd_ack_r3) begin
tohdl_xtb_rdata_r4<= `SMX_PD xtb_rdata_r3;
tohdl_xtb_rdata_perr<= `SMX_PD xtb_rdata_perr_n;
end
end
/*
register implemented
niu_smx_regfl #(144,6) xtb_regfl(
.clk (clk),
.reset_l (reset_l),
.wr (rdreq_xtb_wr | wreq_xtb_wr),
.addr_wr (sel_xtb_waddr[5:0]),
.data_wr ({16'h0, sel_xtb_wdata[127:0]}),
.rd (xtb_rd),
.addr_rd (xtb_raddr[5:0]),
.data_rd (sel_xtb_rdata[143:0])
);
*/
/*
not use
niu_smx_regfl #(144,5) xtb_wr_regfl(
.clk (clk),
.reset_l (reset_l),
.wr (wreq_xtb_wr),
.addr_wr (wreq_xtb_waddr[4:0]),
.data_wr ({16'h0, wreq_xtb_wdata[127:0]}),
.rd (wreq_xtb_rd),
.addr_rd (wreq_xtb_raddr[4:0]),
.data_rd (wreq_xtb_rdata[143:0])
);
*/
/*
wire[5:0] xtb_waddr= (wreq_xtb_wr)? {1'b1, wreq_xtb_waddr[4:0]} :
{1'b0, rdreq_xtb_waddr[4:0]};
wire [9:0] rcvfile_rdata;
wire [128:0] xtb_rdata= {rcvfile_rdata[9:0],sel_xtb_rdata[118:0]};
wire xtb_wr= rdreq_xtb_wr | wreq_xtb_wr;
*/
// ??? no parity yet
// ??? can more bits remove ?
// ??? rcvfile rdata truncate to 9bits
// make 2 copies; one for rd, one for wr; ???
// might need to add arb if combine both ????
// wire [9:0] rdreq_rcvfile_rdata;
// // // // // // // // wire [9:0] wreq_rcvfile_rdata;
/*
wire [9:0] sel_rcvfile_rdata= (xtb_raddr[5])?
wreq_rcvfile_rdata : rdreq_rcvfile_rdata;
*/
wire [9:0] rcvfile_rdata;
wire [128:0] xtb_rdata= {rcvfile_rdata[9:0], xtb_rdata_r4[118:0]};
wire [5:0] rcvfile_raddr_n= (xtb_rcvfile_update)?
xtb_rcvfile_update_addr : xtb_raddr;
niu_smx_resp_rcvfile #(10,6) rdreq_resp_rcvfile(
.clk (clk),
.reset_l (reset_l),
.rd (xtb_rd_ack_n),
.rd_inc (xtb_rcvfile_update),
.raddr (rcvfile_raddr_n[5:0]),
.wr_rst (rdreq_xtb_wr | wreq_xtb_wr),
.waddr (sel_xtb_waddr[5:0]),
.rdata (rcvfile_rdata[9:0])
);
/*
niu_smx_resp_rcvfile #(10,5) wreq_resp_rcvfile(
.clk (clk),
.reset_l (reset_l),
.rd (), // nc
.rd_inc (xtb_rd),
.raddr (xtb_raddr[4:0]),
.wr_rst (wreq_xtb_wr),
.waddr (wreq_xtb_waddr[4:0]),
.rdata (wreq_rcvfile_rdata[9:0])
);
*/
// ??? add xtb_rd arb; rcvfile xtb_rd fix ?????
// error inject
reg one_pkt_flag;
reg alt_pkt_flag;
wire rd_ack_n= xtb_rd_ack_r3 | tohdl_xtb_rd_ack_r3;
// mux err-injected data occurs at r3
always @(posedge clk) begin
if(!reset_l) begin
one_pkt_flag <= `SMX_PD 1'b0;
alt_pkt_flag <= `SMX_PD 1'b0;
end
else begin
if(rd_ack_n & ~one_pkt_flag & pio_xtb_err_inject_cfg[0])
one_pkt_flag <= `SMX_PD 1'b1; // set one_pkt flag
else if (~pio_xtb_err_inject_cfg[0]) one_pkt_flag <= `SMX_PD 1'b0;
// reset when cfg one_pkt unset
if(rd_ack_n & pio_xtb_err_inject_cfg[1]) // alternate each rd
alt_pkt_flag <= `SMX_PD ~alt_pkt_flag;
end
end
assign err_inject_enable_n= (~one_pkt_flag & pio_xtb_err_inject_cfg[0]) |
(alt_pkt_flag & pio_xtb_err_inject_cfg[1]) |
pio_xtb_err_inject_cfg[2];
endmodule