Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / dmu / rtl / dmu_tmu_dim_datapath.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: dmu_tmu_dim_datapath.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 dmu_tmu_dim_datapath (
clk,
rst_l,
// data path
k2y_buf_addr,
y2k_buf_data,
y2k_buf_dpar,
// DIU interface
tm2di_data,
tm2di_bmask,
tm2di_dpar,
// IMU interface
tm2im_data,
// talk to datafsm.v
idb_rptr_inc,
data_mux_select,
first_dwbe_dp,
last_dwbe_dp,
align_addr_dp,
end_addr_dp,
payld_len_is_one_dp,
ld_saved_data_dp
);
//synopsys sync_set_reset "rst_l"
// >>>>>>>>>>>>>>>>>>>>>>>>> Parameter Declarations <<<<<<<<<<<<<<<<<<<<<<<<<
// data_mux_select
parameter ONLY_VDB = 0,
LAST_VDB = 1,
MID_VDB = 2,
FRST_VDB = 3,
ZERO_FILL = 4;
// data_mux_select number
parameter DATA_MUX_NUM = 5;
// >>>>>>>>>>>>>>>>>>>>>>>>> Port Declarations <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//------------------------------------------------------------------------
// Clock and Reset Signals
//------------------------------------------------------------------------
input clk;
input rst_l;
//------------------------------------------------------------------------
// data path to ILU
//------------------------------------------------------------------------
output [`FIRE_DLC_ITI_ADDR_WDTH-1:0] k2y_buf_addr; // read pointer to IDB
input [`FIRE_DLC_ITI_DATA_WDTH-1:0] y2k_buf_data; // 16-byte data
input [`FIRE_DLC_ITI_DPAR_WDTH-1:0] y2k_buf_dpar; // data parity
//------------------------------------------------------------------------
// DIU interface
//------------------------------------------------------------------------
output [`FIRE_DLC_TRD_DATA_WDTH-1:0] tm2di_data; // data to DIU
output [`FIRE_DLC_TRD_BMASK_WDTH-1:0] tm2di_bmask; // byte mask
output [`FIRE_DLC_TRD_DPAR_WDTH-1:0] tm2di_dpar; // data parity
//------------------------------------------------------------------------
// IMU interface
//------------------------------------------------------------------------
output [`FIRE_DLC_MDF_REC_WDTH-1:0] tm2im_data; // ingress
//------------------------------------------------------------------------
// talk to datafsm.v - data_mux_select encoding is
// { zero_fill, f_vdb, m_vdb, l_vdb, only_vdb}
//------------------------------------------------------------------------
input idb_rptr_inc;
input [DATA_MUX_NUM-1:0] data_mux_select;
input [3:0] first_dwbe_dp;
input [3:0] last_dwbe_dp;
input [3:2] align_addr_dp;
input [3:2] end_addr_dp;
input payld_len_is_one_dp;
input ld_saved_data_dp;
// >>>>>>>>>>>>>>>>>>>>>>>>> Data Type Declarations <<<<<<<<<<<<<<<<<<<<<<<<<
// ~~~~~~~~~~~~~~~~~~~~~~~~~ REGISTER - FLOPS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reg [`FIRE_DLC_ITI_ADDR_WDTH-1:0] k2y_buf_addr; // read pointer to IDB
reg [127:0] current_data;
reg [3:0] current_dpar;
reg [95:0] saved_data;
reg [2:0] saved_dpar;
reg [127:0] tm2di_data;
reg [4:0] tm2di_dpar;
reg [15:0] tm2di_bmask;
reg msi_parity_err;
// ~~~~~~~~~~~~~~~~~~~~~~~~~ REGISTER - NON-FLOPS ~~~~~~~~~~~~~~~~~~~~~~~~
reg [127:0] n_tm2di_data;
reg [4:0] n_tm2di_dpar;
reg [15:0] n_tm2di_bmask;
reg [127:0] data_pattern;
reg [3:0] dpar_pattern;
reg [127:0] f_vdb_data;
reg [127:0] m_vdb_data;
wire [127:0] l_vdb_data;
reg [4:0] f_vdb_dpar;
reg [4:0] m_vdb_dpar;
reg [15:0] f_vdb_bmask;
reg [15:0] m_vdb_bmask;
reg [15:0] l_vdb_bmask;
// ~~~~~~~~~~~~~~~~~~~~~~~~~ NETS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wire [127:0] only_vdb_data;
wire [4:0] l_vdb_dpar;
wire [4:0] only_vdb_dpar;
wire [15:0] only_vdb_bmask;
wire calc_parity;
wire n_msi_parity_err;
wire [3:0] first_dwbe; // bit swap of first_dwbe_dp
wire [3:0] last_dwbe; // bit swap of last_dwbe_dp
// >>>>>>>>>>>>>>>>>>>>>>>>> Function Declarations <<<<<<<<<<<<<<<<<<<<<<<<<<
function calc_dpar_bit; // odd parity
input [15:0] data;
begin
calc_dpar_bit = ~(^data[15:0]);
end
endfunction // calc_dpar_bit
// >>>>>>>>>>>>>>>>>>>>>>>>> RTL/Behavioral Model <<<<<<<<<<<<<<<<<<<<<<<<<<<
//------------------------------------------------------------------------
// bit swap of first_dwbe_dp and last_dwbe_dp
// set last_dwbe to 4'b1111 if payld_len_is_one_dp == 1'b1 for
// only_vdb_bmask formation, which is f_vdb_bmask & l_vdb_bmask
//------------------------------------------------------------------------
assign first_dwbe[3] = first_dwbe_dp[0];
assign first_dwbe[2] = first_dwbe_dp[1];
assign first_dwbe[1] = first_dwbe_dp[2];
assign first_dwbe[0] = first_dwbe_dp[3];
assign last_dwbe[3] = payld_len_is_one_dp ? 1'b1 : last_dwbe_dp[0];
assign last_dwbe[2] = payld_len_is_one_dp ? 1'b1 : last_dwbe_dp[1];
assign last_dwbe[1] = payld_len_is_one_dp ? 1'b1 : last_dwbe_dp[2];
assign last_dwbe[0] = payld_len_is_one_dp ? 1'b1 : last_dwbe_dp[3];
//------------------------------------------------------------------------
// parity check for first DW data and form tm2im_data
//------------------------------------------------------------------------
// calculate the first DW parity bit - odd parity
assign calc_parity = ~(^y2k_buf_data[127:96]);
assign n_msi_parity_err = (calc_parity ^ y2k_buf_dpar[3]); // fire uses odd parity
// MSI-X assign tm2im_data = {msi_parity_err, current_data[127:112]};
assign tm2im_data = {msi_parity_err, current_data[127:96]};
//------------------------------------------------------------------------
// form f_vdb_data, dpar and bmask
//------------------------------------------------------------------------
always @ (align_addr_dp or current_data or current_dpar or first_dwbe)
begin
case (align_addr_dp)
2'b00:
begin
f_vdb_data = current_data;
f_vdb_dpar[4:1] = current_dpar;
f_vdb_bmask = {first_dwbe, 12'hfff};
end
2'b01:
begin
f_vdb_data = {32'b0, current_data[127:32]};
f_vdb_dpar[4:1] = {1'b1, current_dpar[3:1]};
f_vdb_bmask = {4'b0, first_dwbe, 8'hff};
end
2'b10:
begin
f_vdb_data = {64'b0, current_data[127:64]};
f_vdb_dpar[4:1] = {2'b11, current_dpar[3:2]};
f_vdb_bmask = {8'b0, first_dwbe, 4'hf};
end
2'b11:
begin
f_vdb_data = {96'b0, current_data[127:96]};
f_vdb_dpar[4:1] = {3'b111, current_dpar[3]};
f_vdb_bmask = {12'b0, first_dwbe};
end
endcase // case(align_addr_low_dp)
f_vdb_dpar[0] = calc_dpar_bit(f_vdb_bmask); // odd parity bit for bmask
end
//------------------------------------------------------------------------
// form m_vdb_data, dpar and bmask
//------------------------------------------------------------------------
always @ (align_addr_dp or current_data or current_dpar or
saved_data or saved_dpar)
begin
m_vdb_dpar[0] = 1'b1; // because the bmask is 16'hffff
m_vdb_bmask = 16'hffff;
case (align_addr_dp)
2'b00:
begin
m_vdb_data = current_data;
m_vdb_dpar[4:1] = current_dpar;
end
2'b01:
begin
m_vdb_data = {saved_data[31:0], current_data[127:32]};
m_vdb_dpar[4:1] = {saved_dpar[0], current_dpar[3:1]};
end
2'b10:
begin
m_vdb_data = {saved_data[63:0], current_data[127:64]};
m_vdb_dpar[4:1] = {saved_dpar[1:0], current_dpar[3:2]};
end
2'b11:
begin
m_vdb_data = {saved_data[95:0], current_data[127:96]};
m_vdb_dpar[4:1] = {saved_dpar[2:0], current_dpar[3]};
end
endcase // case(align_addr_dp)
end
//------------------------------------------------------------------------
// mux out patterns for l_vdb_data, dpar[4:1] and only_vdb_data, dpar[4:1]
//------------------------------------------------------------------------
always @ (end_addr_dp)
begin
case (end_addr_dp)
2'b00:
begin
data_pattern = {{32{1'b1}}, {32{1'b1}}, {32{1'b1}}, {32{1'b1}}};
dpar_pattern = {1'b0, 1'b0, 1'b0, 1'b0};
end
2'b01:
begin
data_pattern = {{32{1'b1}}, 32'b0, 32'b0, 32'b0};
dpar_pattern = {1'b0, 1'b1, 1'b1, 1'b1};
end
2'b10:
begin
data_pattern = {{32{1'b1}}, {32{1'b1}}, 32'b0, 32'b0};
dpar_pattern = {1'b0, 1'b0, 1'b1, 1'b1};
end
2'b11:
begin
data_pattern = {{32{1'b1}}, {32{1'b1}}, {32{1'b1}}, 32'b0};
dpar_pattern = {1'b0, 1'b0, 1'b0, 1'b1};
end
endcase // case(end_addr_dp)
end
//------------------------------------------------------------------------
// form l_vdb_data, dpar and bmask
//------------------------------------------------------------------------
always @ (end_addr_dp or last_dwbe)
begin
case (end_addr_dp)
2'b00:
begin
l_vdb_bmask = {12'hfff, last_dwbe};
end
2'b01:
begin
l_vdb_bmask = {last_dwbe, 12'b0};
end
2'b10:
begin
l_vdb_bmask = {4'hf, last_dwbe, 8'b0};
end
2'b11:
begin
l_vdb_bmask = {8'hff, last_dwbe, 4'b0};
end
endcase // case(end_addr_dp)
end
assign l_vdb_dpar[0] = calc_dpar_bit(l_vdb_bmask); // parity bit for bmask
assign l_vdb_data = m_vdb_data & data_pattern;
assign l_vdb_dpar[4:1] = m_vdb_dpar[4:1] | dpar_pattern;
//------------------------------------------------------------------------
// form only_vdb_data, dpar and bmask
//------------------------------------------------------------------------
assign only_vdb_bmask = f_vdb_bmask & l_vdb_bmask;
assign only_vdb_data = f_vdb_data & data_pattern;
assign only_vdb_dpar[4:1] = f_vdb_dpar[4:1] | dpar_pattern;
assign only_vdb_dpar[0] = calc_dpar_bit(only_vdb_bmask);
//------------------------------------------------------------------------
// mux out from zero-fill, f_vdb, m_vdb, l_vdb, only_vdb
//------------------------------------------------------------------------
always @ (data_mux_select or
f_vdb_data or m_vdb_data or
l_vdb_data or only_vdb_data or
f_vdb_dpar or m_vdb_dpar or
l_vdb_dpar or only_vdb_dpar or
f_vdb_bmask or m_vdb_bmask or
l_vdb_bmask or only_vdb_bmask )
begin
n_tm2di_data = 128'b0;
n_tm2di_bmask = 16'b0;
n_tm2di_dpar = 5'b11111;
case (1'b1) // synopsys parallel_case
data_mux_select[ZERO_FILL]:
// 5'b10000: // zero-fill
begin
n_tm2di_data = 128'b0;
n_tm2di_bmask = 16'b0;
n_tm2di_dpar = 5'b11111;
end
data_mux_select[FRST_VDB]:
// 5'b01000: // f_vdb
begin
n_tm2di_data = f_vdb_data;
n_tm2di_bmask = f_vdb_bmask;
n_tm2di_dpar = f_vdb_dpar;
end
data_mux_select[MID_VDB]:
// 5'b00100: // m_vdb
begin
n_tm2di_data = m_vdb_data;
n_tm2di_bmask = m_vdb_bmask;
n_tm2di_dpar = m_vdb_dpar;
end
data_mux_select[LAST_VDB]:
// 5'b00010: // l_vdb
begin
n_tm2di_data = l_vdb_data;
n_tm2di_bmask = l_vdb_bmask;
n_tm2di_dpar = l_vdb_dpar;
end
data_mux_select[ONLY_VDB]:
// 5'b00001: // only_vdb
begin
n_tm2di_data = only_vdb_data;
n_tm2di_bmask = only_vdb_bmask;
n_tm2di_dpar = only_vdb_dpar;
end
endcase // case(1'b1)
end
//------------------------------------------------------------------------
// rptr to IDB
//------------------------------------------------------------------------
always @ (posedge clk)
if (!rst_l)
begin
k2y_buf_addr <= {`FIRE_DLC_ITI_ADDR_WDTH{1'b0}};
end
else if (idb_rptr_inc)
begin
k2y_buf_addr <= k2y_buf_addr + 1'b1;
end
//------------------------------------------------------------------------
// flops
//------------------------------------------------------------------------
always @ (posedge clk)
if(~rst_l) begin
current_data <= {128{1'b0}};
current_dpar <= {4{1'b0}};
saved_data <= {96{1'b0}};
saved_dpar <= {3{1'b0}};
msi_parity_err <= 1'b0;
tm2di_data <= {128{1'b0}};
tm2di_dpar <= {5{1'b0}};
tm2di_bmask <= {16{1'b0}};
end
else begin
current_data <= y2k_buf_data;
current_dpar <= y2k_buf_dpar;
if (ld_saved_data_dp) begin
saved_data <= current_data[95:0];
saved_dpar <= current_dpar[2:0];
end
msi_parity_err <= n_msi_parity_err;
tm2di_data <= n_tm2di_data;
tm2di_dpar <= n_tm2di_dpar;
tm2di_bmask <= n_tm2di_bmask;
end
// >>>>>>>>>>>>>>>>>>>>>>>>> Instantiations <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
endmodule // dmu_tmu_dim_datapath