// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: niu_pio_ucb.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
// ========== Copyright Header End ============================================
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 by Sun Microsystems, Inc.
// All rights reserved. No part of this design may be reproduced,
// stored in a retrieval system, or transmitted, in any form or by
// any means, electronic, mechanical, photocopying, recording, or
// otherwise, without prior written permission of Sun Microsystems,
// Sun Proprietary/Confidential
// Primary Contact: Jimmy.Lau@sun.com x48745
// Description: Unit Control Block for NIU interface to NCU,
// basing on Niagra design's ucb_flow_jbi module.
// This module is customized for N2's NIU block.
// - provides 1+2 deep buffer for incoming requests
// - provides single buffer for returns going back to
// - Downstream data bus width : 32' + 2' control
// - Upstream data bus widht : 32' + 2' control
// Revision: 1. March 08, 2004 - John Lo
// Changed modules name from
// ucb_bus_in32_niu.v to niu_pio_ucb_in32
// ucb_bus_out32_niu.v to niu_pio_ucb_out32
// ucb_flow_niu.v to niu_pio_ucb
// Changed enl2clk to clk.
// Revision: 2. September 01, 2004 - Jimmy Lau
// Changed addr_in from [39:0] to [25:0].
////////////////////////////////////////////////////////////////////////////////
// Downstream Path from NCU //
// Upstream Path to NCU //
// Local CSR Read Retruns //
input [31:0] ncu_niu_data;
output [31:0] niu_ncu_data;
// Ack/Nack from local unit
// Interrupt from local unit
input [6:0] dev_id; // interrupt device ID
wire [2:0] unconnected_size_in;
wire [12:0] unconnected_addr_39_27;
wire [8:0] unconnected_rsvd;
wire [1:0] buf_head_next;
wire [1:0] buf_tail_next;
//wire [56:0] int_buf_in;
wire [127:0] outdata_buf_in;
wire [3:0] outdata_vec_in;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/************************************************************
************************************************************/
niu_pio_ucb_in32 niu_pio_ucb_in32 (.reset(niu_reset_l),
.data(ncu_niu_data[31:0]),
.indata_buf_vld(indata_buf_vld),
.indata_buf(indata_buf[127:0]),
.stall_a1(niu_ncu_stall_a1));
/************************************************************
* Decode inbound packet type
************************************************************/
assign read_pending = (indata_buf[3:0] == 4'b0100) & indata_buf_vld;
assign write_pending = (indata_buf[3:0] == 4'b0101) & indata_buf_vld;
assign niu_ncu_stall_a1 = (read_pending | write_pending) & buf_full;
/************************************************************
************************************************************/
assign rd_buf = req_accepted;
assign buf_head_next[1:0] = niu_reset_l ? 2'b01 :
rd_buf ? {buf_head[0],buf_head[1]} : buf_head[1:0];
df1 #(2) buf_head_ff (.d(buf_head_next[1:0]),
assign wr_buf = (read_pending | write_pending) & ~buf_full;
assign buf_tail_next[1:0] = niu_reset_l ? 2'b01 :
wr_buf ? {buf_tail[0], buf_tail[1]} : buf_tail[1:0];
df1 #(2) buf_tail_ff (.d(buf_tail_next[1:0]),
assign buf_full_next = (buf_head_next[1:0] == buf_tail_next[1:0]) & wr_buf;
dffre #(1) buf_full_ff (.d(buf_full_next),
assign buf_empty_next = ((buf_head_next[1:0] == buf_tail_next[1:0]) & rd_buf) | niu_reset_l;
dffe #(1) buf_empty_ff (.d(buf_empty_next),
.en(rd_buf|wr_buf|niu_reset_l),
assign unconnected_addr_39_27[12:0] = indata_buf[54:42];
assign unconnected_rsvd[8:0] = indata_buf[63:55];
assign req_in[103:0] = {indata_buf[127:64],
assign buf0_en = buf_tail[0] & wr_buf;
dffre #(104) buf0_ff (.d(req_in[103:0]),
assign buf1_en = buf_tail[1] & wr_buf;
dffre #(104) buf1_ff (.d(req_in[103:0]),
assign req_out[103:0] = buf_head[0] ? buf0[103:0] :
buf_head[1] ? buf1[103:0] : 104'b0;
/************************************************************
* Inbound interface to local unit
************************************************************/
unconnected_size_in[2:0],
rd_req_vld_nq} = req_out[103:0];
assign rd_req_vld = rd_req_vld_nq & ~buf_empty;
assign wr_req_vld = wr_req_vld_nq & ~buf_empty;
/************************************************************
************************************************************/
assign ack_buf_wr = rd_ack_vld | rd_nack_vld;
assign ack_buf_vld_next = ack_buf_wr ? 1'b1 :
ack_buf_rd ? 1'b0 : ack_buf_vld;
dffr #(1) ack_buf_vld_ff (.d(ack_buf_vld_next),
dffre #(1) ack_buf_is_nack_ff (.d(rd_nack_vld),
assign ack_typ_out[3:0] = rd_ack_vld ? 4'b0001: //UCB_READ_ACK
assign ack_buf_in[75:0] = {data_out[7:0],
dffre #(76) ack_buf_ff (.d(ack_buf_in[75:0]),
assign ack_buf_vec[3:0] = ack_buf_is_nack ? {2'b00,2'b11} : {4'b1111} ;
assign rack_busy = ack_buf_vld;
/************************************************************
************************************************************/
assign int_buf_wr = int_vld;
assign int_buf_vld_next = int_buf_wr ? 1'b1 :
int_buf_rd ? 1'b0 : int_buf_vld;
dffr #(1) int_buf_vld_ff (.d(int_buf_vld_next),
assign int_buf_in[56:0] = {int_vec[5:0],
assign int_buf_in[6:0] = dev_id[6:0] ;
dffre #(7) int_buf_ff (.d(int_buf_in[6:0]),
assign int_buf_vec = {2'b00,2'b11};
assign int_busy = int_buf_vld;
/************************************************************
* Outbound ack/interrupt Arbitration
************************************************************/
dffre #(1) int_last_rd_ff (.d(int_buf_rd),
.en(ack_buf_rd|int_buf_rd),
assign ack_buf_rd = ~outdata_buf_busy & ack_buf_vld &
(~int_buf_vld | int_last_rd);
assign int_buf_rd = ~outdata_buf_busy & int_buf_vld &
(~ack_buf_vld | ~int_last_rd);
assign outdata_buf_wr = ack_buf_rd | int_buf_rd;
assign outdata_buf_in[127:0] = ack_buf_rd ? {ack_buf[75:12], //payload 64bit
40'h00_0000_0000, //40bit addr [54:15]
ack_buf[11:10], //buf_id 2bit
ack_buf[9:4], //thr_id 6bit
ack_buf[3:0]}: //type 4bit
{64'h0000_0000_0000_0000,
7'b000_0000, // reserved[63:57]
{2'b0,int_buf[6:0]}, //dev_id 9bit
4'b1000}; //pkt_typ 4bit,plain int
assign outdata_vec_in[3:0] = ack_buf_rd ? ack_buf_vec[3:0] : int_buf_vec[3:0] ;
niu_pio_ucb_out32 niu_pio_ucb_out32 (.reset(niu_reset_l),
.data(niu_ncu_data[31:0]),
.outdata_buf_busy(outdata_buf_busy),
.outdata_buf_wr(outdata_buf_wr),
.outdata_buf_in(outdata_buf_in[127:0]),
.outdata_vec_in(outdata_vec_in[3:0]) );