Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / niu_rdmc_rcr_manager.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: niu_rdmc_rcr_manager.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 ============================================
/*************************************************************************
*
* File Name : niu_rdmc_rcr_manager.v
* Author Name : Jeanne Cai
* Description :
* Date Created : 07/18/2004
*
* Copyright (c) 2001, Sun Microsystems, Inc.
* Sun Proprietary and Confidential
*
*
*************************************************************************/
`include "niu_rdmc.h"
module niu_rdmc_rcr_manager (
clk,
reset,
clk_div_value,
dma_chnl_grp_id,
shadw_start_addr,
shadw_rd_end_addr,
shadw_wr_end_addr,
dma_en,
dma_reset,
page_valid0,
addr_mask0,
comp_value0,
relo_value0,
page_valid1,
addr_mask1,
comp_value1,
relo_value1,
dma_fatal_err,
rx_log_page_hdl_reg,
rcr_cfig_a_reg,
rcr_cfig_b_reg,
rx_dma_ctl_stat_reg,
rx_dma_ctl_stat_reg_bit47,
rcr_flush_reg,
mbox_addr,
rcr_cfig_a_reg_wenu,
rcr_cfig_a_reg_wenl,
rx_dma_ctl_stat_reg_wenu,
rx_dma_ctl_stat_reg_wenl,
chnl_sel_buf_en_r, //from niu_rdmc_buf_manager.v
pref_buf_used_num, //up to three for jumbo packets
wr_transfer_comp_int,
wr_last_pkt_data,
update_rcr_shadw, //from niu_rdmc_wr_sched.v, need chnl id
rdmc_wr_data_dma_num,
rcr_wrbk_gnt,
rcr_wrbk_done,
rcr_wrbk_pkt_num,
rdmc_rcr_ack_valid,
rdmc_rcr_ack_err,
rdmc_rcr_ack_dma_num,
shadw_parity_err,
shadw_wr_en,
shadw_wr_even,
shadw_wr_ptr,
shadw_rd_ptr,
rcr_wrbk_sched,
rcr_wrbk_req,
rcr_wrbk_addr,
rcr_wrbk_numb,
rcr_wrbk_data_type,
rcr_ack_accept,
rcr_curr_qlen,
shadw_curr_space_cnt,
reset_rcr_flush,
m_bit_en,
rcr_ctl_stat_word,
rcr_curr_addr,
rcr_status_a,
rcr_addr_not_valid,
mbox_addr_not_valid,
rcr_addr_overflow,
rcr_curr_cnt_overflow,
rcr_curr_cnt_underflow,
rcr_pkt_cnt_underflow,
rcr_idle_cycle,
rcr_ack_err,
chnl_has_pkt,
chnl_shadw_parity_err
);
input clk;
input reset;
input[15:0] clk_div_value;
input[4:0] dma_chnl_grp_id;
input[7:0] shadw_start_addr;
input[7:0] shadw_rd_end_addr;
input[7:0] shadw_wr_end_addr;
input dma_en;
input dma_reset;
input page_valid0;
input[31:0] addr_mask0;
input[31:0] comp_value0;
input[31:0] relo_value0;
input page_valid1;
input[31:0] addr_mask1;
input[31:0] comp_value1;
input[31:0] relo_value1;
input dma_fatal_err;
input[19:0] rx_log_page_hdl_reg;
input[53:0] rcr_cfig_a_reg;
input[22:0] rcr_cfig_b_reg;
input[31:0] rx_dma_ctl_stat_reg;
input rx_dma_ctl_stat_reg_bit47;
input rcr_flush_reg;
input[43:0] mbox_addr;
input rcr_cfig_a_reg_wenu;
input rcr_cfig_a_reg_wenl;
input rx_dma_ctl_stat_reg_wenu;
input rx_dma_ctl_stat_reg_wenl;
input chnl_sel_buf_en_r;
input[1:0] pref_buf_used_num;
input wr_transfer_comp_int;
input wr_last_pkt_data;
input update_rcr_shadw;
input[4:0] rdmc_wr_data_dma_num;
input rcr_wrbk_gnt;
input rcr_wrbk_done;
input[3:0] rcr_wrbk_pkt_num;
input rdmc_rcr_ack_valid;
input rdmc_rcr_ack_err;
input[4:0] rdmc_rcr_ack_dma_num;
input shadw_parity_err;
output shadw_wr_en;
output shadw_wr_even;
output[7:0] shadw_wr_ptr;
output[7:0] shadw_rd_ptr;
output rcr_wrbk_sched;
output rcr_wrbk_req;
output[63:0] rcr_wrbk_addr;
output[3:0] rcr_wrbk_numb;
output rcr_wrbk_data_type;
output rcr_ack_accept;
output[15:0] rcr_curr_qlen;
output[7:0] shadw_curr_space_cnt;
output reset_rcr_flush;
output m_bit_en;
output[2:0] rcr_ctl_stat_word;
output[15:0] rcr_curr_addr;
output[15:0] rcr_status_a;
output rcr_addr_not_valid;
output mbox_addr_not_valid;
output rcr_addr_overflow;
output rcr_curr_cnt_overflow;
output rcr_curr_cnt_underflow;
output rcr_pkt_cnt_underflow;
output rcr_idle_cycle;
output rcr_ack_err;
output chnl_has_pkt;
output chnl_shadw_parity_err;
reg rcr_cfig_a_reg_wenu_dly2;
reg rcr_cfig_a_reg_wenu_dly;
reg rcr_cfig_a_reg_wenl_dly2;
reg rcr_cfig_a_reg_wenl_dly;
reg rx_dma_ctl_stat_reg_wenu_dly;
reg rx_dma_ctl_stat_reg_wenl_dly;
reg[3:0] addr_cnt;
reg cal_addr_en;
reg[15:0] rcr_curr_addr_tmp;
reg[15:0] rcr_curr_addr;
reg dec_rcr_curr_cnt;
reg dec_rcr_curr_cnt_r;
reg[16:0] rcr_curr_cnt; //bit[16] is overflow bit
reg[3:0] rcr_wrbk_act_num;
reg[3:0] rcr_wrbk_numb;
reg[16:0] rcr_curr_pkt_cnt;
reg[3:0] rcr_wrbk_pkt_num_sav;
reg[3:0] rcr_wrbk_pkt_act_num;
reg[3:0] rcr_wrbk_pkt_num_r;
reg not_in_cacheline;
reg[43:0] rcr_relo_addr_r;
reg rcr_curr_cnt_overflow_r;
reg shadw_parity_err_r;
reg rcr_wrbk_data_type;
reg rcr_wrbk_req;
reg rcr_wrbk_sched;
reg rcr_wrbk_done_r;
reg rcr_wrbk_done_r1;
reg rcr_wrbk_ack_done;
reg rcr_wrbk_ack_done_r;
reg mbox_update_done;
reg rcr_ack_accept;
reg rcr_idle_cycle;
reg rcr_wrbk_req_sm;
reg mbox_req_sm;
reg rcr_wrbk_ack_done_sm;
reg mbox_update_done_sm;
reg rcr_ack_accept_sm;
reg reset_rcr_timer;
reg reset_m_bit;
reg[3:0] state;
reg[3:0] next_state;
reg shadw_wr_en;
reg[7:0] shadw_wr_ptr;
reg[7:0] shadw_rd_ptr;
reg inc_shadw_curr_cnt;
reg[7:0] shadw_curr_cnt;
reg[5:0] shadw_act_curr_cnt;
reg dec_shadw_space_cnt;
reg[7:0] shadw_curr_space_cnt;
reg chnl_has_pkt_s1;
reg chnl_has_pkt_s2;
reg timer_m_bit;
reg[15:0] clk_cnt;
reg[5:0] timeout_cnt;
reg rcr_timer_done_r;
reg rcr_timer_done_r_dly;
reg mbox_update_done_dly;
reg rcr_flush_reg_dly;
reg rcr_thresh_reg;
reg thresh_m_bit;
wire[2:0] rcr_ctl_stat_word;
wire[15:0] rcr_curr_qlen = rcr_curr_cnt[15:0];
//wire[17:0] rcr_status_a = {rcr_curr_cnt[16], rcr_curr_pkt_cnt[16:0]};
wire[15:0] rcr_status_a = rcr_curr_pkt_cnt[15:0];
wire rcr_ack_err = rdmc_rcr_ack_valid & rdmc_rcr_ack_err;
/**********************************************/
//PIO programmed parameters
/**********************************************/
reg[16:0] rcr_end_addr_r;
wire[15:0] rcr_max_len = rcr_cfig_a_reg[53:38];
wire[24:0] rcr_base_addr = rcr_cfig_a_reg[37:13];
wire[15:0] rcr_start_addr = {rcr_cfig_a_reg[12:0], 3'b0};
wire[15:0] rcr_end_addr = rcr_end_addr_r[15:0];
wire rcr_addr_overflow = rcr_end_addr_r[16] & dma_en;
wire[15:0] pkt_thresh = rcr_cfig_b_reg[22:7];
wire timeout_en = rcr_cfig_b_reg[6];
wire[5:0] timeout_value = rcr_cfig_b_reg[5:0];
wire[19:0] page_handle = rx_log_page_hdl_reg;
wire m_bit = rx_dma_ctl_stat_reg_bit47;
//wire rcr_thresh_bit = rx_dma_ctl_stat_reg[46];
//wire rcrto_bit = rx_dma_ctl_stat_reg[45];
wire[15:0] cpu_ptr_rd_num = rx_dma_ctl_stat_reg[31:16];
wire[15:0] cpu_pkt_rd_num = rx_dma_ctl_stat_reg[15:0];
/****************************/
//RCR Manager
/****************************/
always @ (posedge clk)
if (reset)
rcr_cfig_a_reg_wenu_dly <= 1'b0;
else if (dma_reset)
rcr_cfig_a_reg_wenu_dly <= 1'b0;
else if (rcr_cfig_a_reg_wenu)
rcr_cfig_a_reg_wenu_dly <= 1'b1;
else
rcr_cfig_a_reg_wenu_dly <= 1'b0;
always @ (posedge clk)
if (reset)
rcr_cfig_a_reg_wenu_dly2 <= 1'b0;
else
rcr_cfig_a_reg_wenu_dly2 <= rcr_cfig_a_reg_wenu_dly;
always @ (posedge clk)
if (reset)
rcr_cfig_a_reg_wenl_dly <= 1'b0;
else if (dma_reset)
rcr_cfig_a_reg_wenl_dly <= 1'b0;
else if (rcr_cfig_a_reg_wenl)
rcr_cfig_a_reg_wenl_dly <= 1'b1;
else
rcr_cfig_a_reg_wenl_dly <= 1'b0;
always @ (posedge clk)
if (reset)
rcr_cfig_a_reg_wenl_dly2 <= 1'b0;
else
rcr_cfig_a_reg_wenl_dly2 <= rcr_cfig_a_reg_wenl_dly;
always @ (posedge clk)
if (reset)
rx_dma_ctl_stat_reg_wenu_dly <= 1'b0;
else if (dma_reset)
rx_dma_ctl_stat_reg_wenu_dly <= 1'b0;
else
rx_dma_ctl_stat_reg_wenu_dly <= rx_dma_ctl_stat_reg_wenu;
always @ (posedge clk)
if (reset)
rx_dma_ctl_stat_reg_wenl_dly <= 1'b0;
else if (dma_reset)
rx_dma_ctl_stat_reg_wenl_dly <= 1'b0;
else
rx_dma_ctl_stat_reg_wenl_dly <= rx_dma_ctl_stat_reg_wenl;
wire[15:0] rcr_end_addr_sub = rcr_max_len[15:0] - 16'd1;
always @ (posedge clk)
if (reset)
rcr_end_addr_r <= 17'b0;
else if (dma_reset)
rcr_end_addr_r <= 17'b0;
else if (rcr_cfig_a_reg_wenu_dly & (|rcr_max_len))
rcr_end_addr_r <= {1'b0, rcr_end_addr_sub};
else if (rcr_cfig_a_reg_wenl_dly2 | rcr_cfig_a_reg_wenu_dly2)
rcr_end_addr_r <= {1'b0, rcr_start_addr[15:0]} + rcr_end_addr_r;
else
rcr_end_addr_r <= rcr_end_addr_r;
always @ (posedge clk)
if (reset)
addr_cnt <= 4'b0;
else if (dma_reset)
addr_cnt <= 4'b0;
else if (cal_addr_en)
addr_cnt <= rcr_wrbk_act_num; //each write back is one cache line for 8 addresses
else if (addr_cnt != 4'b0)
addr_cnt <= addr_cnt - 4'd1;
else
addr_cnt <= addr_cnt;
always @ (posedge clk)
if (reset)
rcr_curr_addr_tmp <= 16'b0;
else if ((addr_cnt != 4'b0) & (rcr_curr_addr_tmp == rcr_end_addr))
rcr_curr_addr_tmp <= rcr_start_addr;
else if (addr_cnt != 4'b0)
rcr_curr_addr_tmp <= rcr_curr_addr_tmp + 16'd1;
else if (cal_addr_en)
rcr_curr_addr_tmp <= rcr_curr_addr[15:0];
else
rcr_curr_addr_tmp <= rcr_curr_addr_tmp;
always @ (posedge clk)
if (reset)
rcr_curr_addr <= 16'b0;
else if (rcr_cfig_a_reg_wenl_dly)
rcr_curr_addr <= rcr_start_addr;
else if (rcr_wrbk_ack_done & !shadw_parity_err_r)
rcr_curr_addr <= rcr_curr_addr_tmp;
else
rcr_curr_addr <= rcr_curr_addr;
always @ (posedge clk)
if (reset)
dec_rcr_curr_cnt <= 1'b0;
else if (rx_dma_ctl_stat_reg_wenl & !rcr_wrbk_ack_done_sm | rx_dma_ctl_stat_reg_wenl_dly & !dec_rcr_curr_cnt)
dec_rcr_curr_cnt <= 1'b1;
else
dec_rcr_curr_cnt <= 1'b0;
always @ (posedge clk)
if (reset)
rcr_curr_cnt <= 17'b0; //pio read only, this is rcr addr cnt
else if (dma_reset)
rcr_curr_cnt <= 17'b0;
else if (rcr_curr_cnt[16] | rcr_curr_cnt_overflow_r)
rcr_curr_cnt <= rcr_curr_cnt;
else if (dec_rcr_curr_cnt)
rcr_curr_cnt <= rcr_curr_cnt - {1'b0, cpu_ptr_rd_num[15:0]}; // bit[16] is overflow bit
else if (rcr_wrbk_ack_done & !shadw_parity_err_r)
rcr_curr_cnt <= rcr_curr_cnt + {13'b0, rcr_wrbk_act_num[3:0]};
else
rcr_curr_cnt <= rcr_curr_cnt;
always @ (posedge clk)
if (reset)
rcr_wrbk_pkt_num_sav <= 4'b0;
else if (dma_reset)
rcr_wrbk_pkt_num_sav <= 4'b0;
else if (rcr_wrbk_ack_done & not_in_cacheline & !shadw_parity_err_r)
rcr_wrbk_pkt_num_sav <= rcr_wrbk_pkt_num_r;
else if (rcr_wrbk_ack_done & !shadw_parity_err_r)
rcr_wrbk_pkt_num_sav <= 4'b0;
else
rcr_wrbk_pkt_num_sav <= rcr_wrbk_pkt_num_sav;
always @ (posedge clk)
if (reset)
rcr_wrbk_pkt_act_num <= 4'b0;
else if (dma_reset)
rcr_wrbk_pkt_act_num <= 4'b0;
else if (rcr_wrbk_ack_done_sm & !shadw_parity_err_r)
rcr_wrbk_pkt_act_num <= (rcr_wrbk_pkt_num_r - rcr_wrbk_pkt_num_sav);
else
rcr_wrbk_pkt_act_num <= rcr_wrbk_pkt_act_num;
always @ (posedge clk)
if (reset)
rcr_curr_pkt_cnt <= 17'b0;
else if (dma_reset)
rcr_curr_pkt_cnt <= 17'b0;
else if (rcr_curr_pkt_cnt[16] | rcr_curr_cnt_overflow_r)
rcr_curr_pkt_cnt <= rcr_curr_pkt_cnt;
else if (dec_rcr_curr_cnt)
rcr_curr_pkt_cnt <= rcr_curr_pkt_cnt - {1'b0, cpu_pkt_rd_num[15:0]};
else if (rcr_wrbk_ack_done & !shadw_parity_err_r)
rcr_curr_pkt_cnt <= rcr_curr_pkt_cnt + {13'b0, rcr_wrbk_pkt_act_num[3:0]};
else
rcr_curr_pkt_cnt <= rcr_curr_pkt_cnt;
/******************************/
//RCR overflow/underflow
/******************************/
//can not detect real packet count overflow
wire rcr_curr_cnt_overflow = rcr_wrbk_ack_done_r & (rcr_curr_cnt > {1'b0, rcr_max_len[15:0]}) & dma_en;
wire rcr_curr_cnt_underflow = dec_rcr_curr_cnt_r & rcr_curr_cnt[16];
wire rcr_pkt_cnt_underflow = dec_rcr_curr_cnt_r & rcr_curr_pkt_cnt[16];
always @ (posedge clk)
if (reset)
dec_rcr_curr_cnt_r <= 1'b0;
else
dec_rcr_curr_cnt_r <= dec_rcr_curr_cnt;
always @ (posedge clk)
if (reset)
rcr_curr_cnt_overflow_r <= 1'b0;
else if (dma_reset)
rcr_curr_cnt_overflow_r <= 1'b0;
else if (rcr_curr_cnt_overflow)
rcr_curr_cnt_overflow_r <= 1'b1;
else
rcr_curr_cnt_overflow_r <= rcr_curr_cnt_overflow_r;
wire chnl_shadw_parity_err = shadw_parity_err & rcr_wrbk_sched;
always @ (posedge clk)
if (reset)
shadw_parity_err_r <= 1'b0;
else if (rcr_wrbk_ack_done)
shadw_parity_err_r <= 1'b0;
else if (chnl_shadw_parity_err | rcr_ack_err)
shadw_parity_err_r <= 1'b1;
else
shadw_parity_err_r <= shadw_parity_err_r;
/*********************************/
//request completion write back
/*********************************/
wire shadw_buf_not_empty = (|shadw_act_curr_cnt);
wire shadw_buf_empty = !shadw_buf_not_empty;
//wire mbox_update_true = (rcrto_bit | rcr_thresh_bit) & m_bit;
wire timer_mbox_update = timer_m_bit & (|rcr_curr_pkt_cnt);
wire thresh_mbox_update = thresh_m_bit & rcr_thresh_reg;
wire mbox_update_true = timer_mbox_update | thresh_mbox_update;
wire rcr_wrbk_trig = (|shadw_curr_cnt[7:3]) |
(rcr_timer_done_r | rcr_flush_reg | thresh_mbox_update) & shadw_buf_not_empty;
wire[3:0] rcr_wrbk_min_num = (|shadw_curr_cnt[7:3]) ? 4'd8 : shadw_curr_cnt[3:0];
wire[3:0] rcr_wrbk_act_num_tmp = not_in_cacheline ? (rcr_wrbk_min_num - {1'b0, rcr_curr_addr[2:0]}) : rcr_wrbk_min_num;
wire[43:0] rcr_full_addr = {rcr_base_addr[24:0], rcr_curr_addr[15:3], 6'b0}; //always start in cacheline
wire rcr_addr_valid0 = ((rcr_full_addr[43:12] & addr_mask0) == (comp_value0 & addr_mask0)) & page_valid0;
wire rcr_addr_valid1 = ((rcr_full_addr[43:12] & addr_mask1) == (comp_value1 & addr_mask1)) & page_valid1;
wire rcr_addr_valid = rcr_addr_valid0 | rcr_addr_valid1;
wire[31:0] rcr_relo_addr0 = (rcr_full_addr[43:12] & ~addr_mask0) | (relo_value0 & addr_mask0);
wire[31:0] rcr_relo_addr1 = (rcr_full_addr[43:12] & ~addr_mask1) | (relo_value1 & addr_mask1);
wire[31:0] rcr_relo_addr = rcr_addr_valid0 ? rcr_relo_addr0 : rcr_relo_addr1;
wire mbox_addr_valid0= ((mbox_addr[43:12] & addr_mask0) == (comp_value0 & addr_mask0)) & page_valid0;
wire mbox_addr_valid1= ((mbox_addr[43:12] & addr_mask1) == (comp_value1 & addr_mask1)) & page_valid1;
wire mbox_addr_valid = mbox_addr_valid0 | mbox_addr_valid1;
wire[31:0] mbox_relo_addr0 = (mbox_addr[43:12] & ~addr_mask0) | (relo_value0 & addr_mask0);
wire[31:0] mbox_relo_addr1 = (mbox_addr[43:12] & ~addr_mask1) | (relo_value1 & addr_mask1);
wire[31:0] mbox_relo_addr = mbox_addr_valid0 ? mbox_relo_addr0 : mbox_relo_addr1;
wire[43:0] relo_addr_tmp = mbox_req_sm ? {mbox_relo_addr, mbox_addr[11:0]} :
{rcr_relo_addr, rcr_full_addr[11:0]};
wire[63:0] rcr_wrbk_addr = {page_handle[19:0], rcr_relo_addr_r[43:0]};
wire rcr_addr_not_valid = !rcr_addr_valid & dma_en;
wire mbox_addr_not_valid = !mbox_addr_valid & dma_en;
always @ (posedge clk)
if (reset)
cal_addr_en <= 1'b0;
else
cal_addr_en <= rcr_wrbk_req_sm;
always @ (posedge clk)
if (reset)
rcr_relo_addr_r <= 44'b0;
else if (rcr_wrbk_req_sm | mbox_req_sm)
rcr_relo_addr_r <= relo_addr_tmp;
else
rcr_relo_addr_r <= rcr_relo_addr_r;
always @ (posedge clk)
if (reset)
rcr_wrbk_act_num <= 4'b0;
else if (dma_reset)
rcr_wrbk_act_num <= 4'b0;
else if (rcr_wrbk_req_sm)
rcr_wrbk_act_num <= rcr_wrbk_act_num_tmp;
else
rcr_wrbk_act_num <= rcr_wrbk_act_num;
always @ (posedge clk)
if (reset)
rcr_wrbk_numb <= 4'b0;
else if (dma_reset)
rcr_wrbk_numb <= 4'b0;
else if (rcr_wrbk_req_sm)
rcr_wrbk_numb <= rcr_wrbk_min_num;
else
rcr_wrbk_numb <= rcr_wrbk_numb;
always @ (posedge clk)
if (reset)
not_in_cacheline <= 1'b0;
else if (dma_reset)
not_in_cacheline <= 1'b0;
else if (rcr_wrbk_req_sm)
not_in_cacheline <= !rcr_wrbk_min_num[3];
else
not_in_cacheline <= not_in_cacheline;
always @ (posedge clk)
if (reset)
rcr_wrbk_data_type <= 1'b0;
else if (dma_reset)
rcr_wrbk_data_type <= 1'b0;
else if (rcr_wrbk_req_sm)
rcr_wrbk_data_type <= 1'b1;
else if (mbox_req_sm)
rcr_wrbk_data_type <= 1'b0;
else
rcr_wrbk_data_type <= rcr_wrbk_data_type;
always @ (posedge clk)
if (reset)
rcr_wrbk_req <= 1'b0;
else if (dma_reset)
rcr_wrbk_req <= 1'b0;
else if (rcr_wrbk_gnt)
rcr_wrbk_req <= 1'b0;
else if (rcr_wrbk_req_sm | mbox_req_sm)
rcr_wrbk_req <= 1'b1;
else
rcr_wrbk_req <= rcr_wrbk_req;
always @ (posedge clk)
if (reset)
rcr_wrbk_sched <= 1'b0;
else if (dma_reset)
rcr_wrbk_sched <= 1'b0;
else if (rcr_wrbk_gnt)
rcr_wrbk_sched <= 1'b1;
else if (rcr_wrbk_done_r)
rcr_wrbk_sched <= 1'b0;
else
rcr_wrbk_sched <= rcr_wrbk_sched;
always @ (posedge clk)
if (reset)
begin
rcr_wrbk_done_r <= 1'b0;
rcr_wrbk_done_r1 <= 1'b0;
end
else
begin
rcr_wrbk_done_r <= rcr_wrbk_sched & rcr_wrbk_done;
rcr_wrbk_done_r1 <= rcr_wrbk_done_r;
end
always @ (posedge clk)
if (reset)
rcr_wrbk_pkt_num_r <= 4'b0;
else if (dma_reset)
rcr_wrbk_pkt_num_r <= 4'b0;
else if (rcr_wrbk_done_r1)
rcr_wrbk_pkt_num_r <= rcr_wrbk_pkt_num;
else
rcr_wrbk_pkt_num_r <= rcr_wrbk_pkt_num_r;
always @ (posedge clk)
if (reset)
begin
rcr_wrbk_ack_done <= 1'b0;
rcr_wrbk_ack_done_r <= 1'b0;
mbox_update_done <= 1'b0;
end
else
begin
rcr_wrbk_ack_done <= rcr_wrbk_ack_done_sm;
rcr_wrbk_ack_done_r <= rcr_wrbk_ack_done;
mbox_update_done <= mbox_update_done_sm;
end
always @ (posedge clk)
if (reset)
rcr_ack_accept <= 1'b0;
else
rcr_ack_accept <= rcr_ack_accept_sm;
/************************************/
//Completion write back FSM
/************************************/
wire rdmc_rcr_ack = rdmc_rcr_ack_valid & (rdmc_rcr_ack_dma_num == dma_chnl_grp_id);
parameter
IDLE = 4'd0,
WRBK_REQ = 4'd1,
WAIT_WRBK_DONE = 4'd2,
WAIT_WRBK_ACK = 4'd3,
WRBK_ACK_DONE_WAIT1 = 4'd4,
WRBK_ACK_DONE_WAIT2 = 4'd5,
WRBK_ACK_DONE = 4'd6,
MBOX_REQ = 4'd7,
WAIT_MBOX_WR_DONE = 4'd8,
WAIT_MBOX_ACK = 4'd9,
COMP_S1 = 4'd10,
COMP_S2 = 4'd11;
always @ (state or rcr_addr_valid or mbox_addr_valid or
rcr_wrbk_trig or mbox_update_true or
rcr_wrbk_sched or rcr_wrbk_done_r or
rdmc_rcr_ack or rdmc_rcr_ack_err or
dma_fatal_err or shadw_parity_err_r or
rcr_timer_done_r)
begin
rcr_idle_cycle = 1'b0;
rcr_wrbk_req_sm = 1'b0;
mbox_req_sm = 1'b0;
rcr_wrbk_ack_done_sm = 1'b0;
mbox_update_done_sm = 1'b0;
rcr_ack_accept_sm = 1'b0;
reset_rcr_timer = 1'b0;
reset_m_bit = 1'b0;
next_state = 4'b0;
case (state) //synopsys parallel_case full_case
IDLE:
begin
rcr_idle_cycle = 1'b1;
if ((rcr_addr_valid | mbox_addr_valid) & !dma_fatal_err)
begin
if (rcr_wrbk_trig)
begin
rcr_wrbk_req_sm = 1'b1;
next_state = WRBK_REQ;
end
else if (mbox_update_true)
begin
mbox_req_sm = 1'b1;
next_state = MBOX_REQ;
end
else if (rcr_timer_done_r)
begin
reset_rcr_timer = 1'b1;
next_state = state;
end
else
next_state = state;
end
else
next_state = state;
end
WRBK_REQ:
begin
if (rcr_wrbk_sched)
next_state = WAIT_WRBK_DONE;
else
next_state = state;
end
WAIT_WRBK_DONE:
begin
if (rcr_wrbk_done_r)
next_state = WAIT_WRBK_ACK;
else
next_state = state;
end
WAIT_WRBK_ACK:
begin
if (rdmc_rcr_ack)
begin
rcr_wrbk_ack_done_sm = 1'b1;
rcr_ack_accept_sm = 1'b1;
if (shadw_parity_err_r | rdmc_rcr_ack_err)
next_state = IDLE;
else
next_state = WRBK_ACK_DONE_WAIT1;
end
else
next_state = state;
end
WRBK_ACK_DONE_WAIT1:
next_state = WRBK_ACK_DONE_WAIT2;
WRBK_ACK_DONE_WAIT2:
next_state = WRBK_ACK_DONE;
WRBK_ACK_DONE:
begin
if (mbox_update_true)
begin
mbox_req_sm = 1'b1;
next_state = MBOX_REQ;
end
else if (rcr_timer_done_r)
begin
reset_m_bit = 1'b1;
reset_rcr_timer = 1'b1;
next_state = COMP_S2;
end
else
begin
reset_m_bit = 1'b1;
next_state = COMP_S2;
end
end
MBOX_REQ:
begin
if (rcr_wrbk_sched)
next_state = WAIT_MBOX_WR_DONE;
else
next_state = state;
end
WAIT_MBOX_WR_DONE:
begin
if (rcr_wrbk_done_r)
next_state = WAIT_MBOX_ACK;
else
next_state = state;
end
WAIT_MBOX_ACK:
begin
if (rdmc_rcr_ack)
begin
mbox_update_done_sm = 1'b1;
rcr_ack_accept_sm = 1'b1;
next_state = COMP_S1;
end
else
next_state = state;
end
COMP_S1:
begin
if (rcr_timer_done_r)
reset_rcr_timer = 1'b1;
else
reset_rcr_timer = 1'b0;
reset_m_bit = 1'b1;
next_state = COMP_S2;
end
COMP_S2:
next_state = IDLE;
default:
next_state = IDLE;
endcase
end
always @ (posedge clk)
if (reset)
state <= 4'b0;
else if (dma_reset)
state <= 4'b0;
else
state <= next_state;
/*********************************/
// shadwow memory manager
/*********************************/
wire shadw_wr_even = shadw_curr_cnt[0];
wire last_rd_addr = (shadw_rd_ptr == shadw_rd_end_addr);
wire last_wr_addr = (shadw_wr_ptr == shadw_wr_end_addr);
always @ (posedge clk)
if (reset)
shadw_wr_en <= 1'b0;
else if (dma_reset)
shadw_wr_en <= 1'b0;
else
shadw_wr_en <= update_rcr_shadw & (rdmc_wr_data_dma_num == dma_chnl_grp_id);
always @ (posedge clk)
if (reset)
shadw_wr_ptr <= shadw_start_addr;
else if (dma_reset)
shadw_wr_ptr <= shadw_start_addr;
else if (shadw_wr_en & shadw_curr_cnt[0] & last_wr_addr)
shadw_wr_ptr <= shadw_start_addr;
else if (shadw_wr_en & shadw_curr_cnt[0])
shadw_wr_ptr <= shadw_wr_ptr + 8'd1;
else
shadw_wr_ptr <= shadw_wr_ptr;
always @ (posedge clk)
if (reset)
shadw_rd_ptr <= shadw_start_addr;
else if (dma_reset)
shadw_rd_ptr <= shadw_start_addr;
else if (rcr_wrbk_ack_done & rcr_wrbk_numb[3] & last_rd_addr)
shadw_rd_ptr <= shadw_start_addr;
else if (rcr_wrbk_ack_done & rcr_wrbk_numb[3])
shadw_rd_ptr <= shadw_rd_ptr + 8'd4;
else
shadw_rd_ptr <= shadw_rd_ptr;
always @ (posedge clk)
if (reset)
inc_shadw_curr_cnt <= 1'b0;
else if (dma_reset)
inc_shadw_curr_cnt <= 1'b0;
else if (shadw_wr_en & rcr_wrbk_ack_done)
inc_shadw_curr_cnt <= 1'b1;
else
inc_shadw_curr_cnt <= 1'b0;
always @ (posedge clk)
if (reset)
shadw_curr_cnt <= 8'b0;
else if (dma_reset)
shadw_curr_cnt <= 8'b0;
else if (shadw_wr_en & !rcr_wrbk_ack_done | inc_shadw_curr_cnt)
shadw_curr_cnt <= shadw_curr_cnt + 8'd1;
else if (rcr_wrbk_ack_done & rcr_wrbk_numb[3])
shadw_curr_cnt <= shadw_curr_cnt - 8'd8;
else
shadw_curr_cnt <= shadw_curr_cnt;
always @ (posedge clk)
if (reset)
shadw_act_curr_cnt <= 6'b0; //support 4 cache line only
else if (dma_reset)
shadw_act_curr_cnt <= 6'b0;
else if (shadw_wr_en & !rcr_wrbk_ack_done | inc_shadw_curr_cnt)
shadw_act_curr_cnt <= shadw_act_curr_cnt + 6'd1;
else if (rcr_wrbk_ack_done)
shadw_act_curr_cnt <= shadw_act_curr_cnt - {2'b0, rcr_wrbk_act_num[3:0]};
else
shadw_act_curr_cnt <= shadw_act_curr_cnt;
always @ (posedge clk)
if (reset)
dec_shadw_space_cnt <= 1'b0;
else if (chnl_sel_buf_en_r & rcr_wrbk_ack_done)
dec_shadw_space_cnt <= 1'b1;
else
dec_shadw_space_cnt <= 1'b0;
always @ (posedge clk)
if (reset)
shadw_curr_space_cnt <= `SHADW_MAX_ADDR_CNT;
else if (dma_reset)
shadw_curr_space_cnt <= `SHADW_MAX_ADDR_CNT;
else if (chnl_sel_buf_en_r & !rcr_wrbk_ack_done | dec_shadw_space_cnt)
shadw_curr_space_cnt <= shadw_curr_space_cnt - {6'b0, pref_buf_used_num[1:0]};
else if (rcr_wrbk_ack_done & rcr_wrbk_numb[3])
shadw_curr_space_cnt <= shadw_curr_space_cnt + 8'd8;
else
shadw_curr_space_cnt <= shadw_curr_space_cnt;
always @ (posedge clk)
if (reset)
chnl_has_pkt_s1 <= 1'b0;
else if (chnl_sel_buf_en_r)
chnl_has_pkt_s1 <= 1'b1;
else if (wr_last_pkt_data & shadw_wr_en)
chnl_has_pkt_s1 <= 1'b0;
else
chnl_has_pkt_s1 <= chnl_has_pkt_s1;
always @ (posedge clk)
if (reset)
chnl_has_pkt_s2 <= 1'b0;
else if (wr_last_pkt_data & shadw_wr_en)
chnl_has_pkt_s2 <= 1'b1;
else if (wr_transfer_comp_int)
chnl_has_pkt_s2 <= 1'b0;
else
chnl_has_pkt_s2 <= chnl_has_pkt_s2;
wire chnl_has_pkt = chnl_has_pkt_s1 | chnl_has_pkt_s2;
/********************************/
//Mailbox operations
/********************************/
wire m_bit_en = mbox_update_done & !rx_dma_ctl_stat_reg_wenu | mbox_update_done_dly;
wire set_rcrto_bit = mbox_update_done ? rcr_timer_done_r : rcr_timer_done_r_dly;
wire m_bit_in = !(rcr_thresh_reg | set_rcrto_bit);
assign rcr_ctl_stat_word= {m_bit_in, rcr_thresh_reg, set_rcrto_bit};
always @ (posedge clk)
if (reset)
rcr_thresh_reg <= 1'b0;
else
rcr_thresh_reg <= (rcr_curr_pkt_cnt[15:0] > pkt_thresh);
always @ (posedge clk)
if (reset)
thresh_m_bit <= 1'b0;
else if (reset_m_bit)
thresh_m_bit <= 1'b0;
else if (rcr_idle_cycle & !rx_dma_ctl_stat_reg_wenu_dly)
thresh_m_bit <= m_bit;
else
thresh_m_bit <= thresh_m_bit;
always @ (posedge clk)
if (reset)
begin
rcr_timer_done_r_dly <= 1'b0;
mbox_update_done_dly <= 1'b0;
end
else
begin
rcr_timer_done_r_dly <= mbox_update_done & rcr_timer_done_r;
mbox_update_done_dly <= mbox_update_done & rx_dma_ctl_stat_reg_wenu;
end
/********************************/
//RCR Timeout counter
/********************************/
wire clk_cnt_done = (clk_cnt == clk_div_value);
wire rcr_timer_done = (timeout_cnt == timeout_value) & timeout_en;
wire pio_wr_reset = rx_dma_ctl_stat_reg_wenu_dly & m_bit & !rcr_timer_done_r;
always @ (posedge clk)
if (reset)
timer_m_bit <= 1'b0;
else if (pio_wr_reset | reset_rcr_timer | m_bit_en)
timer_m_bit <= 1'b0;
else if (rcr_timer_done)
timer_m_bit <= m_bit;
else
timer_m_bit <= timer_m_bit;
always @ (posedge clk)
if (reset)
clk_cnt <= 16'b0;
else if (dma_reset)
clk_cnt <= 16'b0;
else if (clk_cnt_done)
clk_cnt <= 16'b0;
else
clk_cnt <= clk_cnt + 16'd1;
always @ (posedge clk)
if (reset)
timeout_cnt <= 6'b0;
else if (dma_reset)
timeout_cnt <= 6'b0;
else if (pio_wr_reset | reset_rcr_timer)
timeout_cnt <= 6'b0;
else if (rcr_timer_done)
timeout_cnt <= timeout_cnt;
else if (clk_cnt_done & timeout_en)
timeout_cnt <= timeout_cnt + 6'd1;
else
timeout_cnt <= timeout_cnt;
always @ (posedge clk)
if (reset)
rcr_timer_done_r <= 1'b0;
else if (pio_wr_reset | reset_rcr_timer)
rcr_timer_done_r <= 1'b0;
else if (rcr_timer_done)
rcr_timer_done_r <= 1'b1;
else
rcr_timer_done_r <= rcr_timer_done_r;
/********************************/
//RCR Flush
/********************************/
always @ (posedge clk)
if (reset)
rcr_flush_reg_dly <= 1'b0;
else
rcr_flush_reg_dly <= rcr_flush_reg;
wire rcr_flush_pulse = rcr_flush_reg & !rcr_flush_reg_dly;
wire reset_rcr_flush = rcr_flush_pulse & shadw_buf_empty | rcr_wrbk_ack_done;
endmodule