// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: dmu_tmu_dim_datafsm.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 ============================================
module dmu_tmu_dim_datafsm (
y2k_buf_addr_vld_monitor,
//synopsys sync_set_reset "rst_l"
// >>>>>>>>>>>>>>>>>>>>>>>>> Parameter Declarations <<<<<<<<<<<<<<<<<<<<<<<<<
parameter // summit enum data_enum
// data_mux_select number
parameter DATA_MUX_NUM = 5;
// >>>>>>>>>>>>>>>>>>>>>>>>> Port Declarations <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//------------------------------------------------------------------------
// Clock and Reset Signals
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
output [`FIRE_DLC_TRD_ADDR_WDTH-1:0] tm2di_addr; // DIU address
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
output data_done; // to bufmgr.v also
//------------------------------------------------------------------------
//------------------------------------------------------------------------
input [`FIRE_DLC_DMA_WPTR_WDTH-2:0] diu_dma_cl_wptr;
input [`FIRE_DLC_PIO_WPTR_WDTH-2:0] diu_pio_cl_wptr;
//------------------------------------------------------------------------
//------------------------------------------------------------------------
input [7:0] payld_len; // only 8-bit due to max. MPS = 512B,
// the possible max. value is 8'b10000000.
//------------------------------------------------------------------------
//------------------------------------------------------------------------
output [DATA_MUX_NUM-1:0] data_mux_select;
output [3:0] first_dwbe_dp;
output [3:0] last_dwbe_dp;
output [3:2] align_addr_dp;
output [3:2] end_addr_dp;
output payld_len_is_one_dp;
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
input y2k_buf_addr_vld_monitor;
input [2:0] low_dbg_sel_a;
input [2:0] low_dbg_sel_b;
output [`FIRE_DBG_DATA_BITS] datafsm_dbg_a;
output [`FIRE_DBG_DATA_BITS] datafsm_dbg_b;
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> Data Type Declarations <<<<<<<<<<<<<<<<<<<<<<<<<
// ~~~~~~~~~~~~~~~~~~~~~~~~~ REGISTER - FLOPS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reg [3:0] first_dwbe_reg;
reg [5:2] align_addr_reg;
reg payld_len_is_one_reg;
reg [`FIRE_DLC_TRD_ADDR_WDTH-1:0] diu_wr_addr_ps1;
reg [DATA_MUX_NUM-1:0] data_mux_sel_ps1;
reg [`FIRE_DLC_TRD_ADDR_WDTH-1:0] diu_wr_addr_ps2;
reg [DATA_MUX_NUM-1:0] data_mux_sel_ps2;
reg [`FIRE_DLC_TRD_ADDR_WDTH-1:0] diu_wr_addr_ps3;
reg [3:0] first_dwbe_ps1;
reg [3:2] align_addr_ps1;
reg payld_len_is_one_ps1;
reg [3:0] first_dwbe_ps2;
reg [3:2] align_addr_ps2;
reg payld_len_is_one_ps2;
reg [STATE_NUM-1:0] data_state; // 0in one_hot
reg [`FIRE_DBG_DATA_BITS] dbg_bus [0:1];
// ~~~~~~~~~~~~~~~~~~~~~~~~~ REGISTER - NON-FLOPS ~~~~~~~~~~~~~~~~~~~~~~~~
reg [DATA_MUX_NUM-1:0] data_mux_sel_ne0 ;
reg [STATE_NUM-1:0] n_data_state;
reg [`FIRE_DBG_DATA_BITS] nxt_dbg_bus [0:1];
// ~~~~~~~~~~~~~~~~~~~~~~~~~ NETS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wire init_num_vd_wrs_inc;
wire [7:0] new_len_claligned; // possible max. value is 8'b10001111
wire [7:0] new_len_dwaligned; // possible max. value is 8'b10000011
wire [3:0] init_num_cls; // possible max. value is 4'b1001
wire [5:0] init_num_wrs; // possible max. value is 6'b100100
wire [5:0] init_num_rds; // possible max. value is 6'b100000
wire [5:0] init_num_vd_wrs; // possible max. value is 6'b100001
wire [5:2] align_addr_cur;
wire [`FIRE_DLC_TRD_ADDR_WDTH-1:0] diu_wr_addr_ne0;
wire [3:0] first_dwbe_ne0;
wire [3:0] last_dwbe_ne0;
wire [3:2] align_addr_ne0;
wire payld_len_is_one_ne0;
// >>>>>>>>>>>>>>>>>>>>>>>>> Zero In Checkers <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 0in bits_on -var data_mux_select -max 1
// 0in max -var new_len_claligned -val 8'b10001111 -active data_start
// 0in max -var new_len_dwaligned -val 8'b10000011 -active data_start
// 0in max -var init_num_cls -val 4'b1001 -active data_start
// 0in max -var init_num_wrs -val 6'b100100 -active data_start
// 0in max -var init_num_rds -val 6'b100000 -active data_start
// 0in max -var init_num_vd_wrs -val 6'b100001 -active data_start
/* 0in state -var data_state -val (8'b1 << IDLE) -next
/* 0in state -var data_state -val (8'b1 << MSI) -next
/* 0in state -var data_state -val (8'b1 << ZF_PRE_WR) -next
/* 0in state -var data_state -val (8'b1 << FRST_VD_WR) -next
/* 0in state -var data_state -val (8'b1 << MID_VD_WR) -next
/* 0in state -var data_state -val (8'b1 << LST_VD_WR) -next
/* 0in state -var data_state -val (8'b1 << ZF_PST_WR) -next
/* 0in state -var data_state -val (8'b1 << WAIT) -next
// >>>>>>>>>>>>>>>>>>>>>>>>> Function Declarations <<<<<<<<<<<<<<<<<<<<<<<<<<
function [STATE_NUM + DATA_MUX_NUM + 4 : 0] data_start_handling;
reg [STATE_NUM-1:0] n_state;
reg [DATA_MUX_NUM-1:0] data_mux_sel;
n_state = {STATE_NUM{1'b0}};
data_mux_sel = {DATA_MUX_NUM{1'b0}};
n_state[FRST_VD_WR] = 1'b1;
if (only_one_vd_wr) data_mux_sel[ONLY_VDB] = 1'b1;
else data_mux_sel[FRST_VDB] = 1'b1;
n_state[ZF_PRE_WR] = 1'b1;
data_mux_sel[ZERO_FILL] = 1'b1;
data_start_handling = {n_state, data_mux_sel, diu_wr_ne0,
msi_wr_ne0, idb_rptr_inc, diu_vd_wr_inc, data_done};
endfunction // data_start_handling
// >>>>>>>>>>>>>>>>>>>>>>>>> RTL/Behavioral Model <<<<<<<<<<<<<<<<<<<<<<<<<<<
//---------------------------------------------------------------------
//---------------------------------------------------------------------
assign rcd_is_cpld_cur = data_start ? rcd_is_cpld : rcd_is_cpld_reg;
// assign diu_cl_addr = rcd_is_cpld_cur ? {2'b10, diu_pio_cl_wptr[3:0]}
assign diu_cl_addr = rcd_is_cpld_cur ? {2'b10, 2'b00, diu_pio_cl_wptr[3:2]}
: {1'b0, diu_dma_cl_wptr[4:0]};
//---------------------------------------------------------------------
// computing some initial values
//---------------------------------------------------------------------
assign new_len_claligned = payld_len + {4'b0, align_addr};
assign end_addr = new_len_claligned[3:0];
assign {dw_carry, new_len_dwaligned[1:0]} = {1'b0, payld_len[1:0]} +
assign new_len_dwaligned[7:2] = dw_carry ? (payld_len[7:2] + 1'b1) :
assign init_num_cls_inc = |end_addr;
assign init_num_cls = init_num_cls_inc ? (new_len_claligned[7:4] + 1'b1) :
assign init_num_wrs = {init_num_cls, 2'b00};
assign init_num_rds_inc = |payld_len[1:0];
assign init_num_rds = init_num_rds_inc ? (payld_len[7:2] + 1'b1) :
assign init_num_vd_wrs_inc = |new_len_dwaligned[1:0];
assign init_num_vd_wrs = init_num_vd_wrs_inc ? (new_len_dwaligned[7:2] + 1'b1) :
//---------------------------------------------------------------------
// flops to lock data transfer rcd info
//---------------------------------------------------------------------
assign only_one_vd_wr = (~(|init_num_vd_wrs[5:1])) & init_num_vd_wrs[0];
assign payld_len_is_one = payld_len[0] & (~(|payld_len[7:1]));
only_one_vd_wr_reg <= 1'b0;
payld_len_is_one_reg <= 1'b0;
rcd_is_cpld_reg <= rcd_is_cpld;
align_addr_reg <= align_addr;
end_addr_reg <= end_addr[3:2];
first_dwbe_reg <= first_dwbe;
last_dwbe_reg <= last_dwbe;
only_one_vd_wr_reg <= only_one_vd_wr;
payld_len_is_one_reg <= payld_len_is_one;
//---------------------------------------------------------------------
// flops to keep track of data movement
//---------------------------------------------------------------------
if (data_start && ~rcd_is_cpld) begin
num_wrs <= init_num_wrs - 1'b1;
// else if (diu_wr_ne0) begin
else if (diu_wr_ne0 & ~rcd_is_cpld_cur) begin
num_wrs <= num_wrs - 1'b1;
if (idb_rptr_inc) num_rds <= init_num_rds - 1'b1;
else num_rds <= init_num_rds;
else if (idb_rptr_inc) num_rds <= num_rds - 1'b1;
if (diu_vd_wr_inc) num_vd_wrs <= init_num_vd_wrs - 1'b1;
else num_vd_wrs <= init_num_vd_wrs;
else if (diu_vd_wr_inc) num_vd_wrs <= num_vd_wrs - 1'b1;
// 2-bit LSB diu_addr_low which is appended to diu_cl_addr to form tm2di_addr
// else if (diu_wr_ne0) diu_addr_low <= diu_addr_low + 1'b1;
else if (diu_wr_ne0 & ~rcd_is_cpld_cur) diu_addr_low <= diu_addr_low + 1'b1;
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// summit state_vector data_state enum data_enum
data_state <= {STATE_NUM{1'b0}};
data_state[IDLE] <= 1'b1;
data_state <= n_data_state;
wire [1:0] diu_addr_low_2;
assign diu_addr_low_2 = rcd_is_cpld_cur ? diu_pio_cl_wptr[1:0] : diu_addr_low;
assign diu_wr_addr_ne0 = {diu_cl_addr, diu_addr_low_2};
assign diu_no_space = (~rcd_is_cpld_reg) & diu_dma_full;
assign align_addr_cur = data_start ? align_addr : align_addr_reg;
assign frst_vd_wr = (align_addr_cur[5:4] == diu_addr_low);
assign last_vd_wr = (~(|num_vd_wrs[5:1])) & num_vd_wrs[0];
assign more_vd_wrs = |num_vd_wrs;
assign last_wr = (~(|num_wrs[5:1])) & num_wrs[0];
assign more_wrs = |num_wrs;
assign more_rds = |num_rds;
assign only_one_rd = (~(|init_num_rds[5:1])) & init_num_rds[0];
assign last_rd = (~(|num_rds[5:1])) & num_rds[0];
assign end_of_cl = ~(|diu_addr_low);
always @ (data_state or data_start or diu_no_space or
rcd_is_msi or only_one_vd_wr or only_one_vd_wr_reg or
frst_vd_wr or last_vd_wr or more_vd_wrs or
last_wr or more_wrs or more_rds or
only_one_rd or last_rd or end_of_cl or rcd_is_cpld_cur )
n_data_state = {STATE_NUM{1'b0}};
data_mux_sel_ne0 = {DATA_MUX_NUM{1'b0}};
case (1'b1) // 0in < case -parallel -full // synopsys parallel_case
data_done} = data_start_handling (rcd_is_msi,
else n_data_state[IDLE] = 1'b1;
n_data_state[IDLE] = 1'b1;
else n_data_state[MSI] = 1'b1;
n_data_state[FRST_VD_WR] = 1'b1;
if (only_one_vd_wr_reg) data_mux_sel_ne0[ONLY_VDB] = 1'b1;
else data_mux_sel_ne0[FRST_VDB] = 1'b1;
n_data_state[ZF_PRE_WR] = 1'b1;
data_mux_sel_ne0[ZERO_FILL] = 1'b1;
data_done} = data_start_handling (rcd_is_msi,
if (more_wrs & end_of_cl & diu_no_space) begin
n_data_state[WAIT] = 1'b1;
n_data_state[LST_VD_WR] = 1'b1;
data_mux_sel_ne0[LAST_VDB] = 1'b1;
n_data_state[MID_VD_WR] = 1'b1;
data_mux_sel_ne0[MID_VDB] = 1'b1;
// else if (more_wrs) begin
else if (more_wrs && ~rcd_is_cpld_cur) begin
n_data_state[ZF_PST_WR] = 1'b1;
data_mux_sel_ne0[ZERO_FILL] = 1'b1;
// n_data_state[IDLE] = 1'b1;
else if (rcd_is_cpld_cur) begin
n_data_state[IDLE] = 1'b1;
n_data_state[IDLE] = 1'b1;
end // else: !if(data_start)
end // case: data_state[FRST_VD_WR]
if (end_of_cl & diu_no_space) begin
n_data_state[WAIT] = 1'b1;
n_data_state[LST_VD_WR] = 1'b1;
data_mux_sel_ne0[LAST_VDB] = 1'b1;
n_data_state[MID_VD_WR] = 1'b1;
data_mux_sel_ne0[MID_VDB] = 1'b1;
data_done} = data_start_handling (rcd_is_msi,
n_data_state[ZF_PST_WR] = 1'b1;
data_mux_sel_ne0[ZERO_FILL] = 1'b1;
n_data_state[IDLE] = 1'b1;
data_done} = data_start_handling (rcd_is_msi,
n_data_state[ZF_PST_WR] = 1'b1;
data_mux_sel_ne0[ZERO_FILL] = 1'b1;
n_data_state[IDLE] = 1'b1;
n_data_state[WAIT] = 1'b1;
n_data_state[LST_VD_WR] = 1'b1;
data_mux_sel_ne0[LAST_VDB] = 1'b1;
n_data_state[MID_VD_WR] = 1'b1;
data_mux_sel_ne0[MID_VDB] = 1'b1;
end // always @ (data_state or data_start or diu_no_space or...
//---------------------------------------------------------------------
//---------------------------------------------------------------------
diu_wr_addr_ps1 <= {`FIRE_DLC_TRD_ADDR_WDTH{1'b0}};
data_mux_sel_ps1 <= {DATA_MUX_NUM{1'b0}};
diu_wr_addr_ps2 <= {`FIRE_DLC_TRD_ADDR_WDTH{1'b0}};
data_mux_sel_ps2 <= {DATA_MUX_NUM{1'b0}};
diu_wr_addr_ps3 <= {`FIRE_DLC_TRD_ADDR_WDTH{1'b0}};
//BP n2 6-24-04 only 1 write for PIO's now, n2 limits PIO's to 16 bytes
// diu_wr_ps1 <= diu_wr_ne0;
diu_wr_ps1 <= (diu_wr_ne0 && ~rcd_is_cpld_cur) | (rcd_is_cpld_cur & data_start);
msi_wr_ps1 <= msi_wr_ne0;
diu_wr_addr_ps1 <= diu_wr_addr_ne0;
data_mux_sel_ps1 <= data_mux_sel_ne0;
diu_wr_ps2 <= diu_wr_ps1;
msi_wr_ps2 <= msi_wr_ps1;
diu_wr_addr_ps2 <= diu_wr_addr_ps1;
data_mux_sel_ps2 <= data_mux_sel_ps1;
diu_wr_ps3 <= diu_wr_ps2;
diu_wr_addr_ps3 <= diu_wr_addr_ps2;
assign first_dwbe_ne0 = data_start ? first_dwbe : first_dwbe_reg;
assign last_dwbe_ne0 = data_start ? last_dwbe : last_dwbe_reg;
assign align_addr_ne0 = align_addr_cur[3:2];
assign end_addr_ne0 = data_start ? end_addr[3:2] : end_addr_reg;
assign payld_len_is_one_ne0 = data_start ? payld_len_is_one : payld_len_is_one_reg;
assign ld_saved_data_ne0 = ~n_data_state[WAIT];
payld_len_is_one_ps1 <= 1'b0;
ld_saved_data_ps1 <= 1'b0;
payld_len_is_one_ps2 <= 1'b0;
ld_saved_data_ps2 <= 1'b0;
first_dwbe_ps1 <= first_dwbe_ne0;
last_dwbe_ps1 <= last_dwbe_ne0;
align_addr_ps1 <= align_addr_ne0;
end_addr_ps1 <= end_addr_ne0;
payld_len_is_one_ps1 <= payld_len_is_one_ne0;
ld_saved_data_ps1 <= ld_saved_data_ne0;
first_dwbe_ps2 <= first_dwbe_ps1;
last_dwbe_ps2 <= last_dwbe_ps1;
align_addr_ps2 <= align_addr_ps1;
end_addr_ps2 <= end_addr_ps1;
payld_len_is_one_ps2 <= payld_len_is_one_ps1;
ld_saved_data_ps2 <= ld_saved_data_ps1;
//---------------------------------------------------------------------
//---------------------------------------------------------------------
assign diu_cl_req = (diu_addr_low == 2'b01); // asserted at 2nd wr in a cache line
assign diu_cl_inc = (diu_addr_low == 2'b11); // asserted at 4th wr in a cache line
assign dma_cl_req = (~rcd_is_cpld_reg) & diu_cl_req;
assign dma_cl_inc = (~rcd_is_cpld_reg) & diu_cl_inc;
// assign pio_cl_inc = rcd_is_cpld_reg & diu_cl_inc;
assign pio_cl_inc = rcd_is_cpld & data_start;
assign tm2di_addr = diu_wr_addr_ps3;
assign tm2im_data_enq = msi_wr_ps2;
assign tm2di_wr = diu_wr_ps3;
assign data_mux_select = data_mux_sel_ps2;
assign align_addr_dp = align_addr_ps2;
assign end_addr_dp = end_addr_ps2;
assign first_dwbe_dp = first_dwbe_ps2;
assign last_dwbe_dp = last_dwbe_ps2;
assign payld_len_is_one_dp = payld_len_is_one_ps2;
assign ld_saved_data_dp = ld_saved_data_ps2;
//---------------------------------------------------------------------
//---------------------------------------------------------------------
always @ (low_dbg_sel_a or low_dbg_sel_b) begin
dbg_sel[0] = low_dbg_sel_a;
dbg_sel[1] = low_dbg_sel_b;
always @ (dbg_sel[0] or dbg_sel[1] or data_state or data_start
or data_done or diu_dma_full or idb_rptr_inc or diu_vd_wr_inc
or num_rds or num_wrs or num_vd_wrs or last_rd
or last_wr or more_rds or more_wrs or align_addr_cur
or rcd_is_cpld_cur or rcd_is_msi
or rel_type or k2y_rel_enq or y2k_buf_addr_vld_monitor)
for (i = 0; i < 2; i = i + 1) begin
case (dbg_sel[i]) // synopsys infer_mux
3'b000: nxt_dbg_bus[i] = data_state;
3'b001: nxt_dbg_bus[i] = {num_rds, last_rd, more_rds};
3'b010: nxt_dbg_bus[i] = {num_wrs, last_wr, more_wrs};
3'b011: nxt_dbg_bus[i] = {num_vd_wrs, data_start, data_done};
3'b100: nxt_dbg_bus[i] = {5'b0, idb_rptr_inc, diu_vd_wr_inc, diu_dma_full};
3'b101: nxt_dbg_bus[i] = {2'b0, align_addr_cur, rcd_is_cpld_cur, rcd_is_msi};
3'b110: nxt_dbg_bus[i] = {5'b0, y2k_buf_addr_vld_monitor, rel_type, k2y_rel_enq};
3'b111: nxt_dbg_bus[i] = 8'h00;
assign datafsm_dbg_a = dbg_bus[0];
assign datafsm_dbg_b = dbg_bus[1];
if(~rst_l) begin : dbg_rst
for (i = 0; i < 2; i = i + 1) begin
for (j = 0; j < 2; j = j + 1) begin
dbg_bus[j] <= nxt_dbg_bus[j];
//---------------------------------------------------------------------
//---------------------------------------------------------------------
assign datafsm_is_idle = data_state[IDLE];
// >>>>>>>>>>>>>>>>>>>>>>>>> Instantiations <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
endmodule // dmu_tmu_dim_datafsm