Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / dmu / rtl / dmu_rmu_lrm_itsb_fsm.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: dmu_rmu_lrm_itsb_fsm.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_rmu_lrm_itsb_fsm (
clk,
rst_l,
// TSB Interface - Ingress Pipeline
rm2ts_i_cmd_type,
rm2ts_i_wr_data,
rm2ts_i_req,
ts2rm_i_gnt,
ts2rm_i_n_trn,
// Internal LRM Output Control Interface - lrm_octl - Outgoing LRM rcd
lrm_rcd,
lrm_rcd_enq,
lrm_rcd_deq,
// Internal LRM Input Control Interface - lrm_ictl - Incoming STD rcd
std_rcd,
std_rcd_enq,
std_rcd_deq,
// Outputs (local) for Debug Port Visibility
trans_type,
sr_std_empty,
itsb_state,
lrm_credit_ok,
dma_rd_bcnt
);
// synopsys sync_set_reset "rst_l"
//############################################################################
// PORT DECLARATIONS
//############################################################################
//------------------------------------------------------------------------
// Clock and Reset Signals
//------------------------------------------------------------------------
input clk;
input rst_l;
//------------------------------------------------------------------------
// TSB Interface
//------------------------------------------------------------------------
// TSB interface (Ingress Pipeline)
output [`FIRE_DLC_TSR_CMD_TYPE_WDTH-1:0] rm2ts_i_cmd_type; // 4 bit TSB Command
output [`FIRE_DLC_TSR_WR_DATA_WDTH-1:0] rm2ts_i_wr_data; // 48 bit Write Data
output rm2ts_i_req;
input ts2rm_i_gnt;
input [`FIRE_DLC_TSR_TRN_WDTH-1:0] ts2rm_i_n_trn; // 5 bit TRN - Trans Scoreboard Tag
//------------------------------------------------------------------------
// Internal LRM Interface to LRM Output Control Module
//------------------------------------------------------------------------
output [`FIRE_DLC_RMU_LRM_WDTH-1:0] lrm_rcd;
output lrm_rcd_enq;
input lrm_rcd_deq; // LRM FIFO deq
//------------------------------------------------------------------------
// Internal LRM Interface to LRM Input Control Module
//------------------------------------------------------------------------
// Standard Records (other than rcd's destined to IMU or RRM)
// Note: STD Record defined identically as the IIN record
input [`FIRE_DLC_RMU_LRM_WDTH-1:0] std_rcd; // 131 bit Std Rcd
input std_rcd_enq; // Std Rcd FIFO Enqueue
output std_rcd_deq; // SR Std Rcd Dequeue
//------------------------------------------------------------------------
// Outputs for Debug Port Visibility
//------------------------------------------------------------------------
output [1:0] trans_type; // SR STD rcd trans type decoder
output sr_std_empty; // STD SR fifo is empty
output [4:0] itsb_state; // Ingress TSB 1-hot FSM
output lrm_credit_ok; // OK to enqueue LRM rcd
output [`FIRE_DLC_TSR_BYTECNT_WDTH:0] dma_rd_bcnt; // 13 bit bcnt calc [12:0] for dma_rd
//############################################################################
// PARAMETERS
//############################################################################
// Ingress Transaction Type Decoder Parameters
parameter
SEND2OCTL = 2'b00, // Send Record Up Pipeline
NP_DMA_TSB = 2'b01, // DMA Rd transaction requiring TSB access
NP_UR_TSB = 2'b10, // Unsupported Request requiring TSB access
UNDEFINED = 2'b11; // undefined type
parameter
DMA_MRD32 = 7'b0000000, // NP_DMA_TSB class
DMA_MRD64 = 7'b0100000, // NP_DMA_TSB class
DMA_MRDLK32 = 7'b0000001, // NP_DMA_TSB class
DMA_MRDLK64 = 7'b0100001, // NP_DMA_TSB class
DMA_UR = 7'b0001001, // NP_DMA_TSB class
DMA_MWR32 = 7'b1000000, // will send straight to MMU
DMA_MWR64 = 7'b1100000, // will send straight to MMU
// MSI_EQWR_32 = 7'b1011000, // should not be seen in this module
// MSI_EQWR_64 = 7'b1111000, // should not be seen in this module
// MSG_EQWR_32 = 7'b1010000, // should not be seen in this module
// MSG_EQWR_64 = 7'b1110000, // should not be seen in this module
// NULL = 7'b1111100, // should not be seen in this module
// MONDO = 7'b1111010, // should not be seen in this module
PIO_CPLD = 7'b1001010, // will send straight to MMU
PIO_CPL = 7'b0001010; // will send straight to MMU
// Ingress Transaction Scoreboard Parameters
parameter
TRN_REQ_WR = 4'b0101; // TSB command - Request TRN and Write Data to TRN addr
// LRM Ingress TSB Finite State Machine Parameters
parameter
I_PROCESS = 0, // FSM ready to process STD records (PIO's, Posted DMA's -DMAWRs)
I_LDPIPE = 1, // TSB Write Access in progress - Load Pipeline, DEQ next STD rcd
I_ENQPIPE = 2, // Complete TSB access and ENQ LRM Rcd - check if another TSB access
I_STALL1 = 3, // No lrm_credits while accessing TSB - finish TSB and chk credit
I_STALL2 = 4; // Pipelined TSB access completed, but had no credits - ENQ when OK!
parameter
NUM_STATES = 5;
// LRM Record FIFO Parameters Width = 123, Depth = 5
parameter
STD_SR_WIDTH = `FIRE_DLC_RMU_LRM_WDTH, // 131 bits
STD_SR_DEPTH = 4; // 4 deep
//############################################################################
// SIGNAL DECLARATIONS
//############################################################################
// Only (1) type of TSB command supported from Ingress Path - TRN Request w Write
wire [`FIRE_DLC_TSR_CMD_TYPE_WDTH-1:0] rm2ts_i_cmd_type; // 4 bit TSB Command
//**************************************************
// Internal Sub-Block Wires
//**************************************************
// Incoming STD Record fields out of the SR fifo - 131 bit STD record
wire [`FIRE_DLC_RMU_LRM_WDTH-1:0] sr_std_dout; // Entire STD-LRM Record
wire [`FIRE_DLC_RMU_LRM_TYPE_WDTH-1:0] sr_std_type; // 7 bit Type Field
wire [`FIRE_DLC_RMU_LRM_TC_WDTH-1:0] sr_std_tc; // 3 bit TC field
wire [`FIRE_DLC_RMU_LRM_ATR_WDTH-1:0] sr_std_atr; // 2 bit Atr field
wire [`FIRE_DLC_RMU_LRM_LEN_WDTH-1:0] sr_std_len; // 10 bit Length
wire [`FIRE_DLC_RMU_LRM_REQID_WDTH-1:0] sr_std_reqid; // 16 bit Reqid
wire [`FIRE_DLC_RMU_LRM_TAG_WDTH-1:0] sr_std_tag; // 8 bit tlptag
wire [`FIRE_DLC_RMU_LRM_LDWBE_WDTH-1:0] sr_std_ldwbe; // 4 bit last DWBE
wire [`FIRE_DLC_RMU_LRM_FDWBE_WDTH-1:0] sr_std_fdwbe; // 4 bit first DWBE
wire [`FIRE_DLC_RMU_LRM_ADDR_WDTH-1:0] sr_std_addr; // 62 bit Addr
wire [`FIRE_DLC_RMU_LRM_DPTR_WDTH-1:0] sr_std_dptr; // 7 bit Data Pointer
wire [`FIRE_DLC_RMU_LRM_LRMTAG_WDTH-1:0] sr_std_lrmtag; // 8 bit sbdtag
wire lrm_credit_ok; // OK to enqueue LRM rcd
wire sr_std_empty; // STD SR fifo is empty
wire [`FIRE_DLC_RMU_LRM_WDTH-1:0] std_lrm_rcd; // concatenation of entire std_dout rcd
wire [`FIRE_DLC_RMU_LRM_WDTH-1:0] tsb_lrm_rcd; // concatenation of entire pipelined rcd
// Fields Used for TSB byte count and lower addr calculations
wire [`FIRE_DLC_TSR_BYTECNT_WDTH-1:0] tsb_bcnt; // 12 bit bcnt written to TSB
wire [`FIRE_DLC_TSR_BYTECNT_WDTH:0] dma_rd_bcnt; // 13 bit bcnt calc [12:0] for dma_rd
wire [`FIRE_DLC_TSR_BYTECNT_WDTH:0] dma_rd_bcnt_mult_dws; // 13 bit bcnt calc [12:0] for multi dw
wire [`FIRE_DLC_TSR_BYTECNT_WDTH:0] dma_rd_len_total_bc; // 13 bit bcnt calc [12:0] from pkt LEN
// before bytes subtracted from BE's
wire [`FIRE_DLC_TSR_ADALIGN_WDTH-1:0] tsb_lower_addr; // 7 bit address
wire [`FIRE_DLC_TSR_ADALIGN_WDTH-1:0] dma_rd_addr; // 7 bit address
wire [`FIRE_DLC_TSR_WR_DATA_WDTH-1:0] next_tsb_write_data; // 48 bit tsb wr data
wire [2:0] total_bytes_off; // 3 bit temporary adder for bcnt calc
wire [1:0] dma_rd_lower_addr; // 2 bit byte aligned lower addr from DMA RD
wire dma_rd_len_eq_dw; // DMA Rd LEN == 1 DW
wire dma_rd_len_fourk; // DMA Rd LEN == 0's -> so 4K!
// Miscellaneous Wires
wire tsb_vld; // transaction type requiring TSB access
wire tsb_lrm_rcd_sel; // Registered lrm rcd mux select
wire ld_tsb_pipe_reg; // Load tsb_lrm_reg's from sr_std_dout
wire ld_tsb_sbdtag_reg; // Load tsb trn tag into upbound LRM rcd
wire [`FIRE_DLC_TSR_TRN_WDTH-1:0] tsb_lrm_sbdtag; // Muxed Output for the 5 bit TSB tag
//**************************************************
// Registers that Are Not Flops
//**************************************************
reg [1:0] trans_type; // SR STD rcd trans type decoder
reg std_rcd_deq; // SR STD rcd dequeue signal
reg lrm_rcd_enq; // LRM rcd enqueue signal
reg ld_tsb_wr_data; // Load Enable for TSB WR data
// Signals used to help calculate DMA RD byte count for TSB accesses
reg [1:0] bytes_off_frst_dwbe; // Bytes to be subtracted from FDWBE
reg [1:0] bytes_off_last_dwbe; // Bytes to be subtracted from LDWBE
reg [2:0] dma_rd_bcnt_one_dw; // Value is 1,2,3 or 4
//**************************************************
// Registers that Are Flops
//**************************************************
// LRM Ingress TSB FSM 1-hot state machine
reg [NUM_STATES-1:0] itsb_state, next_itsb_state; // 1-hot FSM
// Registered TSB Outputs
reg [`FIRE_DLC_TSR_WR_DATA_WDTH-1:0] rm2ts_i_wr_data; // 48 bit Write Data
reg rm2ts_i_req, next_rm2ts_i_req; // TSB Request Signal
// LRM FIFO credit mechanism - STD rcd and LRM rcd FIFO's sized to depth of 4
reg [2:0] lrm_credit_count, next_lrm_credit_count; // 3 bit credit count
// tsb_lrm_reg's - Pipelined registers fro STD rcd's that need TSB access - allows streaming
reg [`FIRE_DLC_RMU_LRM_TYPE_WDTH-1:0] tsb_reg_type; // 7 bit Type Field
reg [`FIRE_DLC_RMU_LRM_TC_WDTH-1:0] tsb_reg_tc; // 3 bit TC field
reg [`FIRE_DLC_RMU_LRM_ATR_WDTH-1:0] tsb_reg_atr; // 2 bit Atr field
reg [`FIRE_DLC_RMU_LRM_LEN_WDTH-1:0] tsb_reg_len; // 10 bit Length
reg [`FIRE_DLC_RMU_LRM_REQID_WDTH-1:0] tsb_reg_reqid; // 16 bit Reqid
reg [`FIRE_DLC_RMU_LRM_LDWBE_WDTH-1:0] tsb_reg_ldwbe; // 4 bit last DWBE
reg [`FIRE_DLC_RMU_LRM_FDWBE_WDTH-1:0] tsb_reg_fdwbe; // 4 bit first DWBE
reg [`FIRE_DLC_RMU_LRM_ADDR_WDTH-1:0] tsb_reg_addr; // 62 bit Addr
reg [`FIRE_DLC_RMU_LRM_DPTR_WDTH-1:0] tsb_reg_dptr; // 7 bit Data Pointer
reg [`FIRE_DLC_RMU_LRM_LRMTAG_WDTH-1:0] tsb_reg_lrmtag; // 8 bit sbdtag
reg [`FIRE_DLC_TSR_TRN_WDTH-1:0] tsb_reg_sbdtag; // 5 bit TSB index tag
// 123 registers total
//############################################################################
// ZERO IN CHECKERS
//############################################################################
/* 0in state -var itsb_state
-val (5'b00001 << I_PROCESS)
-next (5'b00001 << I_LDPIPE)
*/
/* 0in state -var itsb_state
-val (5'b00001 << I_LDPIPE)
-next (5'b00001 << I_ENQPIPE)
(5'b00001 << I_STALL1)
*/
/* 0in state -var itsb_state
-val (5'b00001 << I_ENQPIPE)
-next (5'b00001 << I_LDPIPE)
(5'b00001 << I_PROCESS)
*/
/* 0in state -var itsb_state
-val (5'b00001 << I_STALL1)
-next (5'b00001 << I_STALL2)
(5'b00001 << I_LDPIPE)
(5'b00001 << I_PROCESS)
*/
/* 0in state -var itsb_state
-val (5'b00001 << I_STALL2)
-next (5'b00001 << I_LDPIPE)
(5'b00001 << I_PROCESS)
*/
// 0in one_hot -var itsb_state
// 0in maximum -var lrm_credit_count -val 4
// 0in maximum -var trans_type -val 2
// Other POTENTIAL areas for Zero In
// make sure rm2ts_wr_data doesnt change while rm2ts_req asserted
/* 0in constant -var rm2ts_i_wr_data
-active ts2rm_i_gnt
*/
//############################################################################
// COMBINATIONAL LOGIC
//############################################################################
// Only (1) type of TSB command supported from Ingress Path - TRN Request w Write
assign rm2ts_i_cmd_type = TRN_REQ_WR; // TSB Command - TRN request w write
//---------------------------------------------------------------------------
// Outgoing LRM record to LRM Output Control Module
//---------------------------------------------------------------------------
assign lrm_rcd = tsb_lrm_rcd_sel ? tsb_lrm_rcd : std_lrm_rcd;
assign std_lrm_rcd = {
sr_std_type,
sr_std_tc,
sr_std_atr,
sr_std_len,
sr_std_reqid,
sr_std_tag,
sr_std_ldwbe,
sr_std_fdwbe,
sr_std_addr,
sr_std_dptr,
sr_std_lrmtag
};
assign tsb_lrm_rcd = {
tsb_reg_type,
tsb_reg_tc,
tsb_reg_atr,
tsb_reg_len,
tsb_reg_reqid,
{3'b000, tsb_lrm_sbdtag},
tsb_reg_ldwbe,
tsb_reg_fdwbe,
tsb_reg_addr,
tsb_reg_dptr,
tsb_reg_lrmtag
};
// Transaction Scoreboard Tag - Only need to mux in the regsitered value if we have no upbound
// LRM credits - but had already initiated a pipelined TSB Wr w trn request
assign tsb_lrm_sbdtag = (itsb_state[I_STALL2]) ? tsb_reg_sbdtag : ts2rm_i_n_trn;
//---------------------------------------------------------------------------
// STD Record Fields used to define outgoing LRM Record
//---------------------------------------------------------------------------
assign sr_std_type = sr_std_dout[`FIRE_DLC_RMU_LRM_TYPE]; // 7 bit TYPE field
assign sr_std_tc = sr_std_dout[`FIRE_DLC_RMU_LRM_TC]; // 3 bit TC field
assign sr_std_atr = sr_std_dout[`FIRE_DLC_RMU_LRM_ATR]; // 2 bit TYPE field
assign sr_std_len = sr_std_dout[`FIRE_DLC_RMU_LRM_LEN]; // 10 bit Length
assign sr_std_reqid = sr_std_dout[`FIRE_DLC_RMU_LRM_REQID]; // 16 bit Reqid
assign sr_std_tag = sr_std_dout[`FIRE_DLC_RMU_LRM_TAG]; // 8 bit tlptag
assign sr_std_ldwbe = sr_std_dout[`FIRE_DLC_RMU_LRM_LDWBE]; // 4 bit last DWBE
assign sr_std_fdwbe = sr_std_dout[`FIRE_DLC_RMU_LRM_FDWBE]; // 4 bit first DWBE
assign sr_std_addr = sr_std_dout[`FIRE_DLC_RMU_LRM_ADDR]; // 62 bit Addr
assign sr_std_dptr = sr_std_dout[`FIRE_DLC_RMU_LRM_DPTR]; // 7 bit Data Pointer
assign sr_std_lrmtag = sr_std_dout[`FIRE_DLC_RMU_LRM_LRMTAG];// 8 bit lrmtag
//---------------------------------------------------------------------------------
// Pipelined STD records that require TSB Access - Pipelined to Stream DMARds, UR's
//---------------------------------------------------------------------------------
always @ (posedge clk)
if(~rst_l) begin
tsb_reg_type <= {`FIRE_DLC_RMU_LRM_TYPE_WDTH{1'b0}};
tsb_reg_tc <= {`FIRE_DLC_RMU_LRM_TC_WDTH{1'b0}};
tsb_reg_atr <= {`FIRE_DLC_RMU_LRM_ATR_WDTH{1'b0}};
tsb_reg_len <= {`FIRE_DLC_RMU_LRM_LEN_WDTH{1'b0}};
tsb_reg_reqid <= {`FIRE_DLC_RMU_LRM_REQID_WDTH{1'b0}};
tsb_reg_ldwbe <= {`FIRE_DLC_RMU_LRM_LDWBE_WDTH{1'b0}};
tsb_reg_fdwbe <= {`FIRE_DLC_RMU_LRM_FDWBE_WDTH{1'b0}};
tsb_reg_addr <= {`FIRE_DLC_RMU_LRM_ADDR_WDTH{1'b0}};
tsb_reg_dptr <= {`FIRE_DLC_RMU_LRM_DPTR_WDTH{1'b0}};
tsb_reg_lrmtag <= {`FIRE_DLC_RMU_LRM_LRMTAG_WDTH{1'b0}};
end
else if (ld_tsb_pipe_reg)
begin
tsb_reg_type <= sr_std_type;
tsb_reg_tc <= sr_std_tc;
tsb_reg_atr <= sr_std_atr;
tsb_reg_len <= sr_std_len;
tsb_reg_reqid <= sr_std_reqid;
tsb_reg_ldwbe <= sr_std_ldwbe;
tsb_reg_fdwbe <= sr_std_fdwbe;
tsb_reg_addr <= sr_std_addr;
tsb_reg_dptr <= sr_std_dptr;
tsb_reg_lrmtag <= sr_std_lrmtag;
end
else
begin
tsb_reg_type <= tsb_reg_type;
tsb_reg_tc <= tsb_reg_tc;
tsb_reg_atr <= tsb_reg_atr;
tsb_reg_len <= tsb_reg_len;
tsb_reg_reqid <= tsb_reg_reqid;
tsb_reg_ldwbe <= tsb_reg_ldwbe;
tsb_reg_fdwbe <= tsb_reg_fdwbe;
tsb_reg_addr <= tsb_reg_addr;
tsb_reg_dptr <= tsb_reg_dptr;
tsb_reg_lrmtag <= tsb_reg_lrmtag;
end
// Register TSB index for LRM record - the TSB access may complete before having credits
// to enqueue up to the LRM - safe bet is to register the value so next TSB trn is not
// muxed into LRM record
always @ (posedge clk)
if(~rst_l) begin
tsb_reg_sbdtag <= {`FIRE_DLC_TSR_TRN_WDTH{1'b0}};
end
else if (ld_tsb_sbdtag_reg)
tsb_reg_sbdtag <= ts2rm_i_n_trn;
else
tsb_reg_sbdtag <= tsb_reg_sbdtag;
//--------------------------------------
// Ingress LRM Record Type Decoder Logic
//--------------------------------------
// Note: Should NEVER see a MSG, MSI, Mondo or Null IN THIS MODULE - they should have been
// forked off to the IMU... and then passed back up to the lrm_octl module where they
// are merged back into the Ingress pipeline
always @ (sr_std_type or sr_std_empty)
begin
if (sr_std_empty)
trans_type = SEND2OCTL;
else
case (sr_std_type) // 0in < case -default
DMA_MRD32 : trans_type = NP_DMA_TSB;
DMA_MRD64 : trans_type = NP_DMA_TSB;
DMA_MRDLK32 : trans_type = NP_DMA_TSB;
DMA_MRDLK64 : trans_type = NP_DMA_TSB;
DMA_UR : trans_type = NP_UR_TSB;
DMA_MWR32 : trans_type = SEND2OCTL;
DMA_MWR64 : trans_type = SEND2OCTL;
PIO_CPLD : trans_type = SEND2OCTL;
PIO_CPL : trans_type = SEND2OCTL;
// Zero In Check for INVALID transaction type if FIFO is not empty
default : trans_type = UNDEFINED;
endcase // case
end // always
//----------------------------------------------------------------------
// Signal that indicates that there is room for LRM rcd - ok to Enqueue
//----------------------------------------------------------------------
assign lrm_credit_ok = |lrm_credit_count; // If Credit is 1-4, then OK!!
// If Credit is 0 - NOT ok! LRM SR full
//############################################################################
// SEQUENTIAL LOGIC
//############################################################################
//------------------------
// TSB request register
//------------------------
always @ (posedge clk)
if (~rst_l)
rm2ts_i_req <= 1'b0;
else
rm2ts_i_req <= next_rm2ts_i_req;
//------------------------
// TSB write data register
//------------------------
always @ (posedge clk)
if (~rst_l)
rm2ts_i_wr_data <= {`FIRE_DLC_TSR_WR_DATA_WDTH{1'b0}};
else if (ld_tsb_wr_data)
rm2ts_i_wr_data <= next_tsb_write_data;
else
rm2ts_i_wr_data <= rm2ts_i_wr_data;
// Fields that make up the 48 bit TSB write data
assign next_tsb_write_data = {
sr_std_tc,
sr_std_atr,
tsb_bcnt,
sr_std_reqid,
sr_std_tag,
tsb_lower_addr
};
assign tsb_bcnt = (trans_type == NP_UR_TSB) ? 12'h4 : dma_rd_bcnt[`FIRE_DLC_TSR_BYTECNT_WDTH-1:0];
assign tsb_lower_addr = (trans_type == NP_UR_TSB) ? 7'h0 : dma_rd_addr;
// Note: IF len = 4K and NO BE's are subtracted from bcnt, all 0's will be written to TSB, the MSB
// or bit 13 of bcnt calculation does not get written to TSB, RRM must check for 4K length
//------------------------------------------------
// DMA Rd Byte Count Calculations for TSB accesses
//------------------------------------------------
// Note that ANY malformed packets WILL be trapped in the ILU - and that
// no additioanl checks need to performed in the RMU!
// Check to see if LEN = 1 DW... if so - then LDWBE's can be ignored - and BC = dma_rd_bcnt_one_dw
assign dma_rd_len_eq_dw = ~|sr_std_len[`FIRE_DLC_RMU_LRM_LEN_WDTH-1:1] & sr_std_len[0];
// Check to see if LEN = 0 DW... if so - then BCNT = 4K, dma_rd_bcnt = 12'h0;
assign dma_rd_len_fourk = ~|sr_std_len[`FIRE_DLC_RMU_LRM_LEN_WDTH-1:0];
// Calculate dma_rd_bcnt for the case when LEN IS exactly equal to 1 DW
always @ (sr_std_fdwbe)
begin
casez (sr_std_fdwbe) // 0in < case -parallel -full -active ~sr_std_empty
4'b1zz1 : dma_rd_bcnt_one_dw = 3'h4;
4'b01z1 : dma_rd_bcnt_one_dw = 3'h3;
4'b1z10 : dma_rd_bcnt_one_dw = 3'h3;
4'b0011 : dma_rd_bcnt_one_dw = 3'h2;
4'b0110 : dma_rd_bcnt_one_dw = 3'h2;
4'b1100 : dma_rd_bcnt_one_dw = 3'h2;
4'b0001 : dma_rd_bcnt_one_dw = 3'h1;
4'b0010 : dma_rd_bcnt_one_dw = 3'h1;
4'b0100 : dma_rd_bcnt_one_dw = 3'h1;
4'b1000 : dma_rd_bcnt_one_dw = 3'h1;
4'b0000 : dma_rd_bcnt_one_dw = 3'h1; // If ZERO byte DMA Rd - byte count = 1!
endcase
end
// Number of bytes off from 1st DWBE
always @ (sr_std_fdwbe)
begin
if (sr_std_fdwbe[0]) bytes_off_frst_dwbe = 2'b00;
else if (sr_std_fdwbe[1]) bytes_off_frst_dwbe = 2'b01;
else if (sr_std_fdwbe[2]) bytes_off_frst_dwbe = 2'b10;
else if (sr_std_fdwbe[3]) bytes_off_frst_dwbe = 2'b11;
else bytes_off_frst_dwbe = 2'b00;
end
// Number of bytes off from last DWBE
always @ (sr_std_ldwbe)
begin
if (sr_std_ldwbe[3]) bytes_off_last_dwbe = 2'b00;
else if (sr_std_ldwbe[2]) bytes_off_last_dwbe = 2'b01;
else if (sr_std_ldwbe[1]) bytes_off_last_dwbe = 2'b10;
else if (sr_std_ldwbe[0]) bytes_off_last_dwbe = 2'b11;
else bytes_off_last_dwbe = 2'b00;
end
assign total_bytes_off = {1'b0, bytes_off_frst_dwbe} + {1'b0, bytes_off_last_dwbe}; // 3-bit value (0-6)
// Calculate DMA Rd BCNT len for cases where the 10 bit LEN field is not a single DW
// NOTE: this calculation also holds for LEN==0, or 4K - all BE's will set,
// total bytes off will = 0 - therefore a value of 12'h0 will be written
// to TSB! Need to validate cases where LEN may == 0, but BE's not all set?
assign dma_rd_len_total_bc = {dma_rd_len_fourk, sr_std_len, 2'b00}; // 13 bit value
assign dma_rd_bcnt_mult_dws = dma_rd_len_total_bc - {10'h0, total_bytes_off}; // 13 bit value
assign dma_rd_bcnt = dma_rd_len_eq_dw ? {10'h0, dma_rd_bcnt_one_dw} : dma_rd_bcnt_mult_dws;
//----------------------------------------------------------
// DMA Lower Address Align Bit Calculations for TSB accesses
//----------------------------------------------------------
assign dma_rd_lower_addr = bytes_off_frst_dwbe; // 2 bit LSB addr
assign dma_rd_addr = {sr_std_addr[4:0], dma_rd_lower_addr}; // 7 bit field
//-------------------------------------------------
// LRM Ingress TSB State Machine Combinatorial Code
//-------------------------------------------------
// ttype of 0x01, 0x10 = NP_DMA, NP_UR respectively
assign tsb_vld = trans_type[1]^trans_type[0];
// Registered lrm rcd mux select
assign tsb_lrm_rcd_sel = (itsb_state[I_ENQPIPE] | itsb_state[I_STALL1] | itsb_state[I_STALL2]);
// Load tsb_lrm_reg's from sr_std_dout
assign ld_tsb_pipe_reg = itsb_state[I_LDPIPE];
// Load enable for TSB trn number for upbound LRM record
assign ld_tsb_sbdtag_reg = (itsb_state[I_STALL1]) & ts2rm_i_gnt;
//-----------------------------------------------
// LRM Ingress TSB State Machine Sequential Logic
//-----------------------------------------------
always @ (posedge clk)
if (~rst_l)
begin
itsb_state[NUM_STATES-1:0] <= {NUM_STATES{1'b0}};
itsb_state[I_PROCESS] <= 1'b1;
end
else
begin
itsb_state <= next_itsb_state;
end
// LRM Ingress TSB State Machine Combinatorial (Next State) Logic
always @ ( itsb_state or sr_std_empty or lrm_credit_ok or trans_type or ts2rm_i_gnt or tsb_vld )
begin
next_itsb_state = {NUM_STATES{1'b0}}; // Default FSM Output Values
std_rcd_deq = 1'b0;
lrm_rcd_enq = 1'b0;
ld_tsb_wr_data = 1'b0;
next_rm2ts_i_req = 1'b0;
case(1'b1) // synopsys parallel_case
// 0in < case -full
// I_PROCESS - Initial State
itsb_state[I_PROCESS] :
if (~sr_std_empty & lrm_credit_ok) // STD rcd ready to be processed
case(trans_type)
(SEND2OCTL) : // Send STD rcd up pipeline
begin
std_rcd_deq = 1'b1;
lrm_rcd_enq = 1'b1;
next_itsb_state[I_PROCESS] = 1'b1;
end
(NP_DMA_TSB), // STD rcd needs to be tracked on TSB
(NP_UR_TSB) :
begin
ld_tsb_wr_data = 1'b1;
next_rm2ts_i_req = 1'b1;
next_itsb_state[I_LDPIPE] = 1'b1;
end
endcase
else // STD rcd fifo empty - Keep Default Values
next_itsb_state[I_PROCESS] = 1'b1;
// I_LDPIPE - TSB Write Access in progress - Load Pipeline, DEQ next STD rcd and chk credit
itsb_state[I_LDPIPE] : // Pipline Load enable for NP record
begin
next_rm2ts_i_req = 1'b1; // Keep REQ asserted
std_rcd_deq = 1'b1; // Pipeline TSB rcd
if (lrm_credit_ok)
next_itsb_state[I_ENQPIPE] = 1'b1; // Complete TSB access and ENQ LRM Rcd
else
next_itsb_state[I_STALL1] = 1'b1; // NO upbound credit - STALL pipeline
end
// I_ENQPIPE - Complete TSB access and ENQ LRM Rcd - check if another TSB access
itsb_state[I_ENQPIPE] : // LRM output rcd mux select -> tsb_lrm_rcd
case({ts2rm_i_gnt, tsb_vld}) // 0in < case -parallel -full
(2'b00), // Wait for GNT to complete
(2'b01) : // Keeping REQ asserted
begin
next_rm2ts_i_req = 1'b1;
next_itsb_state[I_ENQPIPE] = 1'b1;
end
(2'b10) : // TSB access complete, ENQ LRM rcd
begin // since no more TSB accesses required
lrm_rcd_enq = 1'b1; // just return to PROCESS state
next_itsb_state[I_PROCESS] = 1'b1;
end
(2'b11) : // TSB access completed, ENQ LRM rcd
begin // and continue to stream NP DMA's
lrm_rcd_enq = 1'b1;
ld_tsb_wr_data = 1'b1;
next_rm2ts_i_req = 1'b1;
next_itsb_state[I_LDPIPE] = 1'b1;
end
endcase
// I_STALL1 - No lrm_credits while accessing TSB - finish TSB and chk credit
itsb_state[I_STALL1] : // LRM output rcd mux select -> tsb_lrm_rcd
case({ts2rm_i_gnt, lrm_credit_ok}) // 0in < case -parallel -full
(2'b00),
(2'b01) :
begin
next_rm2ts_i_req = 1'b1; // credit freed up before GNT
next_itsb_state[I_STALL1] = 1'b1; // need to wait for credit_ok
end
(2'b10) :
begin
next_itsb_state[I_STALL2] = 1'b1; // deassert REQ - but wait for credit
end
(2'b11) :
begin // TSB completed and have credit!
lrm_rcd_enq = 1'b1; // ENQ lrm rcd!, deassert req
if (tsb_vld) // Another NP_DMA or NP_UR ready for TSB
begin
ld_tsb_wr_data = 1'b1;
next_rm2ts_i_req = 1'b1;
next_itsb_state[I_LDPIPE] = 1'b1; // Stream out Non Posted DMA's
end
else
begin
next_itsb_state[I_PROCESS] = 1'b1; // Either fifo empty or
end
end
endcase
// I_STALL2 - Pipelined TSB access completed, but had no credits - ENQ when OK!
itsb_state[I_STALL2] : // LRM output rcd mux select -> tsb_lrm_rcd
case({lrm_credit_ok, tsb_vld}) // 0in < case -parallel -full
(2'b00),
(2'b01) :
begin
next_itsb_state[I_STALL2] = 1'b1; // need to wait for credit_ok
end
(2'b10) :
begin
lrm_rcd_enq = 1'b1; // OK to ENQ LRM Rcd - no more TSB cycles
next_itsb_state[I_PROCESS] = 1'b1;
end
(2'b11) :
begin // Have credit!, and Another TSB access
lrm_rcd_enq = 1'b1; // ENQ lrm rcd!, deassert req
ld_tsb_wr_data = 1'b1;
next_rm2ts_i_req = 1'b1;
next_itsb_state[I_LDPIPE] = 1'b1;
end
endcase
endcase // ends itsb_state case FSM
end // ends combinatorial always block for i_fsm state machine
//--------------------------------------------------------------------------------------------
// LRM rcd Credit Counter - Establishes whether there is credit to Enqueue LRM rcd to lrm_octl
//--------------------------------------------------------------------------------------------
always @ (posedge clk)
if (~rst_l)
lrm_credit_count <= 3'b100; // Initially sized to LRM FIFO Depth - 5
else
lrm_credit_count <= next_lrm_credit_count;
always @ (lrm_rcd_enq or lrm_rcd_deq or lrm_credit_count)
begin // Combinatorial next_lrm_credit_count logic
next_lrm_credit_count = 3'b000; // Just for initialization
case ({lrm_rcd_deq, lrm_rcd_enq}) // synopsys infer_mux
(2'b01) : // Enqueueing LRM record
next_lrm_credit_count = lrm_credit_count - 1'b1; // Decrement LRM credit
(2'b10) : // Dequeueing Record from LRM SR
next_lrm_credit_count = lrm_credit_count + 1'b1; // Increment LRM credit
(2'b00),
(2'b11) :
next_lrm_credit_count = lrm_credit_count; // Credit Count Remains the Same
endcase
end
//############################################################################
// MODULE INSTANTIATIONS
//############################################################################
//----------------------------------------------------
// STD Standard Record FIFO = 131 * 5 = 655 registers
// STD Standard Record FIFO = 131 * 4 = 524 registers
//----------------------------------------------------
fire_dmc_common_srfifo #(STD_SR_WIDTH, STD_SR_DEPTH) sr_std_fifo (
.clk (clk),
.rst_l (rst_l),
.enq (std_rcd_enq),
.data_in (std_rcd),
.deq (std_rcd_deq),
.data_out (sr_std_dout),
.full (),
.empty (sr_std_empty),
.overflow (),
.underflow ()
);
endmodule