URL
https://opencores.org/ocsvn/pcie_ds_dma/pcie_ds_dma/trunk
Subversion Repositories pcie_ds_dma
[/] [pcie_ds_dma/] [trunk/] [core/] [ds_dma64/] [pcie_src/] [pcie_core64_m1/] [source/] [tlm_rx_data_snk.v] - Rev 17
Go to most recent revision | Compare with Previous | Blame | View Log
//----------------------------------------------------------------------------- // // (c) Copyright 2009-2010 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : V5-Block Plus for PCI Express // File : tlm_rx_data_snk.v //-------------------------------------------------------------------------------- //-------------------------------------------------------------------------------- /***************************************************************************** * Description : Rx Data Sink * * Hierarchical : tlm_rx * tlm_rx_data_snk * * malformed_checks * pwr_mgmt * bar_hit * * Functional : * Takes incoming packets, examines the packet for correct * construction and drops if it malformed. * Removes power management packets from the stream and signals * sideband to CMM * Rips out header control information for easier control downstream * ****************************************************************************/ `timescale 1ns/1ps `ifndef TCQ `define TCQ 1 `endif `ifndef PCIE `ifndef AS `define PCIE `endif `endif module tlm_rx_data_snk #(parameter DW = 32,// Data width parameter FCW = 6, // Packet credit width `ifdef PCIE parameter BARW = 7, // BAR-hit width parameter DOWNSTREAM_PORT = 0, // Endpoint or switch? `else // `ifdef AS parameter OVC = 0, // Any ordered VCs? parameter MVC = 0, // Any multicast VCs? `endif parameter MPS = 512,//Core MPS parameter TYPE1_UR = 0) // Type1 config bad? ( input clk_i, input reset_i, //-------------------------------------------------------- // Datapath signals //-------------------------------------------------------- // To FIFO output reg [DW-1:0] d_o, // Data output reg sof_o, // ll sof output reg eof_o, // ll eof output reg preeof_o, // ll eof - one cycle early output reg src_rdy_o, // ll src_rdy output reg rem_o, // ll rem (in words) output reg dsc_o, // ll dsc output reg cfg_o, // Config packet, @bar `ifdef PCIE output reg np_o, // Non-posted packet, @bar output reg cpl_o, // Completion packet, @bar output reg locked_o, // Locked msg or cpl, @bar output reg [BARW-1:0] bar_o, // Bar hit, @bar output reg rid_o, // RID hit, @bar output reg vend_msg_o, // Vendor-defined MSG output reg bar_src_rdy_o, // ll src_rdy `endif // To Flow controller output reg fc_use_p_o, // posted update.. implies 1 hdr output reg fc_use_np_o, // nonposted update.. '' `ifdef PCIE output reg fc_use_cpl_o, // compl update.. '' `endif output reg [FCW-1:0] fc_use_data_o, // number of data credits used output reg fc_unuse_o, // ll src_rdy.. implies 1 header // From LLM input [DW-1:0] d_i, // Data input sof_i, // ll sof input eof_i, // ll eof input rem_i, // ll rem in binary bytes input src_rdy_i, // ll src_rdy input src_dsc_i, // ll dsc //-------------------------------------------------------- // Sideband signals //-------------------------------------------------------- // InitFC communication to LLM output reg vc_hit_o, // TLP received on VC0 // Power management signals for CMM `ifdef PCIE output pm_as_nak_l1_o, // Pkt detected, implies src_rdy output pm_turn_off_o, // Pkt detected, implies src_rdy output pm_set_slot_pwr_o, // Pkt detected, implies src_rdy output [9:0] pm_set_slot_pwr_data_o, // value of field input pm_suspend_req_i, // Go into pm.. drop packets `else // `ifdef AS input [1:0] lnk_state_i, // Link state input lnk_state_src_rdy_i, // New link state valid `endif `ifdef PCIE // Completion event information for CMM output reg [47:0] err_tlp_cpl_header_o, // Header fields output reg err_tlp_p_o, // Pkt is posted output reg err_tlp_ur_o, // Unsupported req, implies src_rdy output reg err_tlp_ur_lock_o, // Unsupported req due to Lock, implies src_rdy output reg err_tlp_uc_o, // Unsupported cpl, implies src_rdy output reg err_tlp_malformed_o, // Pkt is badly constructed, // implies src_rdy // status register in the CMM output reg stat_tlp_cpl_ep_o, // cpl inc pkt poison output reg stat_tlp_cpl_abort_o, // cpl stat is abort output reg stat_tlp_cpl_ur_o, // cpl stat is ur output reg stat_tlp_ep_o, // incoming pkt poison // Outgoing information to check CMM for bar hit output [63:0] check_raddr_o, // is address mapped? output check_mem32_o, output check_mem64_o, output check_rio_o, // implies src_rdy output check_rdev_o, // implies src_rdy output check_rbus_o, // implies src_rdy output check_rfun_o, // implies src_rdy // Incoming information from CMM on bar hit status input check_rhit_i, // match found input [BARW-1:0] check_rhit_bar_i, // address of match `else // `ifdef AS // PI-5 event information for CMM. output reg err_tlp_bad_header_crc_o, // Bad HCRC output reg err_tlp_bad_pi_chain_o, // Bad PI chain output reg err_tlp_bad_credit_length_o, // CR < length output reg err_tlp_invalid_credit_length_o, // CR > MPS output reg err_tlp_non_zero_turn_pointer_o, // Endpoints only output reg err_tlp_unsup_mvc_o, // MVC output reg err_tlp_unsup_ovc_o, // OVC output reg [159:0] err_tlp_type_b_header_o, // PI-5 rtn. info input err_tlp_type_b_ack_i, // PI-5 ack'd `endif // Static control from CMM `ifdef PCIE input [2:0] max_payload_i, // Enc val for max paysize allowed input rhit_bar_lat3_i, // BAR-hit latency 3 clocks? input legacy_mode_i, // For interp of the spec input legacy_cfg_access_i,//User implements legacy config? input ext_cfg_access_i, // User implements ext. config? input hotplug_msg_enable_i,//Pass obsolete hot-plug to user? `else // `ifdef AS input [3:0] max_payload_i, // Enc val for max paysize allowed input switch_mode_i, // Is core a Switch? input fabric_manager_mode_i, // Is core a Fabric Manager? input [31:0] cfg_ap0_space_end_i, // End of Aperture 0 range input [31:0] cfg_ap1_space_start_i, // Start of Aperture 1 range input [31:0] cfg_ap1_space_end_i, // End of Aperture 1 range `endif input td_ecrc_trim_i // Strip digest for user? ); //-------------------------------------------------------------------------- // Locally derived constants `ifdef PCIE //-------------------------------------------------------------------------- // Symbolic constants // Full type localparam MRD32 = 7'b00_00000; localparam MRD64 = 7'b01_00000; localparam MRD32LK = 7'b00_00001; localparam MRD64LK = 7'b01_00001; localparam MWR32 = 7'b10_00000; localparam MWR64 = 7'b11_00000; localparam IORD = 7'b00_00010; localparam IOWR = 7'b10_00010; localparam CFGRD0 = 7'b00_00100; localparam CFGWR0 = 7'b10_00100; localparam CFGRD1 = 7'b00_00101; localparam CFGWR1 = 7'b10_00101; localparam MSG = 7'b01_10xxx; localparam MSGD = 7'b11_10xxx; localparam MSGAS = 7'b01_11xxx; localparam MSGASD = 7'b11_11xxx; localparam CPL = 7'b00_01010; localparam CPLD = 7'b10_01010; localparam CPLLK = 7'b00_01011; localparam CPLDLK = 7'b10_01011; // Encoded Full type into "one hots" localparam MEM_BIT = 8; localparam ADR_BIT = 7; localparam MRD_BIT = 6; localparam MWR_BIT = 5; localparam MLK_BIT = 4; localparam IO_BIT = 3; localparam CFG_BIT = 2; localparam MSG_BIT = 1; localparam CPL_BIT = 0; // Memory and address-routed types are given an extra bits to improve // timing for BAR checks localparam [8:0] OTHERTYPE = 9'b0; localparam [8:0] MEMANY = 9'b1 << MEM_BIT; localparam [8:0] ADRANY = 9'b1 << ADR_BIT; localparam [8:0] MRDANY = (9'b1 << MRD_BIT) | ADRANY | MEMANY; localparam [8:0] MWRANY = (9'b1 << MWR_BIT) | ADRANY | MEMANY; localparam [8:0] MLKANY = (9'b1 << MLK_BIT) | ADRANY | MEMANY; localparam [8:0] IOANY = (9'b1 << IO_BIT) | ADRANY; localparam [8:0] CFGANY = 9'b1 << CFG_BIT; localparam [8:0] MSGANY = 9'b1 << MSG_BIT; localparam [8:0] CPLANY = 9'b1 << CPL_BIT; // Message code localparam UNLOCK = 8'b0000_0000; localparam PM_ACTIVE_STATE_NAK = 8'b0001_0100; localparam PM_PME = 8'b0001_1000; localparam PME_TURN_OFF = 8'b0001_1001; localparam PME_TO_ACK = 8'b0001_1011; localparam ATTENTION_INDICATOR_OFF = 8'b0100_0000; localparam ATTENTION_INDICATOR_ON = 8'b0100_0001; localparam ATTENTION_INDICATOR_BLINK = 8'b0100_0011; localparam POWER_INDICATOR_ON = 8'b0100_0101; localparam POWER_INDICATOR_BLINK = 8'b0100_0111; localparam POWER_INDICATOR_OFF = 8'b0100_0100; localparam ATTENTION_BUTTON_PRESSED = 8'b0100_1000; localparam SET_SLOT_POWER_LIMIT = 8'b0101_0000; localparam VENDOR_DEFINED_TYPE_0 = 8'b0111_1110; localparam VENDOR_DEFINED_TYPE_1 = 8'b0111_1111; // Route localparam ROUTE_BY_ID = 3'b010; // Format localparam FMT_3DW_NODATA = 2'b00; localparam FMT_4DW_NODATA = 2'b01; localparam FMT_3DW_WDATA = 2'b10; localparam FMT_4DW_WDATA = 2'b11; // Completion status localparam CPL_STAT_SC = 3'b000; localparam CPL_STAT_UR = 3'b001; localparam CPL_STAT_CRS = 3'b010; localparam CPL_STAT_CA = 3'b100; `endif // `ifdef PCIE //------------------------------------------------------------------ // Bit indices for aliasing `ifdef PCIE // First Dword localparam FULLTYPE_HI_IND = DW-2; localparam FULLTYPE_LO_IND = DW-8; localparam TC_HI_IND = DW-10; localparam TC_LO_IND = DW-12; localparam TD_IND = DW-17; localparam EP_IND = DW-18; localparam ATTR_HI_IND = DW-19; localparam ATTR_LO_IND = DW-20; localparam LENGTH_HI_IND = DW-23; localparam LENGTH_LO_IND = DW-32; // Second Dword localparam REQ_ID_HI_IND = 31; localparam REQ_ID_LO_IND = 16; localparam TAG_HI_IND = 15; localparam TAG_LO_IND = 8; localparam CPL_STAT_HI_IND = 15; localparam CPL_STAT_LO_IND = 13; // Third Dword localparam REQ_ID_CPL_HI_IND = DW-1; localparam REQ_ID_CPL_LO_IND = DW-16; localparam LOWER_ADDR32_HI_IND = DW-26; localparam LOWER_ADDR32_LO_IND = DW-30; localparam APERTURE_HI_IND = DW-21; localparam APERTURE_LO_IND = DW-24; localparam OFFSET_HI_IND = DW-25; localparam OFFSET_LO_IND = DW-30; // Fourth Dword localparam LOWER_ADDR64_HI_IND = 6; localparam LOWER_ADDR64_LO_IND = 2; // Data localparam SET_SLOT_PWRVAL_HI_IND = DW-1; localparam SET_SLOT_PWRVAL_LO_IND = DW-8; localparam SET_SLOT_PWRSCL_HI_IND = DW-15; localparam SET_SLOT_PWRSCL_LO_IND = DW-16; `else // `ifdef AS // First Dword localparam PI_1ST_HI_IND = DW-26; localparam PI_1ST_LO_IND = DW-32; localparam TC_HI_IND = DW-21; localparam TC_LO_IND = DW-23; localparam TD_IND = DW-24; localparam OO_IND = DW-20; localparam TS_IND = DW-19; localparam LENGTH_HI_IND = DW-14; localparam LENGTH_LO_IND = DW-18; localparam TURN_PTR_HI_IND = DW-8; localparam TURN_PTR_LO_IND = DW-12; localparam HCRC_HI_IND = DW-1; localparam HCRC_LO_IND = DW-7; // Second Dword localparam TURN_POOL_HI_IND= 30; localparam TURN_POOL_LO_IND= 0; localparam DIR_IND = 31; // Third Dword localparam PI_2ND_HI_IND = DW-26; localparam PI_2ND_LO_IND = DW-32; localparam APERTURE_HI_IND = DW-29; localparam APERTURE_LO_IND = DW-32; // Fourth Dword localparam PI_3RD_HI_IND = 6; localparam PI_3RD_LO_IND = 0; localparam OFFSET_HI_IND = 31; localparam OFFSET_LO_IND = 2; // Fifth Dword localparam PI_4TH_HI_IND = DW-26; localparam PI_4TH_LO_IND = DW-32; `endif // Delayed versions of input signals //-------------------------------------------------------- reg [6:1] sof_q; reg [6:1] eof_q; reg [6:1] eof_nd_q; reg [6:1] src_rdy_q; reg [6:1] dsc_q; reg [6:1] rem_q; reg cur_rem; // before TD change reg packet_ip; wire [DW-1:0] d_mux; reg [DW-1:0] d_q1, d_q2, d_q3, d_q4, d_q5, d_q6; // 2D makes NC unhappy //==================================================================== // Because certain operations take more time than might be available // in a packet, we need the information for the packet that's arriving // as well as the information from the packet that is exiting. Since // we're immediately registering the values when they come in we can // alias the D-input of the flops right to the data coming in. //==================================================================== //---------------------------------------------------------- // Latch enable signals //---------------------------------------------------------- // 64 bit 32 bit // ------------- ------ // sof_i | DW 1 | DW 2 | | DW 1 | // sof_q1 | DW 3 | DW 4 | | DW 2 | // sof_q2 ------------- | DW 3 | // sof_q3 | DW 4 | // ------ wire latch_1st_dword = sof_i && src_rdy_i; reg latch_1st_dword_q1, latch_1st_dword_q2, latch_1st_dword_q3, latch_1st_dword_q4; wire latch_2nd_dword = (DW == 32) ? sof_q[1]: sof_i && src_rdy_i; reg latch_2nd_dword_q1, latch_2nd_dword_q2; wire latch_3rd_dword = (DW == 32) ? sof_q[2] : sof_q[1]; reg latch_3rd_dword_q1; wire latch_4th_dword = (DW == 32) ? sof_q[3] : sof_q[1]; reg latch_4th_dword_q1; `ifdef AS wire latch_5th_dword = (DW == 32) ? sof_q[4] : sof_q[2]; `endif //----------------------------------------------------------- // First Dword //----------------------------------------------------------- `ifdef PCIE // Fulltype is used in packet type determination, and header type wire [6:0] fulltype_in = d_i[FULLTYPE_HI_IND:FULLTYPE_LO_IND]; reg [6:0] cur_fulltype; reg cur_fulltype_64, cur_fulltype_mem; wire cur_has_data = cur_fulltype[6]; wire [2:0] cur_routing = cur_fulltype[2:0]; reg [8:0] cur_fulltype_oh; reg cur_locked, cur_locked_q; reg cur_cpl; // Traffic class needs to be 0 for certain packets, also to CMM cpl wire [2:0] tc_in = d_i[TC_HI_IND:TC_LO_IND]; reg [2:0] cur_tc; reg cur_tc0; // The error poisoned bit gets forwarded with the packet wire ep_in = d_i[EP_IND]; reg cur_ep, cur_ep_q; // Attributes needs to be know for the CMM to construct a completion wire [1:0] attr_in = d_i[ATTR_HI_IND:ATTR_LO_IND]; reg [1:0] cur_attr; `else // `ifdef AS // Primary PI wire [6:0] pi_1st = d_i[PI_1ST_HI_IND:PI_1ST_LO_IND]; // Header CRC reg [6:0] cur_hcrc; // Turn Pointer reg [4:0] cur_turn_pointer; // Ordered-Only and Type-Specific reg cur_oo, cur_ts; `endif // TLP Digest/PCRC wire td_in = d_i[TD_IND]; reg cur_td, cur_td_q; // Length/Credits Required is used in correct length determination localparam LENW = LENGTH_HI_IND - LENGTH_LO_IND + 1; wire [9:0] length_in = d_i[LENGTH_HI_IND:LENGTH_LO_IND]; reg [9:0] cur_length; `ifdef PCIE reg cur_length1; `else // `ifdef AS reg np_o; // Local in AS, needed for credit tracking `endif reg cur_np; wire cur_cfg; //---------------------------------------------------------- // Second Dword //---------------------------------------------------------- `ifdef PCIE wire [15:0] req_id_in = d_i[REQ_ID_HI_IND:REQ_ID_LO_IND]; reg [15:0] cur_req_id; // Used in CMM cpl to mark pkts wire [7:0] tag_in = d_i[TAG_HI_IND:TAG_LO_IND]; reg [7:0] cur_tag; // Byte enables on boundaries wire [3:0] last_be_in = d_i[7:4]; reg [1:0] last_be_missing; wire [3:0] first_be_in = d_i[3:0]; reg [1:0] cur_first_be_adj; reg [1:0] first_be_missing; reg [2:0] cur_bytes_missing; reg [2:0] cur_byte_ct_1dw; reg [2:0] byte_ct_1dw; // Message types wire [7:0] msgcode_in = d_i[7:0]; reg [7:0] cur_msgcode; reg cur_vend_msg; `else // `ifdef AS // Turn Pool and Routing Direction reg [30:0] cur_turn_pool; reg cur_dir; // Route header (for Header CRC check, actually covers 2 DW) reg [50:0] cur_route_header; `endif //---------------------------------------------------------- // Third Dword //---------------------------------------------------------- `ifdef PCIE wire [15:0] req_id_cpl_in = d_i[REQ_ID_CPL_HI_IND: REQ_ID_CPL_LO_IND]; wire [31:0] addr_hi_in = d_i[DW-1:DW-32]; reg [31:0] cur_addr_hi; wire [6:2] lower_addr32_in = d_i[LOWER_ADDR32_HI_IND: LOWER_ADDR32_LO_IND]; wire [6:2] lower_addr64_in = d_i[LOWER_ADDR64_HI_IND: LOWER_ADDR64_LO_IND]; reg [6:2] lower_addr32_in_q, lower_addr64_in_q; wire [2:0] cpl_stat_in = d_i[CPL_STAT_HI_IND: CPL_STAT_LO_IND]; reg [2:0] cur_cpl_stat; `else // `ifdef AS // Secondary PI wire [6:0] pi_2nd = d_i[PI_2ND_HI_IND:PI_2ND_LO_IND]; `endif // PCIe config extended reg. number or AS PI-4 config address aperture wire [3:0] aperture = d_i[APERTURE_HI_IND:APERTURE_LO_IND]; //---------------------------------------------------------- // Third/Fourth Dword //---------------------------------------------------------- // Config TLP (3rd DW) or PI-4 config (4th DW) address offset wire [OFFSET_HI_IND-OFFSET_LO_IND+2:0] offset; assign offset = {d_i[OFFSET_HI_IND:OFFSET_LO_IND],2'b00}; //---------------------------------------------------------- // Fourth Dword //---------------------------------------------------------- `ifdef PCIE wire [31:0] addr_lo_i = d_i[31:0]; `else // `ifdef AS // Tertiary PI wire [6:0] pi_3rd = d_i[PI_3RD_HI_IND:PI_3RD_LO_IND]; `endif `ifdef AS //---------------------------------------------------------- // Fifth Dword //---------------------------------------------------------- // Quaternary PI wire [6:0] pi_4th = d_i[PI_4TH_HI_IND:PI_4TH_LO_IND]; `endif `ifdef PCIE //---------------------------------------------------------- // Data //---------------------------------------------------------- wire [9:0] pwr_data_i = {d_i[SET_SLOT_PWRSCL_HI_IND: SET_SLOT_PWRSCL_LO_IND], d_i[SET_SLOT_PWRVAL_HI_IND: SET_SLOT_PWRVAL_LO_IND]}; `endif //---------------------------------------------------------- // Derived signals //---------------------------------------------------------- // Data credits wire [FCW-1:0] cur_data_credits; wire cur_data_credits_vld; reg [FCW-1:0] fc_use_data_d; // Digest removal reg remove_lastword; // Bad or dropped packets `ifdef PCIE wire malformed; wire tlp_ur; wire tlp_ur_lock; wire tlp_uc; wire tlp_filt; reg [6:0] cur_lower_addr; // used to assemble cpl's reg [11:0] cur_byte_ct; // '' `else // `ifdef AS wire bad_header_crc; wire bad_pi_chain; wire bad_credit_length; wire invalid_credit_length; wire non_zero_turn_pointer; wire unsup_mvc; wire unsup_ovc; wire filter_drop; `endif reg cur_drop, next_cur_drop; `ifdef PCIE // Power management reg pwr_mgmt_mode_on; wire cur_pm_msg_detect; // packet types reg np_d, cpl_d, cfg_d, locked_d, vend_msg_d; // bar checks wire [BARW-1:0] rhit_bar_d; wire rhit_src_rdy; wire rhit_ack; wire rhit_lock; // cmm status reg cur_cpl_ep, cur_cpl_abort, cur_cpl_ur; reg [28:0] cur_cpl_header_fmt; reg [47:0] err_tlp_cpl_header_d; // obsolete packet types (hot-plug) wire cur_hp_msg_detect; `else // `ifdef AS // Storage of Type B header reg [5:0] load_type_b; reg type_b_pending; wire wr_hdr; wire rd_hdr; wire sof_hdr; wire [DW-1:0] hdr; `endif // data-path sync wire [2:0] out_d1; wire [2:0] out_d2; wire [2:0] out_d3; //================================================================ // EOF/Discontinue //================================================================ // Synchronize EOF events, including error reporting //---------------------------------------------------------------- `ifdef PCIE assign out_d1 = rhit_bar_lat3_i ? 6 : 5; `else // `ifdef AS assign out_d1 = 4; `endif assign out_d2 = out_d1 - 1; assign out_d3 = out_d1 - 2; //==================================================== // Credit transmissions //==================================================== // Output registers that drive the flow controller //---------------------------------------------------- always @(posedge clk_i) begin if (reset_i) begin fc_use_p_o <= #`TCQ 0; fc_use_np_o <= #`TCQ 0; `ifdef PCIE fc_use_cpl_o <= #`TCQ 0; `endif fc_unuse_o <= #`TCQ 0; // At this point we know if the packet is correctly // formed.. // np and cpl we can directly use the same control // going to the FIFO end else if (eof_q[out_d2] && !dsc_q[out_d2]) begin fc_use_np_o <= #`TCQ np_o; `ifdef PCIE fc_use_p_o <= #`TCQ !np_o && !cpl_o; fc_use_cpl_o <= #`TCQ cpl_o; `else // `ifdef AS fc_use_p_o <= #`TCQ !np_o; `endif // Packets that we dropped because we signal them // sideband or they are invalid, we 'fake' out // the flow controller by freeing those packets // immediately // Dsc in from the LLM is the only case we don't // do this-- which has priority over invalid // packets fc_unuse_o <= #`TCQ next_cur_drop; // all signals imply src ready, return back to zero end else begin fc_use_p_o <= #`TCQ 0; fc_use_np_o <= #`TCQ 0; `ifdef PCIE fc_use_cpl_o <= #`TCQ 0; `endif fc_unuse_o <= #`TCQ 0; end end // cur_data_credits may only be valid until eof_q3.. but // since this signal only has a quantity, latch it earlier always @(posedge clk_i) begin `ifdef PCIE if (!rhit_bar_lat3_i || (DW == 32)) `endif begin if (cur_data_credits_vld) begin fc_use_data_o <= #`TCQ cur_data_credits; end fc_use_data_d <= #`TCQ 0; `ifdef PCIE end else begin if (cur_data_credits_vld) begin fc_use_data_d <= #`TCQ cur_data_credits; end fc_use_data_o <= #`TCQ fc_use_data_d; `endif end end `ifdef PCIE //==================================================== // Status register updates for the CMM's registers //==================================================== // Output registers //------------------------------------------------- always @(posedge clk_i) begin if (reset_i) begin stat_tlp_ep_o <= #`TCQ 0; stat_tlp_cpl_ep_o <= #`TCQ 0; stat_tlp_cpl_abort_o <= #`TCQ 0; stat_tlp_cpl_ur_o <= #`TCQ 0; // at this point we know if the packet is valid so we // can safely communicate these status fields to the // cmm.. we can wait until eof5, because we might lose // the ep bit when multiple packets are in the pipe for // 64 bit end else if (eof_q[out_d2] && !dsc_q[out_d2] && !next_cur_drop) begin stat_tlp_ep_o <= #`TCQ cur_ep_q; stat_tlp_cpl_ep_o <= #`TCQ cur_cpl_ep; stat_tlp_cpl_abort_o <= #`TCQ cur_cpl_abort; stat_tlp_cpl_ur_o <= #`TCQ cur_cpl_ur; // all signals imply source ready, return to zero end else begin stat_tlp_ep_o <= #`TCQ 0; stat_tlp_cpl_ep_o <= #`TCQ 0; stat_tlp_cpl_abort_o <= #`TCQ 0; stat_tlp_cpl_ur_o <= #`TCQ 0; end end always @(posedge clk_i) begin if (reset_i) begin cur_cpl_ep <= #`TCQ 0; cur_cpl_abort <= #`TCQ 0; cur_cpl_ur <= #`TCQ 0; end else if (latch_2nd_dword_q2) begin // We need to know if completions are poisoned, or if have // their status fields set to abort or ur. // We're stealing one cycle to keep these calcs valid for // the output drivers if (cur_fulltype_oh[CPL_BIT]) begin cur_cpl_ep <= #`TCQ cur_ep; cur_cpl_abort <= #`TCQ cur_cpl_stat == CPL_STAT_CA; cur_cpl_ur <= #`TCQ cur_cpl_stat == CPL_STAT_UR; end else begin cur_cpl_ep <= #`TCQ 0; cur_cpl_abort <= #`TCQ 0; cur_cpl_ur <= #`TCQ 0; end end end //================================================================ // In the case of malformed packets, communicate data to the CMM // such that it can construct the completion header //================================================================ always @(posedge clk_i) begin if (reset_i) begin err_tlp_malformed_o <= #`TCQ 0; err_tlp_ur_o <= #`TCQ 0; err_tlp_ur_lock_o <= #`TCQ 0; err_tlp_uc_o <= #`TCQ 0; err_tlp_p_o <= #`TCQ 0; // If the LNK signaled dsc, then the packet never happened // if not, we can signal malformed // if not malformed, we can signal ur or uc // wait until eof4/5 -> the earliest time bar misses are known // as well as if the packet has invalid length // We don't need a return to 0 because eof is in the logic signal end else begin err_tlp_malformed_o <= #`TCQ eof_nd_q[out_d2] && malformed; err_tlp_ur_o <= #`TCQ (eof_nd_q[out_d2] && !malformed) && tlp_ur; err_tlp_ur_lock_o <= #`TCQ (eof_nd_q[out_d2] && !malformed) && tlp_ur_lock; err_tlp_uc_o <= #`TCQ (eof_nd_q[out_d2] && !malformed) && tlp_uc; // posted continuously valid -> no eof err_tlp_p_o <= #`TCQ !np_o; end end // The header is only looked at if there was a problem, always latch always @(posedge clk_i) begin // In order to save 48 flops, steal some time by delaying capture of // err_tlp_cpl_header as long as possible. // In 64-bit, worst case is eof_q2 of next == eof_q4 of current. // Current errors are latched on eof_q4, so we need to wait until // AFTER eof_q2 of next to make sure the next err_tlp_cpl_header is // not associated with any current TLP error. if (!rhit_bar_lat3_i || (DW == 32)) begin if (eof_q[3]) begin err_tlp_cpl_header_o <= #`TCQ {cur_lower_addr, cur_byte_ct, cur_cpl_header_fmt}; end // Unfortunately, we cannot do this in case of a three-clock BAR // latency with a 64-bit data path as the minimum TLP size is only // two clocks. end else begin if (eof_q[3]) begin err_tlp_cpl_header_d <= #`TCQ {cur_lower_addr, cur_byte_ct, cur_cpl_header_fmt}; end err_tlp_cpl_header_o <= #`TCQ err_tlp_cpl_header_d; end end always @(posedge clk_i) begin // For 64b, the most we can wait is 2 cycles for either 1st or // 2nd word. For 32b, we can wait 3 cycles on the 1st word // because we are guaranteed a gap if (latch_2nd_dword_q2) begin cur_cpl_header_fmt <= #`TCQ {cur_tc, cur_attr, cur_req_id, cur_tag}; end end `endif // Packets are dropped when they're malformed, unexpected/unsupported, // filtered or signaled sideband to the LLM such as power management. // This does not contain dsc, which has different credit rules. We // use the "next" signal in another place, which is why the flop is // split out from the logic cloud. //-------------------------------------------------------------------- always @* begin if (eof_q[out_d2]) begin `ifdef PCIE next_cur_drop = malformed || tlp_ur || tlp_uc || cur_pm_msg_detect || tlp_filt || (!hotplug_msg_enable_i && cur_hp_msg_detect); `else // `ifdef AS next_cur_drop = bad_header_crc || bad_pi_chain || bad_credit_length || invalid_credit_length || non_zero_turn_pointer || unsup_ovc || unsup_mvc || filter_drop; `endif end else begin next_cur_drop = 0; end end always @(posedge clk_i) begin if (reset_i) begin cur_drop <= #`TCQ 0; end else begin cur_drop <= #`TCQ next_cur_drop; end end //==================================================================== // Instantiation of malformed checks/drops // power management checks/drops // bar hits/drops // These are scheduled when we know that the fields are able to be // latched. All power managment sidebands are not allowed to actually // activate until we know that the packet is sound. //==================================================================== tlm_rx_data_snk_mal #( .DW (DW), .FCW (FCW), `ifdef PCIE .DOWNSTREAM_PORT (DOWNSTREAM_PORT), `else // `ifdef AS .OVC (OVC), .MVC (MVC), `endif .MPS (MPS), .TYPE1_UR (TYPE1_UR)) malformed_checks (.clk_i (clk_i), .reset_i (reset_i), .sof_i (sof_i && src_rdy_i && !packet_ip), .eof_i (eof_i && src_rdy_i && packet_ip), `ifdef PCIE .rem_i (rem_i), `endif .eval_formats_i (latch_2nd_dword_q1), .length_i (cur_length), `ifdef PCIE .length_1dw_i (cur_length1), `endif .aperture_i (aperture), .load_aperture_i (latch_3rd_dword), .offset_i (offset), `ifdef PCIE .eval_fulltype_i (latch_1st_dword), .fulltype_i (fulltype_in), .eval_msgcode_i (latch_2nd_dword), .msgcode_i (msgcode_in), .tc0_i (cur_tc0), .td_i (cur_td), .hit_src_rdy_i (rhit_src_rdy), .hit_ack_i (rhit_ack), .hit_lock_i (rhit_lock), .hit_i (rhit_d), `else // `ifdef AS .oo_i (cur_oo), .ts_i (cur_ts), .pi_1st_i (pi_1st), .pi_2nd_i (pi_2nd), .pi_3rd_i (pi_3rd), .pi_4th_i (pi_4th), .load_pi_1st_i (latch_1st_dword), .load_pi_2nd_i (latch_3rd_dword), .load_pi_3rd_i (latch_4th_dword), .load_pi_4th_i (latch_5th_dword), .load_offset_i (latch_4th_dword), .hcrc_i (cur_hcrc), .route_header_i (cur_route_header), .turn_pointer_i (cur_turn_pointer), .dir_i (cur_dir), `endif .data_credits_o (cur_data_credits), .data_credits_vld_o (cur_data_credits_vld), .cfg_o (cur_cfg), .hp_msg_detect_o (cur_hp_msg_detect), `ifdef PCIE .malformed_o (malformed), .tlp_ur_o (tlp_ur), .tlp_ur_lock_o (tlp_ur_lock), .tlp_uc_o (tlp_uc), .tlp_filt_o (tlp_filt), `else // `ifdef AS .bad_header_crc_o (bad_header_crc), .bad_pi_chain_o (bad_pi_chain), .bad_credit_length_o (bad_credit_length), .invalid_credit_length_o (invalid_credit_length), .non_zero_turn_pointer_o (non_zero_turn_pointer), .unsup_mvc_o (unsup_mvc), .unsup_ovc_o (unsup_ovc), .filter_drop_o (filter_drop), `endif .max_payload_i (max_payload_i), `ifdef PCIE .legacy_mode_i (legacy_mode_i), .legacy_cfg_access_i (legacy_cfg_access_i), .ext_cfg_access_i (ext_cfg_access_i), .hit_lat3_i (rhit_bar_lat3_i), .pwr_mgmt_on_i (pwr_mgmt_mode_on) `else // `ifdef AS .switch_mode_i (switch_mode_i), .fabric_manager_mode_i (fabric_manager_mode_i), .cmm_ap0_space_end_i (cfg_ap0_space_end_i), .cmm_ap1_space_start_i (cfg_ap1_space_start_i), .cmm_ap1_space_end_i (cfg_ap1_space_end_i), .lnk_state_i (lnk_state_i), .lnk_state_src_rdy_i (lnk_state_src_rdy_i) `endif ); `ifdef PCIE tlm_rx_data_snk_pwr_mgmt pwr_mgmt (.clk_i (clk_i), .reset_i (reset_i), .pm_as_nak_l1_o (pm_as_nak_l1_o), .pm_turn_off_o (pm_turn_off_o), .pm_set_slot_pwr_o (pm_set_slot_pwr_o), .pm_set_slot_pwr_data_o (pm_set_slot_pwr_data_o), .pm_msg_detect_o (cur_pm_msg_detect), // AS messages will get thrown out elsewhere as UR's .ismsg_i (cur_fulltype_oh[MSG_BIT]), .msgcode_i (cur_msgcode), .pwr_data_i (pwr_data_i), .eval_pwr_mgmt_i (latch_2nd_dword_q2), // The set slot power field is not known at the same // time as the message types .eval_pwr_mgmt_data_i (latch_4th_dword_q1), // This is the first time we know the packet it correct // -we only check bar hits for ROUTE_BY_ID, which is not // allowed for any of the pwr mgmt message types // Messages are never completion types .act_pwr_mgmt_i (eof_q[out_d3] && !(malformed || tlp_ur)) ); tlm_rx_data_snk_bar #( .BARW (BARW)) bar_hit (.clk_i (clk_i), .reset_i (reset_i), .check_raddr_o (check_raddr_o), .check_rmem64_o (check_mem64_o), .check_rmem32_o (check_mem32_o), .check_rio_o (check_rio_o), .check_rdev_id_o (check_rdev_o), .check_rbus_id_o (check_rbus_o), .check_rfun_id_o (check_rfun_o), .check_rhit_bar_i (check_rhit_bar_i), .check_rhit_i (check_rhit_i), .check_rhit_bar_o (rhit_bar_d), .check_rhit_o (rhit_d), .check_rhit_src_rdy_o (rhit_src_rdy), .check_rhit_ack_o (rhit_ack), .check_rhit_lock_o (rhit_lock), .addr_lo_i (addr_lo_i), .addr_hi_i (((DW == 32) && cur_fulltype_64) ? cur_addr_hi : addr_hi_in), .fulltype_oh_i (cur_fulltype_oh), .mem64_i (cur_fulltype_64), .routing_i (cur_routing), .req_id_i (cur_req_id), .req_id_cpl_i (req_id_cpl_in), // in 3rd dw, latch on 3rd .eval_check_i (cur_fulltype_64 ? latch_4th_dword: latch_3rd_dword), .rhit_lat3_i (rhit_bar_lat3_i), .legacy_mode_i (legacy_mode_i) ); `endif `ifdef PCIE //=================================================================== // Generate Byte Count and Lower Address fields for non-Successful // Completion Header using the byte enables as offsets, and the // byte counts as totals // Byte Count from table 2-21, page 90 PCI 1.1 spec // Lower address from table 2-22, page 91 PCI 1.1 spec //=================================================================== // convert the byte enable signals into actual bytes removed from // the length field //-------------------------------------------------------------------------- always @* begin casex (last_be_in) 4'b1xxx: last_be_missing = 0; // 1111 - all enabled, no offset 4'b01xx: last_be_missing = 1; 4'b001x: last_be_missing = 2; 4'b0001: last_be_missing = 3; // 0001 - 1 enabled, 3 offset default: last_be_missing = 0; endcase casex (first_be_in) 4'bxxx1: first_be_missing = 0; // 1111 - all enabled, no offset 4'bxx10: first_be_missing = 1; // 1110 - 1st 3 enabled, 1 offset 4'bx100: first_be_missing = 2; // 1100 - 1st 2 enables, 2 offset 4'b1000: first_be_missing = 3; // 1000 - 1st enabled, 3 offset default: first_be_missing = 0; // 0000 - no offset, 1 DW flush below endcase casex (first_be_in) // last_be_in must == 0000 4'b1xx1: byte_ct_1dw = 4; 4'b01x1: byte_ct_1dw = 3; 4'b1x10: byte_ct_1dw = 3; 4'b0011: byte_ct_1dw = 2; 4'b0110: byte_ct_1dw = 2; 4'b1100: byte_ct_1dw = 2; 4'b0001: byte_ct_1dw = 1; 4'b0010: byte_ct_1dw = 1; 4'b0100: byte_ct_1dw = 1; 4'bx000: byte_ct_1dw = 1; endcase end // Subtract from the total byte count (length x 4) based on the First // and Last DW BE fields. //-------------------------------------------------------------------------- always @(posedge clk_i) begin if (latch_2nd_dword) begin cur_bytes_missing <= #`TCQ first_be_missing + last_be_missing; end end always @(posedge clk_i) begin if (reset_i) begin cur_byte_ct_1dw <= #`TCQ 0; end else if (latch_2nd_dword) begin cur_byte_ct_1dw <= #`TCQ byte_ct_1dw; end end // We need to move the address forward to handle any empty bytes // in the payload.. this will be the start of the first actual // byte of payload always @(posedge clk_i) begin if (reset_i) begin cur_first_be_adj <= #`TCQ 0; end else if (latch_2nd_dword) begin cur_first_be_adj <= #`TCQ first_be_missing; end end //-------------------------------------------------------------------------- // Determine the Byte Count for the CMM to create a completion //-------------------------------------------------------------------------- always @(posedge clk_i) begin if (latch_2nd_dword_q2) begin casex (cur_fulltype) MRD32, MRD64, MRD32LK, MRD64LK: // for a 1 dword length, the last be is not involved, so // be sure not to use it if (cur_length1) begin cur_byte_ct <= #`TCQ cur_byte_ct_1dw; end else begin // length is in words- total length is length*4 // ..subtracting the bytes that don't particpate cur_byte_ct <= #`TCQ {cur_length,2'b00} - cur_bytes_missing; end // The Byte Count is set to 4 for Completions other than Memory Read default: cur_byte_ct <= #`TCQ 4; endcase end end //-------------------------------------------------------------------------- // Lower Address is calculated from the Address field for Memory Reads, // and is set to zero for all other transaction types. The lower address is // taken from the third dword in MR32 and from the fourth dword in MR64. //-------------------------------------------------------------------------- always @(posedge clk_i) begin if (cur_fulltype_64) begin if (latch_4th_dword_q1) begin if (cur_fulltype_mem) begin cur_lower_addr[6:2] <= #`TCQ lower_addr64_in_q; end else begin cur_lower_addr[6:2] <= #`TCQ 0; end end end else begin if (latch_3rd_dword_q1) begin if (cur_fulltype_mem) begin cur_lower_addr[6:2] <= #`TCQ lower_addr32_in_q; end else begin cur_lower_addr[6:2] <= #`TCQ 0; end end end end // The lower two bits are based on the First DW Byte Enables. always @(posedge clk_i) begin if (latch_3rd_dword_q1) begin if (cur_fulltype_mem) begin cur_lower_addr[1:0] <= #`TCQ cur_first_be_adj; end else begin cur_lower_addr[1:0] <= #`TCQ 0; end end end always @(posedge clk_i) begin lower_addr32_in_q <= #`TCQ lower_addr32_in; lower_addr64_in_q <= #`TCQ lower_addr64_in; end //======================================================================= // If directed to go to into management, let the current packet // complete, then reject following packets - used in malformed checks //======================================================================= always @(posedge clk_i) begin if (reset_i) begin pwr_mgmt_mode_on <= #`TCQ 0; end else if (sof_i) begin pwr_mgmt_mode_on <= #`TCQ pm_suspend_req_i; end end `endif // `ifdef PCIE //===================================================================== // Datapath pipe and associated control logic // there are only resets where absolutely required as we want // to infer SRLs wherever possible //===================================================================== // used to create clean local link packets... concatenating two packets // together because one had bad signalling will results in a malformed // packet, so we are covered //--------------------------------------------------------------------- always @(posedge clk_i) begin if (reset_i) begin packet_ip <= #`TCQ 0; end else if (src_rdy_i) begin packet_ip <= #`TCQ (sof_i || packet_ip) && !eof_i; end end //-------------------------------------------------------------------------- // The last qword of the frame is removed if it doesn't contain any header // or data information (contain only an unaligned TD dword) // If the TD is in the lower dword of the last qword, it is disabled by // inverting rem for 64b //-------------------------------------------------------------------------- always @(posedge clk_i) begin if (reset_i) begin remove_lastword <= #`TCQ 0; end else begin // defer calc until needed due to packet overlap if (eof_q[3]) begin if (DW == 64) begin remove_lastword <= #`TCQ !cur_rem && (cur_td_q && td_ecrc_trim_i); end else begin remove_lastword <= #`TCQ cur_td_q && td_ecrc_trim_i; end end else if (eof_o) begin remove_lastword <= #`TCQ 0; end end end // Control pipe //------------------------------------------------------------- always @(posedge clk_i) begin if (reset_i) begin sof_q[1] <= #`TCQ 0; eof_q[1] <= #`TCQ 0; src_rdy_q[1] <= #`TCQ 0; rem_q[1] <= #`TCQ 1; dsc_q[1] <= #`TCQ 0; eof_nd_q[1] <= #`TCQ 0; sof_o <= #`TCQ 0; end else begin // gate the input signals with src_rdy, and ensure valid // local link signalling sof_q[1] <= #`TCQ sof_i && src_rdy_i && !packet_ip; eof_q[1] <= #`TCQ eof_i && src_rdy_i && packet_ip; src_rdy_q[1] <= #`TCQ src_rdy_i && (packet_ip || sof_i); dsc_q[1] <= #`TCQ eof_i && src_rdy_i && packet_ip && src_dsc_i; eof_nd_q[1] <= #`TCQ eof_i && src_rdy_i && packet_ip && !src_dsc_i; // if we have rem, only modify it if we are actually removing the digest if (DW == 64) begin if (eof_i) begin rem_q[1] <= #`TCQ rem_i ^ (cur_td && td_ecrc_trim_i); cur_rem <= #`TCQ rem_i; end else begin rem_q[1] <= #`TCQ 1; end end else begin rem_q[1] <= #`TCQ 1; cur_rem <= #`TCQ 1; end sof_o <= #`TCQ sof_q[out_d1]; end end // Mux for last word when digest removal requires a forward. Turn off // src_rdy_o for one cycle if the last (unadjusted) data beat is // unaligned in 64-bit. In 32-bit, this cycle is always invalidated. always @(posedge clk_i) begin if (reset_i) begin src_rdy_o <= #`TCQ 0; dsc_o <= #`TCQ 0; rem_o <= #`TCQ 1; eof_o <= #`TCQ 0; preeof_o <= #`TCQ 0; end else if (remove_lastword) begin if (!eof_o) begin src_rdy_o <= #`TCQ src_rdy_q[out_d2]; // Note that rem_q has already been adjusted for ECRC trim by this // point so that, in a 64-bit system, an UNaligned indicator means // that the trimming has NOT blanked out the original EOF quadword // completely. Thus the original src_rdy is still valid. end else if ((DW == 64) && !rem_q[out_d2]) begin src_rdy_o <= #`TCQ src_rdy_q[out_d2]; end else begin src_rdy_o <= #`TCQ 1'b0; end dsc_o <= #`TCQ dsc_q[out_d2] || (eof_q[out_d2] && next_cur_drop); rem_o <= #`TCQ (DW == 64) ? rem_q[out_d2] : 1'b1; eof_o <= #`TCQ eof_q[out_d2]; preeof_o <= #`TCQ eof_q[out_d3]; end else begin // Special case to filter src_rdy_o // when eof is moved forward across // DWORD boundaries due to ECRC trimming src_rdy_o <= #`TCQ src_rdy_q[out_d1] && !(eof_o && !sof_q[out_d1]); dsc_o <= #`TCQ dsc_q[out_d1] || (eof_q[out_d1] && cur_drop); rem_o <= #`TCQ (DW == 64) ? rem_q[out_d1] : 1'b1; eof_o <= #`TCQ eof_q[out_d1]; preeof_o <= #`TCQ eof_q[out_d2]; end end // we want SRLs for the internal stages // we've got resets on the input/output -> the middles will resolve always @(posedge clk_i) begin sof_q[6:2] <= #`TCQ sof_q[5:1]; eof_q[6:2] <= #`TCQ eof_q[5:1]; src_rdy_q[6:2] <= #`TCQ src_rdy_q[5:1]; dsc_q[6:2] <= #`TCQ dsc_q[5:1]; rem_q[6:2] <= #`TCQ (DW == 64) ? rem_q[5:1] : 5'h1f; eof_nd_q[6:2] <= #`TCQ eof_nd_q[5:1]; end `ifdef PCIE // In PCIe, if we are dropping the digest, we don't want to tell the // downstream logic that we have one. It's a bit ugly, but it creates // only one extra flop instead of a whole word. assign d_mux = (sof_i && td_ecrc_trim_i) ? {d_i[DW-1:TD_IND+1], 1'b0, d_i[TD_IND-1:0]} : d_i; `else // `ifdef AS // In AS, even if we trim the packet CRC, we still want to tell the // Read Monitor that PCRC existed, so it can be counted toward credit // reallocation. The FIFO will turn off the PCRC bit later so that the // packet looks clean to the user. assign d_mux = d_i; `endif // Data pipe always @(posedge clk_i) begin d_q1 <= #`TCQ d_mux; d_q2 <= #`TCQ d_q1; d_q3 <= #`TCQ d_q2; d_q4 <= #`TCQ d_q3; d_q5 <= #`TCQ d_q4; d_q6 <= #`TCQ d_q5; case (out_d1) 5: d_o <= #`TCQ d_q5; 6: d_o <= #`TCQ d_q6; default: d_o <= #`TCQ d_q4; endcase end // Tell the LLM that a TLP has been received, so that it can exit // FC_INIT2 if necessary. This signal stays asserted for the life of // device operation, until the next system reset. always @(posedge clk_i) begin if (reset_i) begin vc_hit_o <= #`TCQ 1'b0; end else if (src_rdy_o && eof_o && !dsc_o) begin vc_hit_o <= #`TCQ 1'b1; end end // Latch the side bands signals that the FIFO needs which are valid at eof // We never have to worry about mal/ur/uc checks here.. but we do need // to worry about back-to-back packets. // We can have up to three packets in the pipeline on any given time // we need three copies of the registers //----------------------------------------------------------------------- always @(posedge clk_i) begin `ifdef PCIE if (!rhit_bar_lat3_i || (DW == 32)) `endif begin if (latch_1st_dword_q4) begin `ifdef PCIE cpl_o <= #`TCQ cur_cpl; locked_o <= #`TCQ cur_locked_q; vend_msg_o <= #`TCQ cur_vend_msg; `endif np_o <= #`TCQ cur_np; cfg_o <= #`TCQ cur_cfg; end end `ifdef PCIE else begin if (latch_1st_dword_q4) begin np_d <= #`TCQ cur_np; cpl_d <= #`TCQ cur_cpl; locked_d <= #`TCQ cur_locked_q; cfg_d <= #`TCQ cur_cfg; vend_msg_d <= #`TCQ vend_msg_d; end np_o <= #`TCQ np_d; cpl_o <= #`TCQ cpl_d; locked_o <= #`TCQ locked_d; cfg_o <= #`TCQ cfg_d; vend_msg_o <= #`TCQ vend_msg_d; end `endif end always @(posedge clk_i) begin if (latch_1st_dword_q2) begin `ifdef PCIE cur_ep_q <= #`TCQ cur_ep; cur_cpl <= #`TCQ cur_fulltype_oh[CPL_BIT]; cur_locked_q <= #`TCQ cur_locked; // These are the POSTED types cur_np <= #`TCQ !cur_fulltype_oh[MWR_BIT] && !cur_fulltype_oh[MSG_BIT] && !cur_fulltype_oh[CPL_BIT]; `else // `ifdef AS cur_np <= #`TCQ !cur_oo && cur_ts; `endif cur_td_q <= #`TCQ cur_td; end end `ifdef PCIE always @(posedge clk_i) begin if (latch_2nd_dword_q2) begin cur_vend_msg <= #`TCQ ((cur_msgcode == VENDOR_DEFINED_TYPE_0) || (cur_msgcode == VENDOR_DEFINED_TYPE_1)) && cur_fulltype_oh[MSG_BIT]; end end `endif `ifdef PCIE // Bar has come back from the CMM when src_rdy is true. // If the packet type needs bar set to 0, the bar block // has already done this for us // Assert rid_o if the requester ID matches (used for completions) //------------------------------------------------------ always @(posedge clk_i) begin if (rhit_src_rdy) begin bar_o <= #`TCQ rhit_bar_d; rid_o <= #`TCQ rhit_d; end end always @(posedge clk_i) begin if (reset_i) begin bar_src_rdy_o <= #`TCQ 0; end else if (rhit_src_rdy) begin bar_src_rdy_o <= #`TCQ 1; end else begin bar_src_rdy_o <= #`TCQ 0; end end `else // `ifdef AS // Latch the OO and TS bits for Bypassable determination. always @(posedge clk_i) begin if (latch_1st_dword) begin cur_oo <= #`TCQ d_i[OO_IND]; cur_ts <= #`TCQ d_i[TS_IND]; end end `endif //======================================================================= // Latch the data fields as the packet arrives into the core //======================================================================= // Delayed versions of control signals //----------------------------------------------------------------------- always @(posedge clk_i) begin if (reset_i) begin latch_1st_dword_q1 <= #`TCQ 0; latch_1st_dword_q2 <= #`TCQ 0; latch_1st_dword_q3 <= #`TCQ 0; latch_1st_dword_q4 <= #`TCQ 0; latch_2nd_dword_q1 <= #`TCQ 0; latch_2nd_dword_q2 <= #`TCQ 0; latch_3rd_dword_q1 <= #`TCQ 0; latch_4th_dword_q1 <= #`TCQ 0; end else begin latch_1st_dword_q1 <= #`TCQ latch_1st_dword; latch_1st_dword_q2 <= #`TCQ latch_1st_dword_q1; latch_1st_dword_q3 <= #`TCQ latch_1st_dword_q2; latch_1st_dword_q4 <= #`TCQ latch_1st_dword_q3; latch_2nd_dword_q1 <= #`TCQ latch_2nd_dword; latch_2nd_dword_q2 <= #`TCQ latch_2nd_dword_q1; latch_3rd_dword_q1 <= #`TCQ latch_3rd_dword; latch_4th_dword_q1 <= #`TCQ latch_4th_dword; end end // fields valid on this packet //----------------------------------------------------------------------- // NOTE: The following attributes were added for XST synthesis of the // PCIe Block Plus project. They are needed to make 250 MHz in a V-5, // but it is very likely that they will have to be removed/disabled for // V-4 and V-IIPro. // synthesis attribute use_clock_enable of cur_td is no; // synthesis attribute use_clock_enable of cur_length is no; // synthesis attribute use_clock_enable of cur_tc is no; // synthesis attribute use_clock_enable of cur_tc0 is no; // synthesis attribute use_clock_enable of cur_ep is no; // synthesis attribute use_clock_enable of cur_attr is no; // synthesis attribute use_clock_enable of cur_length1 is no; // synthesis attribute use_clock_enable of cur_fulltype is no; always @(posedge clk_i) begin if (latch_1st_dword) begin cur_td <= #`TCQ td_in; cur_length <= #`TCQ length_in; `ifdef PCIE cur_tc <= #`TCQ tc_in; cur_tc0 <= #`TCQ tc_in == 0; cur_ep <= #`TCQ ep_in; cur_attr <= #`TCQ attr_in; cur_length1 <= #`TCQ length_in == 1; cur_fulltype <= #`TCQ fulltype_in; casex (fulltype_in) MRD32, MRD32LK, MWR32, MRD64, MRD64LK, MWR64: cur_fulltype_mem <= #`TCQ 1; default: cur_fulltype_mem <= #`TCQ 0; endcase casex (fulltype_in) MRD64, MRD64LK, MWR64: cur_fulltype_64 <= #`TCQ 1; default: cur_fulltype_64 <= #`TCQ 0; endcase casex (fulltype_in) MRD32, MRD64: cur_fulltype_oh <= #`TCQ MRDANY; MWR32, MWR64: cur_fulltype_oh <= #`TCQ MWRANY; MRD32LK, MRD64LK: cur_fulltype_oh <= #`TCQ MLKANY; IORD, IOWR: cur_fulltype_oh <= #`TCQ IOANY; CFGRD0, CFGWR0, CFGRD1, CFGWR1: cur_fulltype_oh <= #`TCQ CFGANY; MSG, MSGD: cur_fulltype_oh <= #`TCQ MSGANY; CPL, CPLD, CPLLK, CPLDLK: cur_fulltype_oh <= #`TCQ CPLANY; default: // don't want MSGAS to alias other types cur_fulltype_oh <= #`TCQ OTHERTYPE; endcase casex (fulltype_in) MRD32LK, MRD64LK, CPLLK, CPLDLK: cur_locked <= #`TCQ 1; default: cur_locked <= #`TCQ 0; endcase `else // `ifdef AS cur_hcrc <= #`TCQ d_i[HCRC_HI_IND:HCRC_LO_IND]; cur_turn_pointer <= #`TCQ d_i[TURN_PTR_HI_IND:TURN_PTR_LO_IND]; `endif end end `ifdef PCIE always @(posedge clk_i) begin if (latch_2nd_dword) begin cur_req_id <= #`TCQ req_id_in; cur_tag <= #`TCQ tag_in; cur_msgcode <= #`TCQ msgcode_in; cur_cpl_stat <= #`TCQ cpl_stat_in; end end // Store the High Address field for a 64-bit memory address (only // needed with the 32-bit datapath) //-------------------------------------------------------------------- always @(posedge clk_i) begin if (latch_3rd_dword) begin cur_addr_hi <= #`TCQ addr_hi_in; end end `else // `ifdef AS // Store the Direction bit for Turn Pointer check //-------------------------------------------------------------------- always @(posedge clk_i) begin if (latch_2nd_dword) begin cur_dir <= #`TCQ d_i[DIR_IND]; end end // Store the Route Header for HCRC check //-------------------------------------------------------------------- always @(posedge clk_i) begin if (latch_1st_dword) begin cur_route_header[50:32] <= #`TCQ d_i[DW-14:DW-32]; end if (latch_2nd_dword) begin cur_route_header[31:0] <= #`TCQ d_i[31:0]; end end `endif `ifdef AS //==================================================================== // Error Reporting //==================================================================== // All errors detected by AS data_snk are Type B events. A Type B // event must be reported with the first 5 DW of the offending packet. // Because the CMM must process the event and send out a PI-5 event // before it can digest the next one, we must wait for acknowledgment // of a Type B event before we can report a new one. This means that // we may need to forgo report of any Type B events while we are // waiting for the CMM's reply. //-------------------------------------------------------------------- // Capture the header information in case of a Type B event. Read it // out and forward it to the CMM if a previous event is not pending. //-------------------------------------------------------------------- tlm_srl_fifo #(.DW (DW), .DMW (DW+1), // Mark each header's SOF .DEPTH (7), .CT_OUT (0)) buf_fifo (.clk_i (clk_i), .reset_i (reset_i), .wen_i (wr_hdr), .d_i ({sof_i,d_i}), .ren_i (rd_hdr), .d_o ({hdr_sof,hdr}), .vld_o (), .nxt_vld_o(), .ct_o (), .chkpt_i (1'b1), .bkp_i (1'b0) ); // Write any of the first 5 DWORDs to the queue. assign wr_hdr = (latch_1st_dword && !packet_ip) || latch_2nd_dword || latch_3rd_dword || latch_4th_dword || latch_5th_dword; // Read out of the queue when we're about to see the result of the // error checks. Don't append the start of the next packet. generate if (DW == 64) begin : rd_hdr_64 assign rd_hdr = eof_q[1] || (|eof_q[3:2] || !sof_hdr); end else begin : rd_hdr_32 assign rd_hdr = eof_o || (|eof_q[4:1] || !sof_hdr); end endgenerate // Read into the header output register if a Type B is not already // pending. Since the queue must synchronize with the data stream, any // headers received while waiting for a Type B acknowledgment will be // read from the queue and silently dropped. always @* load_type_b[0] = !type_b_pending && ((DW == 64) ? eof_q[1] : (eof_i && src_rdy_i && packet_ip)); always @(posedge clk_i) begin load_type_b[5:1] <= #`TCQ load_type_b[4:0]; end wire latch_1st_hdr_dword = load_type_b[0]; wire latch_2nd_hdr_dword = (DW == 64) ? load_type_b[0] : load_type_b[1]; wire latch_3rd_hdr_dword = (DW == 64) ? load_type_b[1] : load_type_b[2]; wire latch_4th_hdr_dword = (DW == 64) ? load_type_b[1] : (load_type_b[3] && !sof_hdr); wire latch_5th_hdr_dword = (DW == 64) ?(load_type_b[2] && !sof_hdr) : (load_type_b[4] && !sof_hdr); localparam UPPER_HI_IND = DW-1; localparam UPPER_LO_IND = DW-32; localparam LOWER_HI_IND = 31; localparam LOWER_LO_IND = 0; always @(posedge clk_i) begin if (latch_1st_hdr_dword) begin err_tlp_type_b_header_o[159:128]<= #`TCQ hdr[UPPER_HI_IND:UPPER_LO_IND]; end if (latch_2nd_hdr_dword) begin err_tlp_type_b_header_o[127:96] <= #`TCQ hdr[LOWER_HI_IND:LOWER_LO_IND]; end else if (latch_1st_hdr_dword) begin err_tlp_type_b_header_o[127:96] <= #`TCQ 0; end if (latch_3rd_hdr_dword) begin err_tlp_type_b_header_o[95:64] <= #`TCQ hdr[UPPER_HI_IND:UPPER_LO_IND]; end else if (latch_1st_hdr_dword) begin err_tlp_type_b_header_o[95:64] <= #`TCQ 0; end if (latch_4th_hdr_dword) begin err_tlp_type_b_header_o[63:32] <= #`TCQ hdr[LOWER_HI_IND:LOWER_LO_IND]; end else if (latch_1st_hdr_dword) begin err_tlp_type_b_header_o[63:32] <= #`TCQ 0; end if (latch_5th_hdr_dword) begin err_tlp_type_b_header_o[31:0] <= #`TCQ hdr[UPPER_HI_IND:UPPER_LO_IND]; end else if (latch_1st_hdr_dword) begin err_tlp_type_b_header_o[31:0] <= #`TCQ 0; end end // Synchronize the data_snk_mal error flags to the Type B header. // In 64-bit, the header is available following the 3rd quadword. // In 32-bit, the header is available following the 5th doubleword. localparam Q2HDR = (DW == 64) ? 3 : 5; // In 64-bit, the header is available following EOF + 3. // In 32-bit, the header is available following EOF + 4. localparam EOF2HDR = (DW == 64) ? 3 : 4; always @(posedge clk_i) begin if (reset_i) begin err_tlp_bad_header_crc_o <= #`TCQ 0; err_tlp_bad_pi_chain_o <= #`TCQ 0; err_tlp_invalid_credit_length_o <= #`TCQ 0; err_tlp_bad_credit_length_o <= #`TCQ 0; err_tlp_non_zero_turn_pointer_o <= #`TCQ 0; err_tlp_unsup_ovc_o <= #`TCQ 0; err_tlp_unsup_mvc_o <= #`TCQ 0; // load_type_b makes sure we stored the current header (i.e., a // previous Type B was not pending). eof_nd_q makes sure the packet // wasn't discontinued. end else if (load_type_b[Q2HDR] && eof_nd_q[EOF2HDR]) begin err_tlp_bad_header_crc_o <= #`TCQ bad_header_crc; err_tlp_bad_pi_chain_o <= #`TCQ bad_pi_chain && !bad_header_crc; err_tlp_invalid_credit_length_o <= #`TCQ invalid_credit_length && !bad_pi_chain && !bad_header_crc; err_tlp_bad_credit_length_o <= #`TCQ bad_credit_length && !invalid_credit_length && !bad_pi_chain && !bad_header_crc; err_tlp_non_zero_turn_pointer_o <= #`TCQ non_zero_turn_pointer && !bad_credit_length && !invalid_credit_length && !bad_pi_chain && !bad_header_crc; err_tlp_unsup_mvc_o <= #`TCQ unsup_mvc && !non_zero_turn_pointer && !bad_credit_length && !invalid_credit_length && !bad_pi_chain && !bad_header_crc; err_tlp_unsup_ovc_o <= #`TCQ unsup_ovc && !unsup_mvc && !non_zero_turn_pointer && !bad_credit_length && !invalid_credit_length && !bad_pi_chain && !bad_header_crc; end else begin err_tlp_bad_header_crc_o <= #`TCQ 0; err_tlp_bad_pi_chain_o <= #`TCQ 0; err_tlp_invalid_credit_length_o <= #`TCQ 0; err_tlp_bad_credit_length_o <= #`TCQ 0; err_tlp_non_zero_turn_pointer_o <= #`TCQ 0; err_tlp_unsup_mvc_o <= #`TCQ 0; err_tlp_unsup_ovc_o <= #`TCQ 0; end end always @(posedge clk_i) begin if (reset_i) begin type_b_pending <= #`TCQ 0; end else if (eof_nd_q[EOF2HDR] && load_type_b[Q2HDR]) begin type_b_pending <= #`TCQ bad_header_crc || bad_pi_chain || invalid_credit_length || bad_credit_length || non_zero_turn_pointer || unsup_mvc || unsup_ovc; end else if (err_tlp_type_b_ack_i) begin type_b_pending <= #`TCQ 0; end end `endif // synthesis translate_off `ifdef PCIE reg [10*8:0] cur_type_str; always @* begin casex (cur_fulltype) MRD32 : begin cur_type_str = "MRD32"; end MRD64 : begin cur_type_str = "MRD64"; end MRD32LK : begin cur_type_str = "MRD32LK";end MRD64LK : begin cur_type_str = "MRD64LK";end MWR32 : begin cur_type_str = "MWR32"; end MWR64 : begin cur_type_str = "MWR64"; end IORD : begin cur_type_str = "IORD"; end IOWR : begin cur_type_str = "IOWR"; end CFGRD0 : begin cur_type_str = "CFGRD0"; end CFGWR0 : begin cur_type_str = "CFGWR0"; end CFGRD1 : begin cur_type_str = "CFGRD1"; end CFGWR1 : begin cur_type_str = "CFGWR1"; end MSG : begin cur_type_str = "MSG"; end MSGD : begin cur_type_str = "MSGD"; end MSGAS : begin cur_type_str = "MSGAS"; end MSGASD : begin cur_type_str = "MSGASD"; end CPL : begin cur_type_str = "CPL"; end CPLD : begin cur_type_str = "CPLD"; end CPLLK : begin cur_type_str = "CPLLK"; end CPLDLK : begin cur_type_str = "CPLDLK"; end default : begin cur_type_str = "undef"; end endcase end reg [30*8:0] cur_msgstr; always @* begin case (cur_msgcode) UNLOCK : cur_msgstr = "UNLOCK"; PM_ACTIVE_STATE_NAK : cur_msgstr = "PM_ACTIVE_STATE_NAK"; PM_PME : cur_msgstr = "PM_PME"; PME_TURN_OFF : cur_msgstr = "PME_TURN_OFF"; PME_TO_ACK : cur_msgstr = "PME_TO_ACK"; ATTENTION_INDICATOR_OFF : cur_msgstr = "ATTENTION_INDICATOR_OFF"; ATTENTION_INDICATOR_ON : cur_msgstr = "ATTENTION_INDICATOR_ON"; ATTENTION_INDICATOR_BLINK : cur_msgstr = "ATTENTION_INDICATOR_BLINK"; POWER_INDICATOR_ON : cur_msgstr = "POWER_INDICATOR_ON"; POWER_INDICATOR_BLINK : cur_msgstr = "POWER_INDICATOR_BLINK"; POWER_INDICATOR_OFF : cur_msgstr = "POWER_INDICATOR_OFF"; ATTENTION_BUTTON_PRESSED : cur_msgstr = "ATTENTION_BUTTON_PRESSED"; SET_SLOT_POWER_LIMIT : cur_msgstr = "SET_SLOT_POWER_LIMIT"; VENDOR_DEFINED_TYPE_0 : cur_msgstr = "VENDOR_DEFINED_TYPE_0"; VENDOR_DEFINED_TYPE_1 : cur_msgstr = "VENDOR_DEFINED_TYPE_1"; default : cur_msgstr = "undef"; endcase end `endif // synthesis translate_on endmodule
Go to most recent revision | Compare with Previous | Blame | View Log