OpenCores
URL https://opencores.org/ocsvn/openhmc/openhmc/trunk

Subversion Repositories openhmc

[/] [openhmc/] [trunk/] [openHMC/] [rtl/] [hmc_controller/] [tx/] [tx_link.v] - Rev 15

Compare with Previous | Blame | View Log

/*
 *                              .--------------. .----------------. .------------.
 *                             | .------------. | .--------------. | .----------. |
 *                             | | ____  ____ | | | ____    ____ | | |   ______ | |
 *                             | ||_   ||   _|| | ||_   \  /   _|| | | .' ___  || |
 *       ___  _ __   ___ _ __  | |  | |__| |  | | |  |   \/   |  | | |/ .'   \_|| |
 *      / _ \| '_ \ / _ \ '_ \ | |  |  __  |  | | |  | |\  /| |  | | || |       | |
 *       (_) | |_) |  __/ | | || | _| |  | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
 *      \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
 *           | |               | |            | | |              | | |          | |
 *           |_|               | '------------' | '--------------' | '----------' |
 *                              '--------------' '----------------' '------------'
 *
 *  openHMC - An Open Source Hybrid Memory Cube Controller
 *  (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
 *  www.ziti.uni-heidelberg.de
 *  B6, 26
 *  68159 Mannheim
 *  Germany
 *
 *  Contact: openhmc@ziti.uni-heidelberg.de
 *  http://ra.ziti.uni-heidelberg.de/openhmc
 *
 *   This source file is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This source file 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 Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this source file.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *  Module name: tx_link
 *
 */
 
`default_nettype none
 
module tx_link #(
    parameter LOG_FPW           = 2,
    parameter FPW               = 4,
    parameter DWIDTH            = FPW*128,
    parameter NUM_LANES         = 8,
    parameter RF_COUNTER_SIZE   = 64,
    parameter HMC_RX_AC_COUPLED = 1,
    parameter MAX_RTC_RET_LOG   = 8,
    parameter LOG_MAX_RX_TOKENS = 8,
    parameter LOG_MAX_HMC_TOKENS= 10,
    parameter LOG_IRTRY_TIMOUT  = 8,
    parameter XIL_CNT_PIPELINED = 0,
    //Debug
    parameter DBG_RX_TOKEN_MON  = 1,
    parameter OPEN_RSP_MODE     = 0
) (
 
    //----------------------------------
    //----SYSTEM INTERFACE
    //----------------------------------
    input   wire                        clk,
    input   wire                        res_n,
 
    //----------------------------------
    //----TO HMC PHY
    //----------------------------------
    output  wire [DWIDTH-1:0]           phy_scrambled_data_out,
 
    //----------------------------------
    //----HMC IF
    //----------------------------------
    output  reg                         LXRXPS,
    input   wire                        LXTXPS,
 
    //----------------------------------
    //----Input data
    //----------------------------------
    input   wire [DWIDTH-1:0]           d_in_data,
    input   wire [FPW-1:0]              d_in_flit_is_hdr,
    input   wire [FPW-1:0]              d_in_flit_is_tail,
    input   wire [FPW-1:0]              d_in_flit_is_valid,
    input   wire                        d_in_empty,
    input   wire                        d_in_a_empty,
    output  reg                         d_in_shift_out,
 
    //----------------------------------
    //----RX Block
    //----------------------------------
    input   wire                        rx_force_tx_retry,
    input   wire                        rx_error_abort_mode,
    input   wire                        rx_error_abort_mode_cleared,
    input   wire [7:0]                  rx_hmc_frp,
    input   wire [7:0]                  rx_rrp,
    input   wire [MAX_RTC_RET_LOG-1:0]  rx_returned_tokens,
    input   wire [LOG_FPW:0]            rx_hmc_tokens_to_return,
    input   wire [LOG_FPW:0]            rx_hmc_poisoned_tokens_to_return,
 
    //----------------------------------
    //----RF
    //----------------------------------
    //Monitoring    1-cycle set to increment
    output  reg                         rf_cnt_retry,
    output  wire [RF_COUNTER_SIZE-1:0]  rf_sent_p,
    output  wire [RF_COUNTER_SIZE-1:0]  rf_sent_np,
    output  wire [RF_COUNTER_SIZE-1:0]  rf_sent_r,
    output  reg                         rf_run_length_bit_flip,
    output  reg                         rf_error_abort_not_cleared,
 
    //Status
    input   wire                        rf_link_is_up,
    input   wire                        rf_hmc_received_init_null,
    input   wire                        rf_descramblers_aligned,
    output  wire [1:0]                  rf_tx_init_status,
    output  reg  [LOG_MAX_HMC_TOKENS-1:0]rf_hmc_tokens_av,
    output  wire [LOG_MAX_RX_TOKENS-1:0]rf_rx_tokens_av,
 
    //Control
    input   wire                        rf_hmc_sleep_requested,
    input   wire                        rf_warm_reset,
    input   wire                        rf_scrambler_disable,
    input   wire [LOG_MAX_RX_TOKENS-1:0]rf_rx_buffer_rtc,
    input   wire [4:0]                  rf_irtry_to_send,
    input   wire                        rf_run_length_enable
 
);
 
`include "hmc_field_functions.h"
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//------------------------------------------------------------------------------------General Assignments
localparam LANE_WIDTH       = (DWIDTH/NUM_LANES);
 
integer i_f;    //counts to FPW
integer i_t;    //counts to number of TS1 packets in a word
 
//Packet command 3-MSB definition
localparam PKT_WRITE        = 3'b001;
localparam PKT_MISC_WRITE   = 3'b010;
localparam PKT_READ         = 3'b110;
localparam PKT_MODE_READ    = 3'b101;
localparam PKT_P_WRITE      = 3'b011;
localparam PKT_MISC_P_WRITE = 3'b100;
 
localparam CMD_IRTRY        = 6'b000011;
 
//------------------------------------------------------------------------------------Scrambler
wire [14:0]             seed_lane   [NUM_LANES-1:0];
 
assign seed_lane[0]     = 15'h4D56;
assign seed_lane[1]     = 15'h47FF;
assign seed_lane[2]     = 15'h75B8;
assign seed_lane[3]     = 15'h1E18;
assign seed_lane[4]     = 15'h2E10;
assign seed_lane[5]     = 15'h3EB2;
assign seed_lane[6]     = 15'h4302;
assign seed_lane[7]     = 15'h1380;
 
generate
    if(NUM_LANES==16) begin : seed_gen_16x
        assign seed_lane[8]     = 15'h3EB3;
        assign seed_lane[9]     = 15'h2769;
        assign seed_lane[10]    = 15'h4580;
        assign seed_lane[11]    = 15'h5665;
        assign seed_lane[12]    = 15'h6318;
        assign seed_lane[13]    = 15'h6014;
        assign seed_lane[14]    = 15'h077B;
        assign seed_lane[15]    = 15'h261F;
    end
endgenerate
 
wire [NUM_LANES-1:0]    bit_was_flipped;
 
//------------------------------------------------------------------------------------FSM and States
reg [2:0]  state;
reg [1:0]  init_state;
localparam INIT_TX_NULL_1       = 2'b00;
localparam INIT_TX_TS1          = 2'b01;
localparam INIT_TX_NULL_2       = 2'b11;
localparam INIT_DONE            = 2'b10;
 
localparam INIT                 = 3'b000;
localparam IDLE                 = 3'b001;
localparam TX                   = 3'b010;
localparam HMC_RTRY             = 3'b011;
localparam SLEEP                = 3'b100;
localparam WAIT_FOR_HMC         = 3'b101;
localparam LNK_RTRY             = 3'b110;
localparam DEBUG                = 3'b111;
 
assign  rf_tx_init_status = init_state;
 
reg     rtc_rx_initialize;
 
//------------------------------------------------------------------------------------DATA and ORDERING
//reorder incoming data to FLITs
wire [127:0]   d_in_flit [FPW-1:0];
genvar  f;
generate
        for(f = 0; f < (FPW); f = f + 1) begin : reorder_input_data_to_flits
            assign d_in_flit[f] = d_in_data[127+(f*128):f*128];
        end
endgenerate
 
//Create a mask and an input buffer that is necessary if packet transmission is interrupted and packets remain untransmitted
reg                 d_in_use_buf;
reg  [127:0]        d_in_buf_flit          [FPW-2:0];
reg  [FPW-2:0]      d_in_buf_flit_is_hdr;
reg  [FPW-2:0]      d_in_buf_flit_is_valid;
 
//Reorder the data per lane
wire [DWIDTH-1:0]   data_rdy;
wire [DWIDTH-1:0]   data_to_scrambler;
 
genvar l,n;
generate
    for(n = 0; n < NUM_LANES; n = n + 1) begin : reorder_data_to_lanes
        for(l = 0; l < LANE_WIDTH; l = l + 1) begin
            assign data_to_scrambler[l+n*LANE_WIDTH] = data_rdy[l*NUM_LANES+n];
        end
    end
endgenerate
 
//------------------------------------------------------------------------------------Init Regs
localparam TS1_SEQ_INC_VAL_PER_CYCLE        = (NUM_LANES==8) ? FPW : (FPW/2);
localparam LOG_CYCLES_NULL_TO_SEND          = (FPW == 2) ? 4 :
                                              (FPW == 4) ? 3 :
                                              (FPW == 6) ? 3 :
                                              2;
 
wire  [(NUM_LANES*4)-1:0]       ts1_seq_part_reordered      [TS1_SEQ_INC_VAL_PER_CYCLE-1:0];    //ts1 seq is 4 bits
reg   [3:0]                     ts1_seq_nr_per_flit         [TS1_SEQ_INC_VAL_PER_CYCLE-1:0];
wire  [127:0]                   ts1_flit                    [FPW-1:0];
reg   [LOG_CYCLES_NULL_TO_SEND-1:0] num_null_cycles_sent;
 
generate
    for(f = 0; f < TS1_SEQ_INC_VAL_PER_CYCLE; f = f + 1) begin : generate_lane_dependent_ts1_sequence
 
        for(n=0; n<4; n=n+1) begin
            assign ts1_seq_part_reordered[f][(n*NUM_LANES)+NUM_LANES-1:(n*NUM_LANES)] = {NUM_LANES{ts1_seq_nr_per_flit[f][n]}};
        end
 
        if(NUM_LANES==8) begin
            assign ts1_flit[f] = {
                32'hffffffff,32'h0,1'h1,7'h0,7'b1111111,1'h0,7'h0,1'h1,1'h0,7'b1111111,ts1_seq_part_reordered[f]
            };
        end else begin
            assign ts1_flit[f*2+1] = {
                64'hffffffffffffffff,64'h0
            };
            assign ts1_flit[f*2] = {
                16'h8000,16'hfffe,16'h0001,16'h7fff,ts1_seq_part_reordered[f]
            };
        end
 
    end
endgenerate
//------------------------------------------------------------------------------------Counter variables
reg  [LOG_FPW:0]    rf_sent_p_comb;
reg  [LOG_FPW:0]    rf_sent_np_comb;
reg  [LOG_FPW:0]    rf_sent_r_comb;
 
//------------------------------------------------------------------------------------SEQ FRP RTC Stage
reg  [127:0]        data2rtc_stage_flit     [FPW-1:0];
reg  [FPW-1:0]      data2rtc_stage_flit_is_hdr;
reg  [FPW-1:0]      data2rtc_stage_flit_is_tail;
reg  [FPW-1:0]      data2rtc_stage_flit_is_valid;
reg                 data2rtc_stage_is_flow;
reg                 data2rtc_stage_force_tx_retry;
 
reg  [127:0]        data2seq_frp_stage_flit          [FPW-1:0];
reg  [FPW-1:0]      data2seq_frp_stage_flit_is_hdr;
reg  [FPW-1:0]      data2seq_frp_stage_flit_is_tail;
reg  [FPW-1:0]      data2seq_frp_stage_flit_is_valid;
reg                 data2seq_frp_stage_is_flow;
reg                 data2seq_frp_stage_force_tx_retry;
 
//Information used to fill the retry buffer
reg [LOG_FPW-1:0]   target_temp [FPW:0];
reg [LOG_FPW-1:0]   next_target;
reg [LOG_FPW-1:0]   target      [FPW-1:0];
 
reg [LOG_FPW:0]     tx_seqnum_inc;
reg [2:0]           tx_seqnum_temp [FPW-1:0];
 
//------------------------------------------------------------------------------------RETRY
//HMC
//Number of cycles to wait until start HMC retry is issued again (when RX error abort is not cleared)
reg  [LOG_IRTRY_TIMOUT-1:0] error_abort_mode_clr_cnt;
reg                         force_hmc_retry;
reg  [4:0]                  irtry_start_retry_cnt;
reg  [4:0]                  irtry_clear_error_cnt;
wire [63:0]                 irtry_hdr;
assign                      irtry_hdr = {6'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000011};
 
//------------------------------------------------------------------------------------Retry Buffer
localparam RAM_ADDR_SIZE   =   (FPW == 2) ? 7 :
                               (FPW == 4) ? 6 :
                               (FPW == 6) ? 5 :
                               (FPW == 8) ? 5 :
                               1;
 
reg  [127:0]                data2ram_flit           [FPW-1:0];
reg  [127:0]                data2ram_flit_temp      [FPW-1:0];
reg  [FPW-1:0]              data2ram_flit_is_hdr;
reg  [FPW-1:0]              data2ram_flit_is_tail;
reg  [FPW-1:0]              data2ram_flit_is_valid;
reg                         data2ram_force_tx_retry;
 
//Header/Tail fields, and at the same time form the RAM read pointer
reg  [RAM_ADDR_SIZE-1:0]    tx_frp_adr [FPW-1:0];
reg  [2:0]                  tx_seqnum;
 
 
reg [FPW-1:0]               ram_w_en ;
reg                         ram_r_en;
wire [RAM_ADDR_SIZE-1:0]    ram_w_addr_next;
assign                      ram_w_addr_next = tx_frp_adr[0] + 1;
reg  [RAM_ADDR_SIZE-1:0]    ram_r_addr_temp;
reg  [FPW-1:0]              ram_r_mask;
wire [128+3-1:0]            ram_r_data              [FPW-1:0];
reg  [128+3-1:0]            ram_w_data              [FPW-1:0];
 
wire  [RAM_ADDR_SIZE-1:0]   ram_r_addr;
assign                      ram_r_addr = rx_rrp[7:8-RAM_ADDR_SIZE];
 
//Avoid overwriting not acknowleged FLITs in the retry buffer
wire [RAM_ADDR_SIZE-1:0]    ram_result;
assign                      ram_result          = ram_r_addr - ram_w_addr_next;
 
//A safe value since ram_w_addr_next is calculated some cycles after packets were accepted
wire                        ram_full;
assign                      ram_full = (ram_result<9 && ram_result>0) ? 1'b1 : 1'b0 ;
 
//Regs for TX Link retry handling
reg                 tx_retry_finished;
reg                 tx_retry_ongoing;
reg                 tx_link_retry_request;  //Sample the retry request
 
//------------------------------------------------------------------------------------RRP Stage
reg  [127:0]        data2rrp_stage_flit           [FPW-1:0];
reg  [FPW-1:0]      data2rrp_stage_flit_is_hdr;
reg  [FPW-1:0]      data2rrp_stage_flit_is_tail;
reg  [FPW-1:0]      data2rrp_stage_flit_is_valid;
 
`ifdef SIMULATION
    //We dont want to crash a simulation run because PRETs are still travelling upon test completion, so we include a trigger to only send PRETs when necessary in simulation
    //In hardware, PRETs will be sent whenever there is no valid FLIT on position 0 -> reduces the overall pointer return delay
    reg  [7:0]  last_transmitted_rx_hmc_frp;
`else 
    reg         send_prets;
`endif
 
//------------------------------------------------------------------------------------CRC
reg  [127:0]        data2crc_flit           [FPW-1:0];
wire [DWIDTH-1:0]   data2crc;
reg  [FPW-1:0]      data2crc_flit_is_hdr;
reg  [FPW-1:0]      data2crc_flit_is_tail;
 
generate
    for(f = 0; f < (FPW); f = f + 1) begin : concatenate_flits_to_single_reg
        assign data2crc[(f*128)+127:(f*128)]  = data2crc_flit[f];
    end
endgenerate
 
//------------------------------------------------------------------------------------FLOW PACKETS
//TRET
wire    [63:0]              tret_hdr;
assign                      tret_hdr        = {6'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000010};
//PRET
wire    [63:0]              pret_hdr;
assign                      pret_hdr        = {6'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000001};
 
//------------------------------------------------------------------------------------RTC HANDLING
//Registers for the RTC field in request packets
reg                         rtc_return;
reg  [4:0]                  rtc_return_val;
 
//A safe value to not send more FLITs than the HMC can buffer
reg  [LOG_FPW-1:0]          num_flits_in_buf;
reg  [LOG_FPW:0]            num_flits_transmitted;
reg  [LOG_MAX_RX_TOKENS-1:0]remaining_tokens;
localparam TOKENS_THRESHOLD=   (FPW == 2) ? 11 :
                               (FPW == 4) ? 15 :
                               (FPW == 6) ? 23 :
                               (FPW == 8) ? 23 :
                               1;
wire                        hmc_tokens_av;
assign                      hmc_tokens_av = ((rf_hmc_tokens_av+num_flits_in_buf+rx_returned_tokens) > TOKENS_THRESHOLD) ? 1'b1 : 1'b0;
 
//Return a maximum of 31 tokens
wire [4:0]                  outstanding_tokens_to_return;
assign                      outstanding_tokens_to_return   = (OPEN_RSP_MODE==0) ? (remaining_tokens > 31 ? 31 : remaining_tokens[4:0]) : 5'h0;
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
//====================================================================
//---------------------------------MISC
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
if(!res_n) begin
    rf_run_length_bit_flip   <= 1'b0;
end else begin
    rf_run_length_bit_flip   <= |bit_was_flipped;
end
end
 
//====================================================================
//---------------------------------Monitor Remaining Tokens in the RX input buffer, just a debug help
//====================================================================
//Track the remaining tokens in the rx input buffer. This is optional since the HMC must make sure not to send more tokens than RX can buffer, useful for debugging
generate
if(DBG_RX_TOKEN_MON==1 && OPEN_RSP_MODE==0) begin : Tokens_in_RX_buf
 
    reg  [6:0]                  sum_requested_tokens;       //Count the amount of tokens requested from the HMC
    reg  [6:0]                  sum_requested_tokens_temp;  //Use this register for combinational logic
 
    always @(*)  begin
        sum_requested_tokens_temp   = {7{1'b0}};
 
        for(i_f=0;i_f<FPW;i_f=i_f+1) begin
 
            if(data2rtc_stage_flit_is_hdr[i_f] && data2rtc_stage_flit_is_valid[i_f]) begin
 
                if(cmd_type(data2rtc_stage_flit[i_f]) == PKT_READ ||
                   cmd_type(data2rtc_stage_flit[i_f]) == PKT_MODE_READ ) begin
                    //it is either a data read or mode read
                    sum_requested_tokens_temp    =  sum_requested_tokens_temp + num_requested_flits(data2rtc_stage_flit[i_f]);
                end else if(    (cmd_type(data2rtc_stage_flit[i_f]) == PKT_WRITE) ||
                                (cmd_type(data2rtc_stage_flit[i_f]) == PKT_MISC_WRITE) ) begin
                    //it is not a posted transaction, so 1 token will be returned as response
                    sum_requested_tokens_temp    = sum_requested_tokens_temp + 1;
                end
 
            end
        end
    end
 
    `ifdef ASYNC_RES
    always @(posedge clk or negedge res_n)  begin `else
    always @(posedge clk)  begin `endif
    if(!res_n) begin
        sum_requested_tokens <= {7{1'b0}};
    end else begin
        sum_requested_tokens <= sum_requested_tokens_temp;
    end
    end
 
    //Monitor remaining tokens in the openHMC RX input buffer
    reg [LOG_MAX_RX_TOKENS-1:0] rx_tokens_av;
    assign rf_rx_tokens_av = rx_tokens_av;
 
    `ifdef ASYNC_RES
    always @(posedge clk or negedge res_n)  begin `else
    always @(posedge clk)  begin `endif
    if(!res_n) begin
        rx_tokens_av     <= {LOG_MAX_RX_TOKENS{1'b0}};
    end else begin
        if(state==INIT_TX_NULL_1)begin
            //initialize token counts when HMC init is not done
            rx_tokens_av        <= rf_rx_buffer_rtc;
        end else begin
            //calculate remaining tokens in RX buffers
            rx_tokens_av        <= rx_tokens_av + rx_hmc_tokens_to_return - sum_requested_tokens;
        end
    end
    end
 
end else begin
    assign rf_rx_tokens_av = {LOG_MAX_RX_TOKENS{1'b0}};
end
endgenerate
 
//=======================================================================================================================
//---------------------------------ALL OTHER LOGIC HERE
//=======================================================================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
    if(!res_n) begin
 
        //----Init Regs
        for(i_t=0;i_t<TS1_SEQ_INC_VAL_PER_CYCLE;i_t=i_t+1) begin    //set
            ts1_seq_nr_per_flit[i_t]<= i_t;
        end
        num_null_cycles_sent             <= {LOG_CYCLES_NULL_TO_SEND{1'b0}};
 
        //General
        init_state                  <= INIT_TX_NULL_1;
        rtc_rx_initialize           <= 1'b1;
    end
    else begin
 
        case(init_state)
            //---------------------------------INIT. Refer to Initialization section in the specification
 
            INIT_TX_NULL_1: begin
                //---init_state---
                if(rf_hmc_received_init_null)begin
                    init_state            <= INIT_TX_TS1;
                end
 
            end
 
            INIT_TX_TS1: begin
 
                rtc_rx_initialize   <= 1'b0;
                for(i_t=0;i_t<TS1_SEQ_INC_VAL_PER_CYCLE;i_t=i_t+1) begin
                    ts1_seq_nr_per_flit[i_t]    <= ts1_seq_nr_per_flit[i_t] + TS1_SEQ_INC_VAL_PER_CYCLE;
                end
 
                //---init_state---
                if(rf_descramblers_aligned)begin
                    init_state   <= INIT_TX_NULL_2;
                end
 
            end
 
            INIT_TX_NULL_2: begin
                //Issue at least 32 NULL FLITs before going active
                if(&num_null_cycles_sent && rf_link_is_up) begin
                        init_state <= INIT_DONE;
                end 
                num_null_cycles_sent <= num_null_cycles_sent + 1;
            end
            default: begin
            end
        endcase
 
        if(!LXTXPS || rf_warm_reset) begin
            init_state          <= INIT_TX_NULL_1;
            if(rf_warm_reset)
                rtc_rx_initialize   <= 1'b1;
        end
 
    end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
`ifdef RESET_ALL
    if(!res_n) begin
        for(i_f=0;i_f<FPW;i_f=i_f+1)    data2rtc_stage_flit[i_f] <= {128{1'b0}};
        for(i_f=0;i_f<FPW-1;i_f=i_f+1)  d_in_buf_flit[i_f]       <= {128{1'b0}};
    end else
`endif
begin    
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        data2rtc_stage_flit[i_f]    <= {128{1'b0}};
    end
 
    case(state)
 
            INIT: begin
                if(init_state == INIT_TX_TS1) begin
 
                    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
                        data2rtc_stage_flit[i_f]    <= ts1_flit[i_f];
                    end
                end
            end
 
            IDLE: begin
                if(|remaining_tokens && !ram_full)begin
                    data2rtc_stage_flit[0]            <= {{64{1'b0}},tret_hdr};
                end
            end
 
            TX: begin
                //Choose the data source
                if(d_in_use_buf) begin
                    for(i_f=0;i_f<FPW-1;i_f=i_f+1) begin
                        data2rtc_stage_flit[i_f+1]        <= d_in_buf_flit[i_f];
                    end
                end else begin
                    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
                        data2rtc_stage_flit[i_f]        <= d_in_flit[i_f];
                    end
                end
 
                for(i_f=0;i_f<FPW-1;i_f=i_f+1)begin
                    //No matter what, fill the buffer
                    d_in_buf_flit[i_f]              <= d_in_flit[i_f+1];
                end
            end
 
            HMC_RTRY: begin
                for(i_f=0;i_f<FPW;i_f=i_f+1)begin //Send IRTRY start retry
                    data2rtc_stage_flit[i_f]        <= {48'h0,8'b00000001,8'h00,irtry_hdr};
                end
            end
 
            LNK_RTRY: begin
                    for(i_f=0;i_f<FPW;i_f=i_f+1)begin   //Send IRTRY clear error abort
                        data2rtc_stage_flit[i_f]        <= {48'h0,8'b00000010,8'h00,irtry_hdr};
                    end
            end
    endcase
end
 
if(!res_n) begin
    data2rtc_stage_flit_is_hdr      <= {FPW{1'b0}};
    data2rtc_stage_flit_is_tail     <= {FPW{1'b0}};
    data2rtc_stage_flit_is_valid    <= {FPW{1'b0}};
    data2rtc_stage_is_flow          <= 1'b0;
 
    data2rtc_stage_force_tx_retry   <= 1'b0;
    d_in_shift_out                  <= 1'b0;
 
    //----Reset the input buffer reg
    d_in_buf_flit_is_hdr            <= {FPW-1{1'b0}};
    d_in_buf_flit_is_valid          <= {FPW-1{1'b0}};
    d_in_use_buf                    <= 1'b0;
 
    //General
    state                           <= INIT;
 
    //Token Flow Control
    remaining_tokens                <= {LOG_MAX_RX_TOKENS{1'b0}};
    rtc_return_val                  <= {5{1'b0}};
    rtc_return                      <= 1'b0;
 
    //Retry
    irtry_start_retry_cnt       <= {5{1'b0}};
    irtry_clear_error_cnt       <= {5{1'b0}};
 
    //HMC Control
    LXRXPS                          <= 1'b1;
 
    //Flow Control
    tx_link_retry_request           <= 1'b0;
 
end
else begin
//====================================================================
//---------------------------------INIT
//====================================================================
    //Reset control signals
    d_in_shift_out              <= 1'b0;
    irtry_start_retry_cnt       <= {5{1'b0}};
    irtry_clear_error_cnt       <= {5{1'b0}};
 
    //HMC Control
    LXRXPS                      <= 1'b1;
 
    if(rx_force_tx_retry)begin
        tx_link_retry_request   <= 1'b1;
    end
 
    //RTC
    rtc_return       <= 1'b0;
    //Initialize rtc to be transmitted after reset and warm reset
    if(rtc_rx_initialize) begin
        remaining_tokens <= rf_rx_buffer_rtc;
    end else begin
        remaining_tokens <= remaining_tokens + rx_hmc_tokens_to_return + rx_hmc_poisoned_tokens_to_return;
    end
 
    //Reset information bits
    data2rtc_stage_flit_is_hdr     <= {FPW{1'b0}};
    data2rtc_stage_flit_is_tail    <= {FPW{1'b0}};
    data2rtc_stage_flit_is_valid   <= {FPW{1'b0}};
    data2rtc_stage_is_flow         <= 1'b0;
    data2rtc_stage_force_tx_retry  <= 1'b0;
 
    rtc_return_val      <= outstanding_tokens_to_return;
 
    case(state)
 
//====================================================================
//---------------------------------Normal operation (including init TRETs)
//====================================================================
// Some branches to other states may be removed in HMC_RTRY for instance.
// Saves logic if an additional cycle in IDLE is acceptable
 
        INIT: begin
            if(init_state==INIT_DONE) state <= IDLE;
        end
 
        IDLE: begin
        //Issue NULL Flits if there's nothing else to do
 
            //SEND TRET PACKET even if there are no tokens available
            if(|remaining_tokens && !ram_full)begin
                data2rtc_stage_flit_is_hdr[0]     <= 1'b1;
                data2rtc_stage_flit_is_tail[0]    <= 1'b1;
                data2rtc_stage_flit_is_valid[0]   <= 1'b1;
 
                remaining_tokens    <= remaining_tokens + rx_hmc_tokens_to_return + rx_hmc_poisoned_tokens_to_return - outstanding_tokens_to_return;
                rtc_return          <= 1'b1;
            end
 
            // //---State---
            if(force_hmc_retry) begin
                state <= HMC_RTRY;
            end else if(tx_link_retry_request) begin
                state <= LNK_RTRY;
            end else if(rf_hmc_sleep_requested) begin
                state <= SLEEP;
            end else if(!d_in_empty && !ram_full && hmc_tokens_av) begin
                state           <= TX;
                d_in_shift_out  <= ~d_in_use_buf;
            end
 
        end
 
        TX: begin
        //Get and transmit data
 
            //First set control signals
            d_in_use_buf    <= 1'b0;
            d_in_shift_out  <= 1'b1;
 
            //Fill the buffer
            d_in_buf_flit_is_hdr         <= d_in_flit_is_hdr[FPW-1:1];
            d_in_buf_flit_is_valid       <= d_in_flit_is_valid[FPW-1:1];
 
            //If there is data buffered - use it
            data2rtc_stage_flit_is_hdr   <= d_in_use_buf ? {d_in_buf_flit_is_hdr,1'b0}   : d_in_flit_is_hdr;
            data2rtc_stage_flit_is_tail  <= d_in_use_buf ? {FPW{1'b0}}                   : d_in_flit_is_tail;
            data2rtc_stage_flit_is_valid <= d_in_use_buf ? {d_in_buf_flit_is_valid,1'b0} : d_in_flit_is_valid;
 
            //Set RTC to be added in the next step
            if( |remaining_tokens &&
                (!d_in_use_buf && |d_in_flit_is_tail)
            ) begin
                remaining_tokens    <= remaining_tokens + rx_hmc_tokens_to_return + rx_hmc_poisoned_tokens_to_return - outstanding_tokens_to_return;
                rtc_return          <= 1'b1;
            end
 
            //Exit state if seen a tail and exit condition occured
            if(     ((!d_in_use_buf && |d_in_flit_is_tail)) &&
                    (force_hmc_retry || ram_full || tx_link_retry_request || !hmc_tokens_av || d_in_a_empty)) begin
 
                d_in_shift_out  <= 1'b0;
 
 
                case ({force_hmc_retry,tx_link_retry_request})
                    2'b00: state    <= IDLE;
                    2'b01: state    <= LNK_RTRY;
                    default: state  <= HMC_RTRY;
                endcase
 
                for(i_f=0;i_f<FPW;i_f=i_f+1)begin
                    if(!d_in_use_buf && d_in_flit_is_tail[i_f])begin
                        data2rtc_stage_flit_is_valid    <= {FPW{1'b1}} >> {FPW-1-i_f};
                    end
                end
 
                for(i_f=1;i_f<FPW;i_f=i_f+1)begin
                    if(d_in_flit_is_tail[i_f])begin
                        d_in_buf_flit_is_hdr            <= d_in_flit_is_hdr[FPW-1:1] & ({FPW-1{1'b1}} << i_f);
                        d_in_buf_flit_is_valid          <= d_in_flit_is_valid[FPW-1:1] & ({FPW-1{1'b1}} << i_f);
                    end
                end
 
                //Use buf next time TX state is entered if there is a packet pending
                if(!d_in_use_buf && (d_in_flit_is_hdr[FPW-1:1] > d_in_flit_is_tail[FPW-1:1]))begin
                    d_in_use_buf    <= 1'b1;
                end
            end
        end
 
    //---------------------------------An error in RX path occured - send irtry start packets
        HMC_RTRY: begin
 
            data2rtc_stage_is_flow          <= 1'b1;
 
            irtry_start_retry_cnt               <= irtry_start_retry_cnt + FPW;
 
            if(irtry_start_retry_cnt+FPW >= rf_irtry_to_send)begin
                irtry_start_retry_cnt           <= {5{1'b0}};
                state <= IDLE;
            end
 
        end
 
 
    //---------------------------------HMC sent start retry packets -
    //                                 re-send all valid packets in RAM after sending clear error packets
        LNK_RTRY: begin
 
            if(!tx_retry_ongoing && (tx_link_retry_request || |irtry_clear_error_cnt)) begin
 
                data2rtc_stage_is_flow          <= 1'b1;
 
                if(irtry_clear_error_cnt+FPW >= rf_irtry_to_send)begin
                    irtry_clear_error_cnt         <= {5{1'b0}};
                    data2rtc_stage_force_tx_retry <= 1'b1;
                end else begin
                    irtry_clear_error_cnt   <= irtry_clear_error_cnt + FPW;
                end
            end
 
            if(tx_retry_finished && !tx_link_retry_request) begin
                state <= IDLE;
            end
 
            if(!tx_retry_ongoing && !rx_force_tx_retry) begin
                tx_link_retry_request   <= 1'b0;
            end
        end
 
    //---------------------------------Power State Management
        SLEEP: begin
 
            if(rf_hmc_sleep_requested) begin
                LXRXPS          <= 1'b0;
            end else begin
                state           <= WAIT_FOR_HMC;
            end
 
        end
 
        WAIT_FOR_HMC: begin
 
            if(LXTXPS) begin
                state           <= INIT;
            end
 
        end
 
    endcase
 
    //Warm Reset
    if(rf_warm_reset) begin
        //in case of a warm reset request, continue at INIT_TX_NULL_2 sequence and intialize tokens to be returned
        state       <= INIT;
    end
 
end
end
 
//====================================================================
//---------------------------------HMC input buffer Token Handling
//====================================================================
//Count the tokens that were used and make sure the HMC has enough tokens in its input buffer left
//This always block remains combinational to save one cycle
always @(*)  begin
 
    num_flits_transmitted = {LOG_FPW+1{1'b0}};
    num_flits_in_buf      = {LOG_FPW{1'b0}};
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        if(d_in_flit_is_valid[i_f] && d_in_shift_out) begin
            num_flits_transmitted   = num_flits_transmitted + 1;
        end
    end
    for(i_f=0;i_f<FPW-1;i_f=i_f+1)begin
        if(d_in_buf_flit_is_valid[i_f] && d_in_use_buf) begin
            num_flits_in_buf = num_flits_in_buf + 1;
        end
    end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
if(!res_n) begin
    rf_hmc_tokens_av    <= {LOG_MAX_HMC_TOKENS{1'b0}};
end else begin
    rf_hmc_tokens_av    <= rf_hmc_tokens_av + rx_returned_tokens - num_flits_transmitted;
end
end
 
//====================================================================
//---------------------------------Counter in the RF, currently only data transactions are counted
//====================================================================
always @(*) begin
 
    rf_sent_p_comb   = {LOG_FPW+1{1'b0}};
    rf_sent_np_comb  = {LOG_FPW+1{1'b0}};
    rf_sent_r_comb   = {LOG_FPW+1{1'b0}};
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        if(data2seq_frp_stage_flit_is_hdr[i_f])begin
        //split into independent cases to avoid dependencies
        //Instead of comparing the entire cmd field, try to reduce logic effort
 
            //All non-posted types have either bit 3 or 4 in the cmd set:
            if( data2seq_frp_stage_flit[i_f][3] ^ data2seq_frp_stage_flit[i_f][4] ) begin
                rf_sent_np_comb = rf_sent_np_comb + {{LOG_FPW{1'b0}},1'b1};
            end
 
            //Only reads have bit 4 and 5 set:
            if(data2seq_frp_stage_flit[i_f][4] && data2seq_frp_stage_flit[i_f][5] ) begin
                rf_sent_r_comb = rf_sent_r_comb + {{LOG_FPW{1'b0}},1'b1};
            end
 
            //Otherwise it's a posted write
            if(cmd_type(data2seq_frp_stage_flit[i_f])==PKT_P_WRITE)begin
                rf_sent_p_comb = rf_sent_p_comb + {{LOG_FPW{1'b0}},1'b1};
            end
 
        end
    end
end
 
 
 
`ifdef XILINX
    openhmc_counter48_wrapper_xilinx #(
        .INC_SIZE(LOG_FPW+1),
        .PIPELINED(XIL_CNT_PIPELINED)
    ) cnt_sent_p (
        .clk(clk),
        .res_n(res_n),
        .inc_value(rf_sent_p_comb),
        .value(rf_sent_p)
    );
 
    openhmc_counter48_wrapper_xilinx #(
        .INC_SIZE(LOG_FPW+1),
        .PIPELINED(XIL_CNT_PIPELINED)
    ) cnt_sent_np (
        .clk(clk),
        .res_n(res_n),
        .inc_value(rf_sent_np_comb),
        .value(rf_sent_np)
    );
 
    openhmc_counter48_wrapper_xilinx #(
        .INC_SIZE(LOG_FPW+1),
        .PIPELINED(XIL_CNT_PIPELINED)
    ) cnt_sent_r (
        .clk(clk),
        .res_n(res_n),
        .inc_value(rf_sent_r_comb),
        .value(rf_sent_r)
    );    
`else
    reg  [RF_COUNTER_SIZE-1:0]    rf_sent_p_temp;
    reg  [RF_COUNTER_SIZE-1:0]    rf_sent_np_temp;
    reg  [RF_COUNTER_SIZE-1:0]    rf_sent_r_temp;
    assign rf_sent_p            = rf_sent_p_temp;
    assign rf_sent_np           = rf_sent_np_temp;
    assign rf_sent_r            = rf_sent_r_temp;
 
    `ifdef ASYNC_RES
    always @(posedge clk or negedge res_n)  begin `else
    always @(posedge clk)  begin `endif
    if(!res_n) begin
        rf_sent_p_temp   <= {RF_COUNTER_SIZE{1'b0}};
        rf_sent_np_temp  <= {RF_COUNTER_SIZE{1'b0}};
        rf_sent_r_temp   <= {RF_COUNTER_SIZE{1'b0}};
    end else begin
        rf_sent_p_temp   <= rf_sent_p_temp  + {{RF_COUNTER_SIZE-LOG_FPW-1{1'b0}},rf_sent_p_comb};
        rf_sent_np_temp  <= rf_sent_np_temp + {{RF_COUNTER_SIZE-LOG_FPW-1{1'b0}},rf_sent_np_comb};
        rf_sent_r_temp   <= rf_sent_r_temp  + {{RF_COUNTER_SIZE-LOG_FPW-1{1'b0}},rf_sent_r_comb};
    end
    end
`endif 
 
//====================================================================
//---------------------------------HMC Retry Logic
//====================================================================
//Monitor RX error abort mode - if the timer expires send another series of start retry packets
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
if(!res_n) begin
    error_abort_mode_clr_cnt       <= {8{1'b0}};
    force_hmc_retry                <= 1'b0;
    rf_error_abort_not_cleared     <= 1'b0;
end else begin
 
    rf_error_abort_not_cleared     <= 1'b0;
 
    if(rx_error_abort_mode)begin
        error_abort_mode_clr_cnt   <= error_abort_mode_clr_cnt + 1; //decrement counter
    end
 
    if(rx_error_abort_mode_cleared) begin
        error_abort_mode_clr_cnt   <= {8{1'b0}};
    end
 
    if(&error_abort_mode_clr_cnt) begin
        rf_error_abort_not_cleared  <= 1'b1;
    end
 
    if((rx_error_abort_mode && state!=HMC_RTRY && |error_abort_mode_clr_cnt==1'b0) || (&error_abort_mode_clr_cnt))begin
        force_hmc_retry             <= 1'b1;
 
    end else begin
        if(state==HMC_RTRY)begin
            force_hmc_retry     <= 1'b0;
        end
    end
 
end
end
 
//====================================================================
//---------------------------------RTC Stage
//====================================================================
generate
if(OPEN_RSP_MODE==0) begin : RTC_stage
    reg  [4:0]      data2seq_frp_stage_flit_rtc     [FPW-1:0];
    reg             rtc_return_sent;
 
    always @(*)  begin
        rtc_return_sent = 0;
 
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
            if(data2rtc_stage_flit_is_tail[i_f] && !rtc_return_sent && rtc_return) begin
                //Return outstanding tokens, but only once per cycle
                data2seq_frp_stage_flit_rtc[i_f] = rtc_return_val;
                rtc_return_sent                  = 1'b1;
            end else begin
                data2seq_frp_stage_flit_rtc[i_f] = 5'h00;
            end
        end
    end
 
    `ifdef ASYNC_RES
    always @(posedge clk or negedge res_n)  begin `else
    always @(posedge clk)  begin `endif
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        `ifdef ASYNC_RES
        if(!res_n)
            data2seq_frp_stage_flit[i_f]  <= {128{1'b0}};
        else 
        `endif
        begin  
            data2seq_frp_stage_flit[i_f]        <= data2rtc_stage_flit[i_f];
            if(data2rtc_stage_flit_is_tail[i_f]) begin
                data2seq_frp_stage_flit[i_f][64+31:64+27]   <= data2seq_frp_stage_flit_rtc[i_f];
            end
        end
    end
    end
end else begin
 
    `ifdef ASYNC_RES
    always @(posedge clk or negedge res_n)  begin `else
    always @(posedge clk)  begin `endif
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
            `ifdef ASYNC_RES
            if(!res_n)
                data2seq_frp_stage_flit[i_f]  <= {128{1'b0}};
            else 
            `endif
            begin        
                data2seq_frp_stage_flit[i_f]  <= data2rtc_stage_flit[i_f];
            end
        end
    end
end
endgenerate
 
    `ifdef ASYNC_RES
    always @(posedge clk or negedge res_n)  begin `else
    always @(posedge clk)  begin `endif
    `ifdef RESET_ALL
        if(!res_n) begin
            data2seq_frp_stage_flit_is_hdr    <= {FPW{1'b0}};
            data2seq_frp_stage_flit_is_tail   <= {FPW{1'b0}};
            data2seq_frp_stage_flit_is_valid  <= {FPW{1'b0}};
            data2seq_frp_stage_is_flow        <= 1'b0;
            data2seq_frp_stage_force_tx_retry <= 1'b0;
        end else 
    `endif
    begin
        data2seq_frp_stage_flit_is_hdr    <= data2rtc_stage_flit_is_hdr & data2rtc_stage_flit_is_valid;
        data2seq_frp_stage_flit_is_tail   <= data2rtc_stage_flit_is_tail & data2rtc_stage_flit_is_valid;
        data2seq_frp_stage_flit_is_valid  <= data2rtc_stage_flit_is_valid;
        data2seq_frp_stage_is_flow        <= data2rtc_stage_is_flow;
        data2seq_frp_stage_force_tx_retry <= data2rtc_stage_force_tx_retry;
    end
    end
 
//====================================================================
//---------------------------------Seqnum and FRP Stage
//====================================================================
 
always @(*)  begin
    tx_seqnum_inc  = {LOG_FPW{1'b0}};
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        tx_seqnum_temp[i_f] = 0;
        if(data2seq_frp_stage_flit_is_tail[i_f])begin
            tx_seqnum_inc       = tx_seqnum_inc + 1;
            tx_seqnum_temp[i_f] = tx_seqnum + tx_seqnum_inc;
        end
    end
 
    target_temp[0] = next_target;
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        if(data2rtc_stage_flit_is_valid[i_f]) begin
             target_temp[i_f+1] = target_temp[i_f] + 1;
             if(target_temp[i_f+1]==FPW)
                target_temp[i_f+1]=0;
        end else begin
            target_temp[i_f+1] = target_temp[i_f];
        end
    end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
if(!res_n) begin
    //Reset the target RAM location and seqnum
    tx_seqnum   <= {LOG_FPW{1'b0}};
    next_target <= {LOG_FPW{1'b0}};
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        target[i_f]   <= {FPW{1'b0}};
    end
end else begin
    tx_seqnum   <= tx_seqnum  + tx_seqnum_inc;
    if(!data2rtc_stage_is_flow) begin
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
            target[i_f]             <= target_temp[i_f];
        end
        next_target <= target_temp[FPW];
    end
end
end
 
//Constant propagation, no need for reset condition
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        `ifdef RESET_ALL
        if(!res_n) data2ram_flit[i_f] <= {128{1'b0}};
        else
        `endif
        begin
            data2ram_flit[i_f]      <= data2seq_frp_stage_flit[i_f];
 
            if(data2seq_frp_stage_flit_is_tail[i_f]) begin
                data2ram_flit[i_f][64+15+3:64+8] <= {tx_seqnum_temp[i_f],tx_frp_adr[target[i_f]],target[i_f]};
            end
        end
    end
 
    data2ram_flit_is_hdr    <= data2seq_frp_stage_flit_is_hdr | {FPW{data2seq_frp_stage_is_flow}};
    data2ram_flit_is_tail   <= data2seq_frp_stage_flit_is_tail;
    data2ram_flit_is_valid  <= data2seq_frp_stage_flit_is_valid | {FPW{data2seq_frp_stage_is_flow}};
    data2ram_force_tx_retry <= data2seq_frp_stage_force_tx_retry;
if(!res_n) begin
    `ifdef RESET_ALL
        data2ram_flit_is_hdr    <= {FPW{1'b0}};
        data2ram_flit_is_tail   <= {FPW{1'b0}};
        data2ram_flit_is_valid  <= {FPW{1'b0}};
        data2ram_force_tx_retry <= 1'b0;
    `endif
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        tx_frp_adr[i_f]     <= {RAM_ADDR_SIZE{1'b0}};
    end
end else begin
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        if(data2seq_frp_stage_flit_is_valid[i_f]) begin
            tx_frp_adr[target[i_f]] <= tx_frp_adr[target[i_f]] + 1;
        end
    end
 
end
end
 
//====================================================================
//---------------------------------Fill RAM
//====================================================================
//-- Always assign FLITs to RAM write register
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        ram_w_data[target[i_f]] <= { data2seq_frp_stage_flit_is_valid[i_f],
                                     data2seq_frp_stage_flit_is_tail[i_f],
                                     data2seq_frp_stage_flit_is_hdr[i_f],
                                     data2seq_frp_stage_flit[i_f]
                                  };
 
        if(data2seq_frp_stage_flit_is_tail[i_f])begin
            ram_w_data[target[i_f]][64+15+3:64+8] <= {tx_seqnum_temp[i_f],tx_frp_adr[target[i_f]],target[i_f]};
        end
    end  
 
    if(!res_n) begin
        ram_w_en    <= {FPW{1'b0}};
    end else begin
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
            if(data2seq_frp_stage_flit_is_valid[i_f]) begin
                ram_w_en[target[i_f]]    <= 1'b1;
            end else begin
                ram_w_en[target[i_f]]    <= 1'b0;
            end
        end
    end
end
 
//====================================================================
//---------------------------------Select Data Source: Valid sources are the Retry Buffers or regular data stream.
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
    `ifdef RESET_ALL
    if(!res_n) data2rrp_stage_flit[i_f] <= {128{1'b0}};
    else
    `endif
        begin
 
            if(tx_retry_ongoing) begin
                //-- If there's a TX retry ongoing increment read address until it equals the write address
                data2rrp_stage_flit[i_f]    <= ram_r_data[i_f][127:0];
            end else begin
                //Propagate data from normal packet stream
                data2rrp_stage_flit[i_f]    <= data2ram_flit[i_f];
            end
        end
    end
 
if(!res_n) begin
    //Reset control signals
    tx_retry_finished   <= 1'b0;
    tx_retry_ongoing    <= 1'b0;
    rf_cnt_retry        <= 1'b0;
 
    //Ram
    ram_r_en            <= 1'b0;
    ram_r_addr_temp     <= {RAM_ADDR_SIZE{1'b0}};
    ram_r_mask          <= {FPW{1'b0}};
 
    //Data propagation
    data2rrp_stage_flit_is_hdr      <= {FPW{1'b0}};
    data2rrp_stage_flit_is_tail     <= {FPW{1'b0}};
    data2rrp_stage_flit_is_valid    <= {FPW{1'b0}};
 
end else begin
    tx_retry_finished   <= 1'b0;
    tx_retry_ongoing    <= 1'b0;
    rf_cnt_retry        <= 1'b0;
 
    ram_r_en            <= 1'b0;
    ram_r_addr_temp     <= {RAM_ADDR_SIZE{1'b0}};
    ram_r_mask          <= {FPW{1'b0}};
 
    //if there is a retry request coming set the ram address to last received rrp
    if(data2seq_frp_stage_force_tx_retry) begin
        ram_r_en            <= 1'b1;
        ram_r_addr_temp     <= ram_r_addr+1;
    end
 
    if(!tx_retry_ongoing) begin
 
        data2rrp_stage_flit_is_hdr      <= data2ram_flit_is_hdr;
        data2rrp_stage_flit_is_tail     <= data2ram_flit_is_tail;
        data2rrp_stage_flit_is_valid    <= data2ram_flit_is_valid;
 
        //Switch to retry if requested
        if(data2ram_force_tx_retry) begin
 
            if(ram_r_addr_temp == ram_w_addr_next) begin //if the next address is the write address -> no retry.
                tx_retry_finished   <= 1'b1;
            end else begin
                ram_r_mask          <= ({FPW{1'b1}}) << (rx_rrp[8-RAM_ADDR_SIZE-1:0]);
                ram_r_addr_temp     <= ram_r_addr_temp+1;
                ram_r_en            <= 1'b1;
                rf_cnt_retry        <= 1'b1;
                tx_retry_ongoing    <= 1'b1;
            end
        end
    end else begin
        //-- If there's a TX retry ongoing increment read addr until it equals the write address
 
        ram_r_mask          <= {FPW{1'b1}};
 
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
                data2rrp_stage_flit_is_hdr[i_f]     <= ram_r_mask[i_f] ? ram_r_data[i_f][128]   :1'b0 ;
                data2rrp_stage_flit_is_tail[i_f]    <= ram_r_mask[i_f] ? ram_r_data[i_f][128+1] :1'b0 ;
                data2rrp_stage_flit_is_valid[i_f]   <= ram_r_mask[i_f] ? ram_r_data[i_f][128+2] :1'b0 ;          
        end    
 
        //if the next address is the write address -> retry finished
        if(ram_r_addr_temp == ram_w_addr_next) begin
            for(i_f=0;i_f<FPW;i_f=i_f+1)begin
                if(i_f >= target[0] && !(tx_frp_adr[0]==tx_frp_adr[FPW-1]))begin
                    data2rrp_stage_flit_is_hdr[i_f]     <= 1'b0;
                    data2rrp_stage_flit_is_tail[i_f]    <= 1'b0;
                    data2rrp_stage_flit_is_valid[i_f]   <= 1'b0;
                end
            end
            tx_retry_finished   <= 1'b1;
        end else begin
            ram_r_addr_temp     <= ram_r_addr_temp + 1;
            tx_retry_ongoing    <= 1'b1;
            ram_r_en            <= 1'b1;
        end
 
    end
 
end
end
 
//====================================================================
//---------------------------------Add RRP
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
    `ifdef RESET_ALL
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
            data2crc_flit[i_f] <= {128{1'b0}};
        end
    `endif
    begin
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
            data2crc_flit[i_f]  <= (data2rrp_stage_flit_is_valid[i_f] || !init_state[1]) ? data2rrp_stage_flit[i_f] : {128{1'b0}};
 
            //Add the RRP
            if(data2rrp_stage_flit_is_tail[i_f] || (data2rrp_stage_flit_is_hdr[i_f] && is_req_flow(data2rrp_stage_flit[i_f])))begin
                data2crc_flit[i_f][64+7:64]     <= rx_hmc_frp;
            end
 
            //Increment the FRP by 1, It points to the next possible FLIT position -> retry will start there
            if(data2rrp_stage_flit_is_tail[i_f])begin
                data2crc_flit[i_f][64+15:64+8]  <= data2rrp_stage_flit[i_f][64+15:64+8] + 1;
            end
 
        end
        `ifdef SIMULATION
            if((last_transmitted_rx_hmc_frp != rx_hmc_frp) && !data2rrp_stage_flit_is_valid[0])begin `else 
            if(!data2rrp_stage_flit_is_valid[0] && send_prets)begin `endif
                data2crc_flit[0][63:0]          <= pret_hdr;
                data2crc_flit[0][64+7:64]       <= rx_hmc_frp;
            end
    end
 
if(!res_n) begin
    `ifdef SIMULATION
        //----Reset control signals
        last_transmitted_rx_hmc_frp <= {8{1'b0}};
    `else 
        send_prets <= 1'b0;
    `endif
 
    //----Data
    data2crc_flit_is_hdr    <= {FPW{1'b0}};
    data2crc_flit_is_tail   <= {FPW{1'b0}};
 
end else begin
 
    //Propagate signals
    data2crc_flit_is_hdr  <= data2rrp_stage_flit_is_hdr;
    data2crc_flit_is_tail <= data2rrp_stage_flit_is_tail |  ((data2rrp_stage_flit_is_hdr[FPW-1] && cmd(data2rrp_stage_flit[FPW-1])==CMD_IRTRY) ? {FPW{1'b1}} : {FPW{1'b0}}) ;
 
    `ifdef SIMULATION
        //If there is a tail, remember the last transmitted RRP. Otherwise generate PRET if there is a new RRP
        if(|data2rrp_stage_flit_is_tail)begin
            last_transmitted_rx_hmc_frp     <= rx_hmc_frp;
        end 
        if((last_transmitted_rx_hmc_frp != rx_hmc_frp) && !data2rrp_stage_flit_is_valid[0])begin
            data2crc_flit_is_hdr[0]         <= 1'b1;
            data2crc_flit_is_tail[0]        <= 1'b1;
            last_transmitted_rx_hmc_frp     <= rx_hmc_frp;
        end
    `else 
 
        if(|data2crc_flit_is_hdr) send_prets <= 1'b1;
        if(rf_hmc_sleep_requested || rf_warm_reset) send_prets <= 1'b0;      
 
        if(!data2rrp_stage_flit_is_valid[0] && send_prets)begin
            data2crc_flit_is_hdr[0]         <= 1'b1;
            data2crc_flit_is_tail[0]        <= 1'b1;
        end   
    `endif
 
end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
//Retry Buffer
generate
    for(f=0;f<FPW;f=f+1)begin : retry_buffer_gen
        openhmc_ram #(
            .DATASIZE(128+3),      //FLIT + tail/hdr/valid indicator
            .ADDRSIZE(RAM_ADDR_SIZE)
        )
        retry_buffer_per_lane_I
        (
            .clk(clk),
            .wen(ram_w_en[f]),
            .wdata(ram_w_data[f]),
            .waddr(tx_frp_adr[f]),
            .ren(ram_r_en),
            .raddr(ram_r_addr_temp),
            .rdata(ram_r_data[f])
        );
    end
endgenerate
 
//HMC CRC Logic
tx_crc_combine #(
    .DWIDTH(DWIDTH),
    .FPW(FPW),
    .LOG_FPW(LOG_FPW)
)
tx_crc_combine_I
(
    .clk(clk),
    .res_n(res_n),
    .d_in_hdr(data2crc_flit_is_hdr),
    .d_in_tail(data2crc_flit_is_tail),
    .d_in_data(data2crc),
    .d_out_data(data_rdy)
);
 
//Scrambler
generate
    for(n=0;n<NUM_LANES;n=n+1) begin : scrambler_gen
        tx_scrambler #(
            .LANE_WIDTH(LANE_WIDTH),
            .HMC_RX_AC_COUPLED(HMC_RX_AC_COUPLED)
        )
        scrambler_I
        (
            .clk(clk),
            .res_n(res_n),
            .disable_scrambler(rf_scrambler_disable),
            .seed(seed_lane[n]), // unique per lane
            .data_in(data_to_scrambler[n*LANE_WIDTH+LANE_WIDTH-1:n*LANE_WIDTH]),
            .data_out(phy_scrambled_data_out[n*LANE_WIDTH+LANE_WIDTH-1:n*LANE_WIDTH]),
            .rf_run_length_enable(rf_run_length_enable && ~rf_scrambler_disable),
            .rf_run_length_bit_flip(bit_was_flipped[n])
        );
    end
endgenerate
 
endmodule
`default_nettype wire
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.