// ========== 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