blob: 4115c4002d8998d44523e482f5bbbf7990fe9bc5 [file] [log] [blame] [edit]
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T1 Processor File: ucb_bus_in.v
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
//
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
//
// The above named 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 work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// ========== Copyright Header End ============================================
////////////////////////////////////////////////////////////////////////
/*
// Module Name: ucb_bus_in (ucb bus inbound interface block)
// Description: This interface block is instaniated by the
// UCB modules and IO Bridge to receive packets
// on the UCB bus.
*/
////////////////////////////////////////////////////////////////////////
// Global header file includes
////////////////////////////////////////////////////////////////////////
`include "sys.h" // system level definition file which contains the
// time scale definition
////////////////////////////////////////////////////////////////////////
// Local header file includes / local defines
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// Interface signal list declarations
////////////////////////////////////////////////////////////////////////
module ucb_bus_in (/*AUTOARG*/
// Outputs
stall, indata_buf_vld, indata_buf,
// Inputs
rst_l, clk, vld, data, stall_a1
);
// synopsys template
parameter UCB_BUS_WIDTH = 32;
parameter REG_WIDTH = 64;
////////////////////////////////////////////////////////////////////////
// Signal declarations
////////////////////////////////////////////////////////////////////////
// Global interface
input rst_l;
input clk;
// UCB bus interface
input vld;
input [UCB_BUS_WIDTH-1:0] data;
output stall;
// Local interface
output indata_buf_vld;
output [REG_WIDTH+63:0] indata_buf;
input stall_a1;
// Internal signals
wire vld_d1;
wire stall_d1;
wire [UCB_BUS_WIDTH-1:0] data_d1;
wire skid_buf0_en;
wire vld_buf0;
wire [UCB_BUS_WIDTH-1:0] data_buf0;
wire skid_buf1_en;
wire vld_buf1;
wire [UCB_BUS_WIDTH-1:0] data_buf1;
wire skid_buf0_sel;
wire skid_buf1_sel;
wire vld_mux;
wire [UCB_BUS_WIDTH-1:0] data_mux;
wire [(REG_WIDTH+64)/UCB_BUS_WIDTH-1:0] indata_vec_next;
wire [(REG_WIDTH+64)/UCB_BUS_WIDTH-1:0] indata_vec;
wire [REG_WIDTH+63:0] indata_buf_next;
wire indata_vec0_d1;
////////////////////////////////////////////////////////////////////////
// Code starts here
////////////////////////////////////////////////////////////////////////
/************************************************************
* UCB bus interface flops
* This is to make signals going between IOB and UCB flop-to-flop
* to improve timing.
************************************************************/
dffrle_ns #(1) vld_d1_ff (.din(vld),
.rst_l(rst_l),
.en(~stall_d1),
.clk(clk),
.q(vld_d1));
dffe_ns #(UCB_BUS_WIDTH) data_d1_ff (.din(data),
.en(~stall_d1),
.clk(clk),
.q(data_d1));
dffrl_ns #(1) stall_ff (.din(stall_a1),
.clk(clk),
.rst_l(rst_l),
.q(stall));
dffrl_ns #(1) stall_d1_ff (.din(stall),
.clk(clk),
.rst_l(rst_l),
.q(stall_d1));
/************************************************************
* Skid buffer
* We need a two deep skid buffer to handle stalling.
************************************************************/
// Assertion: stall has to be deasserted for more than 1 cycle
// ie time between two separate stalls has to be
// at least two cycles. Otherwise, contents from
// skid buffer will be lost.
// Buffer 0
assign skid_buf0_en = stall_a1 & ~stall;
dffrle_ns #(1) vld_buf0_ff (.din(vld_d1),
.rst_l(rst_l),
.en(skid_buf0_en),
.clk(clk),
.q(vld_buf0));
dffe_ns #(UCB_BUS_WIDTH) data_buf0_ff (.din(data_d1),
.en(skid_buf0_en),
.clk(clk),
.q(data_buf0));
// Buffer 1
dffrl_ns #(1) skid_buf1_en_ff (.din(skid_buf0_en),
.clk(clk),
.rst_l(rst_l),
.q(skid_buf1_en));
dffrle_ns #(1) vld_buf1_ff (.din(vld_d1),
.rst_l(rst_l),
.en(skid_buf1_en),
.clk(clk),
.q(vld_buf1));
dffe_ns #(UCB_BUS_WIDTH) data_buf1_ff (.din(data_d1),
.en(skid_buf1_en),
.clk(clk),
.q(data_buf1));
/************************************************************
* Mux between skid buffer and interface flop
************************************************************/
// Assertion: stall has to be deasserted for more than 1 cycle
// ie time between two separate stalls has to be
// at least two cycles. Otherwise, contents from
// skid buffer will be lost.
assign skid_buf0_sel = ~stall_a1 & stall;
dffrl_ns #(1) skid_buf1_sel_ff (.din(skid_buf0_sel),
.clk(clk),
.rst_l(rst_l),
.q(skid_buf1_sel));
assign vld_mux = skid_buf0_sel ? vld_buf0 :
skid_buf1_sel ? vld_buf1 :
vld_d1;
assign data_mux = skid_buf0_sel ? data_buf0 :
skid_buf1_sel ? data_buf1 :
data_d1;
/************************************************************
* Assemble inbound data
************************************************************/
// valid vector
assign indata_vec_next = {vld_mux,
indata_vec[(REG_WIDTH+64)/UCB_BUS_WIDTH-1:1]};
dffrle_ns #((REG_WIDTH+64)/UCB_BUS_WIDTH) indata_vec_ff (.din(indata_vec_next),
.en(~stall_a1),
.rst_l(rst_l),
.clk(clk),
.q(indata_vec));
// data buffer
assign indata_buf_next = {data_mux,
indata_buf[REG_WIDTH+63:UCB_BUS_WIDTH]};
dffe_ns #(REG_WIDTH+64) indata_buf_ff (.din(indata_buf_next),
.en(~stall_a1),
.clk(clk),
.q(indata_buf));
// detect a new packet
dffrle_ns #(1) indata_vec0_d1_ff (.din(indata_vec[0]),
.rst_l(rst_l),
.en(~stall_a1),
.clk(clk),
.q(indata_vec0_d1));
assign indata_buf_vld = indata_vec[0] & ~indata_vec0_d1;
endmodule // ucb_bus_in