URL
https://opencores.org/ocsvn/pcie_mini/pcie_mini/trunk
Subversion Repositories pcie_mini
[/] [pcie_mini/] [trunk/] [main_sources/] [oldversions/] [xilinx_pcie2wb_v1.2.vhd] - Rev 11
Compare with Previous | Blame | View Log
---------------------------------------------------------------------------------- -- Company: -- Engineer: Istvan Nagy, buenos@freemail.hu -- -- Create Date: 05/30/2010 -- Modify date: 08/10/2012 -- Design Name: pcie_mini -- Module Name: xilinx_pcie2wb - Behavioral -- Version: 1.2 -- Project Name: -- Target Devices: Xilinx Series-5/6/7 FPGAs -- Tool versions: ISE-DS 12.1 -- Description: -- PCI-express endpoint block, transaction layer logic and back-end logic. The main -- purpose of this file is to make a useable back-end interface and handle flow control -- for the xilinx auto-generated PCIe endpoint IP. -- The PCIe endpoint implements one 256MByte memory BAR (Base Address Register). -- This 256MBytes size is set up in the core config, and also hardcoded in this -- file (search for: "256MBytes"). -- This 1 BAR is implemented as a Wishbone master interface with byte addressing, -- where address [x:2] shows DWORD address, while sel[3:0] decodes the 2 LSBs. -- ADDRESSES ARE BYTE ADDRESSES. -- The lower address bits are usually zero, so the slave (MCB) has to select bytes based -- on the byte select signals: sel[3:0]. The output address of the core contails the 2 -- LSBs as well. The core was only tested with 32-bit accesses, byte-wide might work or not. -- The TLP logic is capable of handling up to 1k bytes (256 DWORDs) payload data in a -- single PCIe transaction, and can handle only one request at a time. If a new request -- is arriving while processing the previous one (e.g. getting the data from a wishbone -- read), then the state machine will not process it immediately, or it will hang. So -- the user software has to wait for the previous read completion before issueing a new -- request. The multiple DWORDs are handled separately by the WB statemachine. -- Performance: WishBone bus: 62.5MHz, 32bit, 2clk/access -> 125MBytes/sec. The maximum -- data throughput can be achieved when using the maximum data payload (block). -- The core uses INTA wirtual wire to signal interrupts. -- -- x1 PCIe, legacy endpoint, uses a 100MHz ref clock. The generated core had to -- be edited manually to support 100MHz, as per Xilinx AR#33761. -- -- Dependencies: The CoreGenerator's configured PCIe core is included. -- If we generate a new pcie endpoint, then copy the new files from the source -- directory into the project's directory, and copy the generic section of the "pcie" -- from the file: xilinx_pcie_1_1_ep_s6.vhd, into this file. -- Synthesis: Set the "FSM Encoding Algorithm" to "user". -- -- Revision: -- Revision 1.0 - File Created by Istvan Nagy -- Revision 1.1 - some fixes by Istvan Nagy -- Revision 1.2 - interrupt fix by Stephen Battazzo -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. library UNISIM; use UNISIM.VComponents.all; entity xilinx_pcie2wb is Port ( --FPGA PINS(EXTERNAL): pci_exp_txp : out std_logic; pci_exp_txn : out std_logic; pci_exp_rxp : in std_logic; pci_exp_rxn : in std_logic; sys_clk_n : in std_logic; sys_clk_p : in std_logic; sys_reset_n : in std_logic; --ON CHIP PORTS: --DATA BUS for BAR0 (wishbone): pcie_bar0_wb_data_o : out std_logic_vector(31 downto 0); pcie_bar0_wb_data_i : in std_logic_vector(31 downto 0); pcie_bar0_wb_addr_o : out std_logic_vector(27 downto 0); pcie_bar0_wb_cyc_o : out std_logic; pcie_bar0_wb_stb_o : out std_logic; pcie_bar0_wb_wr_o : out std_logic; pcie_bar0_wb_ack_i : in std_logic; pcie_bar0_wb_clk_o : out std_logic; --62.5MHz pcie_bar0_wb_sel_o : out std_logic_vector(3 downto 0); --OTHER: pcie_irq : in std_logic; pcie_resetout : out std_logic --active high ); end xilinx_pcie2wb; architecture Behavioral of xilinx_pcie2wb is -- Internal Signals ------------------------------------------------------------ --SIGNAL dummy : std_logic_vector(15 downto 0); --write data bus SIGNAL cfg_do : std_logic_vector(31 downto 0); SIGNAL cfg_rd_wr_done_n : std_logic; SIGNAL cfg_dwaddr : std_logic_vector(9 downto 0); SIGNAL cfg_rd_en_n : std_logic; SIGNAL cfg_err_ur_n : std_logic; SIGNAL cfg_err_cor_n : std_logic; SIGNAL cfg_err_ecrc_n : std_logic; SIGNAL cfg_err_cpl_timeout_n : std_logic; SIGNAL cfg_err_cpl_abort_n : std_logic; SIGNAL cfg_err_posted_n : std_logic; SIGNAL cfg_err_locked_n : std_logic; SIGNAL cfg_err_tlp_cpl_header : std_logic_vector(47 downto 0); SIGNAL cfg_err_cpl_rdy_n : std_logic; SIGNAL cfg_interrupt_n : std_logic; SIGNAL cfg_interrupt_rdy_n : std_logic; SIGNAL cfg_interrupt_assert_n : std_logic; SIGNAL cfg_interrupt_do : std_logic_vector(7 downto 0); SIGNAL cfg_interrupt_di : std_logic_vector(7 downto 0); SIGNAL cfg_interrupt_mmenable : std_logic_vector(2 downto 0); SIGNAL cfg_interrupt_msienable : std_logic; SIGNAL cfg_turnoff_ok_n : std_logic; SIGNAL cfg_to_turnoff_n : std_logic; SIGNAL cfg_pm_wake_n : std_logic; SIGNAL cfg_pcie_link_state_n : std_logic_vector(2 downto 0); SIGNAL cfg_trn_pending_n : std_logic; SIGNAL cfg_dsn : std_logic_vector(63 downto 0); SIGNAL cfg_bus_number : std_logic_vector(7 downto 0); SIGNAL cfg_device_number : std_logic_vector(4 downto 0); SIGNAL cfg_function_number : std_logic_vector(2 downto 0); SIGNAL cfg_status : std_logic_vector(15 downto 0); SIGNAL cfg_command : std_logic_vector(15 downto 0); SIGNAL cfg_dstatus : std_logic_vector(15 downto 0); SIGNAL cfg_dcommand : std_logic_vector(15 downto 0); SIGNAL cfg_lstatus : std_logic_vector(15 downto 0); SIGNAL cfg_lcommand : std_logic_vector(15 downto 0); -- System Interface SIGNAL sys_clk : std_logic; SIGNAL trn_clk : std_logic; SIGNAL trn_reset_n : std_logic; SIGNAL received_hot_reset : std_logic; -- Transaction (TRN) Interface SIGNAL trn_lnk_up_n : std_logic; -- data interface Tx SIGNAL trn_td : std_logic_vector(31 downto 0); SIGNAL trn_tsof_n : std_logic; SIGNAL trn_teof_n : std_logic; SIGNAL trn_tsrc_rdy_n : std_logic; SIGNAL trn_tdst_rdy_n : std_logic; SIGNAL trn_terr_drop_n : std_logic; SIGNAL trn_tsrc_dsc_n : std_logic; SIGNAL trn_terrfwd_n : std_logic; SIGNAL trn_tbuf_av : std_logic_vector(5 downto 0); SIGNAL trn_tstr_n : std_logic; SIGNAL trn_tcfg_req_n : std_logic; SIGNAL trn_tcfg_gnt_n : std_logic; -- data interface Rx SIGNAL trn_rd : std_logic_vector(31 downto 0); SIGNAL trn_rsof_n : std_logic; SIGNAL trn_reof_n : std_logic; SIGNAL trn_rsrc_rdy_n : std_logic; SIGNAL trn_rsrc_dsc_n : std_logic; SIGNAL trn_rdst_rdy_n : std_logic; SIGNAL trn_rerrfwd_n : std_logic; SIGNAL trn_rnp_ok_n : std_logic; SIGNAL trn_rbar_hit_n : std_logic_vector(6 downto 0); -- flow control SIGNAL trn_fc_sel : std_logic_vector(2 downto 0); SIGNAL trn_fc_nph : std_logic_vector(7 downto 0); SIGNAL trn_fc_npd : std_logic_vector(11 downto 0); SIGNAL trn_fc_ph : std_logic_vector(7 downto 0); SIGNAL trn_fc_pd : std_logic_vector(11 downto 0); SIGNAL trn_fc_cplh : std_logic_vector(7 downto 0); SIGNAL trn_fc_cpld : std_logic_vector(11 downto 0); SIGNAL start_read_wb0 : std_logic; SIGNAL start_write_wb0 : std_logic; SIGNAL wb_transaction_complete : std_logic; SIGNAL pcie_bar0_wb_data_i_latched : std_logic_vector(31 downto 0); SIGNAL pcie_bar0_wb_data_o_feed : std_logic_vector(31 downto 0); SIGNAL pcie_bar0_wb_addr_o_feed : std_logic_vector(27 downto 0); SIGNAL pcie_bar0_wb_sel_o_feed : std_logic_vector(3 downto 0); SIGNAL start_read_wb1 : std_logic; SIGNAL start_write_wb1 : std_logic; SIGNAL rd_data_ready_wb1 : std_logic; SIGNAL pcie_just_received_a_new_tlp : std_logic ; SIGNAL pcie_start_reading_rx_tlp : std_logic ; SIGNAL pcie_there_is_a_new_tlp_to_transmit : std_logic ; SIGNAL rxtlp_decodedaddress : std_logic_vector(31 downto 0); SIGNAL tlp_payloadsize_dwords : std_logic_vector(7 downto 0); SIGNAL rxtlp_firstdw_be : std_logic_vector(3 downto 0); SIGNAL rxtlp_lastdw_be : std_logic_vector(3 downto 0); SIGNAL rxtlp_requesterid : std_logic_vector(15 downto 0); SIGNAL tlp_state : std_logic_vector(7 downto 0); SIGNAL tlp_state_copy : std_logic_vector(7 downto 0); SIGNAL rxtlp_data_0 : std_logic_vector(31 downto 0); SIGNAL rxtlp_data_1 : std_logic_vector(31 downto 0); SIGNAL rxtlp_data_2 : std_logic_vector(31 downto 0); SIGNAL rxtlp_data_3 : std_logic_vector(31 downto 0); SIGNAL rxtlp_data_4 : std_logic_vector(31 downto 0); SIGNAL rxtlp_data_5 : std_logic_vector(31 downto 0); SIGNAL rxtlp_data_6 : std_logic_vector(31 downto 0); SIGNAL rxtlp_data_7 : std_logic_vector(31 downto 0); SIGNAL txtlp_data_0 : std_logic_vector(31 downto 0); SIGNAL txtlp_data_1 : std_logic_vector(31 downto 0); SIGNAL txtlp_data_2 : std_logic_vector(31 downto 0); SIGNAL txtlp_data_3 : std_logic_vector(31 downto 0); SIGNAL txtlp_data_4 : std_logic_vector(31 downto 0); SIGNAL txtlp_data_5 : std_logic_vector(31 downto 0); SIGNAL txtlp_data_6 : std_logic_vector(31 downto 0); SIGNAL txtlp_data_7 : std_logic_vector(31 downto 0); SIGNAL pcie_tlp_tx_complete : std_logic; --this signal added by StBa, AAC Microtec SIGNAL irq_prohibit : std_logic; SIGNAL pcieirq_state : std_logic_vector(7 downto 0); SIGNAL txtrn_counter : std_logic_vector(7 downto 0); SIGNAL trn_rx_counter : std_logic_vector(7 downto 0); SIGNAL cfg_completer_id : std_logic_vector(15 downto 0); SIGNAL wb0_state : std_logic_vector(7 downto 0); SIGNAL epif_tx_state : std_logic_vector(7 downto 0); SIGNAL epif_rx_state : std_logic_vector(7 downto 0); SIGNAL bit10 : std_logic_vector(1 downto 0); SIGNAL bram_rxtlp_we : std_logic_vector(0 downto 0); SIGNAL bram_rxtlp_writeaddress : std_logic_vector(31 downto 0); SIGNAL bram_rxtlp_writedata : std_logic_vector(31 downto 0); SIGNAL bram_rxtlp_readaddress : std_logic_vector(31 downto 0); SIGNAL bram_rxtlp_readdata : std_logic_vector(31 downto 0); SIGNAL bram_txtlp_we : std_logic_vector(0 downto 0); SIGNAL bram_txtlp_writeaddress : std_logic_vector(8 downto 0); SIGNAL bram_txtlp_writedata : std_logic_vector(31 downto 0); SIGNAL bram_txtlp_readaddress : std_logic_vector(31 downto 0); SIGNAL bram_txtlp_readdata : std_logic_vector(31 downto 0); SIGNAL tlp_datacount : std_logic_vector(7 downto 0); --SIGNAL bram_rxtlp_firstdata_address : std_logic_vector(8 downto 0); SIGNAL rxtlp_header_dw1 : std_logic_vector(31 downto 0); SIGNAL rxtlp_header_dw2 : std_logic_vector(31 downto 0); SIGNAL rxtlp_header_dw3 : std_logic_vector(31 downto 0); SIGNAL rxtlp_header_dw4 : std_logic_vector(31 downto 0); SIGNAL flag1 : std_logic; SIGNAL rxdw1_23_0 : std_logic_vector(23 downto 0); SIGNAL pcie_rxtlp_tag : std_logic_vector(7 downto 0); SIGNAL pciewb_localreset_n : std_logic; SIGNAL cfg_interrupt_assert_n_1 : std_logic; SIGNAL trn_tsrc_rdy_n_1 : std_logic; SIGNAL trn_tsof_n1 : std_logic; SIGNAL rcompl_bytecount_field : std_logic_vector(9 downto 0); SIGNAL rxstm_readytoroll : std_logic; SIGNAL tlpstm_isin_idle : std_logic; -- COMPONENT DECLARATIONS (introducing the IPs) -------------------------------- --this is the pcie endpoint core from coregenerator. --Core name: Xilinx Spartan-6 Integrated --Block for PCI Express --Version: 1.2 --Release Date: September 16, 2009. ISE DS 11.4 component pcie is generic ( TL_TX_RAM_RADDR_LATENCY : integer := 0; TL_TX_RAM_RDATA_LATENCY : integer := 2; TL_RX_RAM_RADDR_LATENCY : integer := 0; TL_RX_RAM_RDATA_LATENCY : integer := 2; TL_RX_RAM_WRITE_LATENCY : integer := 0; VC0_TX_LASTPACKET : integer := 14; VC0_RX_RAM_LIMIT : bit_vector := x"7FF"; VC0_TOTAL_CREDITS_PH : integer := 32; VC0_TOTAL_CREDITS_PD : integer := 211; VC0_TOTAL_CREDITS_NPH : integer := 8; VC0_TOTAL_CREDITS_CH : integer := 40; VC0_TOTAL_CREDITS_CD : integer := 211; VC0_CPL_INFINITE : boolean := TRUE; BAR0 : bit_vector := x"F0000000"; BAR1 : bit_vector := x"00000000"; BAR2 : bit_vector := x"00000000"; BAR3 : bit_vector := x"00000000"; BAR4 : bit_vector := x"00000000"; BAR5 : bit_vector := x"00000000"; EXPANSION_ROM : bit_vector := "0000000000000000000000"; DISABLE_BAR_FILTERING : boolean := FALSE; DISABLE_ID_CHECK : boolean := FALSE; TL_TFC_DISABLE : boolean := FALSE; TL_TX_CHECKS_DISABLE : boolean := FALSE; USR_CFG : boolean := FALSE; USR_EXT_CFG : boolean := FALSE; DEV_CAP_MAX_PAYLOAD_SUPPORTED : integer := 2; CLASS_CODE : bit_vector := x"068000"; CARDBUS_CIS_POINTER : bit_vector := x"00000000"; PCIE_CAP_CAPABILITY_VERSION : bit_vector := x"1"; PCIE_CAP_DEVICE_PORT_TYPE : bit_vector := x"1"; PCIE_CAP_SLOT_IMPLEMENTED : boolean := FALSE; PCIE_CAP_INT_MSG_NUM : bit_vector := "00000"; DEV_CAP_PHANTOM_FUNCTIONS_SUPPORT : integer := 0; DEV_CAP_EXT_TAG_SUPPORTED : boolean := FALSE; DEV_CAP_ENDPOINT_L0S_LATENCY : integer := 7; DEV_CAP_ENDPOINT_L1_LATENCY : integer := 7; SLOT_CAP_ATT_BUTTON_PRESENT : boolean := FALSE; SLOT_CAP_ATT_INDICATOR_PRESENT : boolean := FALSE; SLOT_CAP_POWER_INDICATOR_PRESENT : boolean := FALSE; DEV_CAP_ROLE_BASED_ERROR : boolean := TRUE; LINK_CAP_ASPM_SUPPORT : integer := 1; --LINK_CAP_L0S_EXIT_LATENCY : integer := 7; --LINK_CAP_L1_EXIT_LATENCY : integer := 7; LL_ACK_TIMEOUT : bit_vector := x"0000"; LL_ACK_TIMEOUT_EN : boolean := FALSE; --LL_REPLAY_TIMEOUT : bit_vector := x"0204"; LL_REPLAY_TIMEOUT : bit_vector := x"0000"; LL_REPLAY_TIMEOUT_EN : boolean := FALSE; MSI_CAP_MULTIMSGCAP : integer := 0; MSI_CAP_MULTIMSG_EXTENSION : integer := 0; LINK_STATUS_SLOT_CLOCK_CONFIG : boolean := FALSE; PLM_AUTO_CONFIG : boolean := FALSE; FAST_TRAIN : boolean := FALSE; ENABLE_RX_TD_ECRC_TRIM : boolean := FALSE; DISABLE_SCRAMBLING : boolean := FALSE; PM_CAP_VERSION : integer := 3; PM_CAP_PME_CLOCK : boolean := FALSE; PM_CAP_DSI : boolean := FALSE; PM_CAP_AUXCURRENT : integer := 0; PM_CAP_D1SUPPORT : boolean := TRUE; PM_CAP_D2SUPPORT : boolean := TRUE; PM_CAP_PMESUPPORT : bit_vector := x"0F"; PM_DATA0 : bit_vector := x"04"; PM_DATA_SCALE0 : bit_vector := x"0"; PM_DATA1 : bit_vector := x"00"; PM_DATA_SCALE1 : bit_vector := x"0"; PM_DATA2 : bit_vector := x"00"; PM_DATA_SCALE2 : bit_vector := x"0"; PM_DATA3 : bit_vector := x"00"; PM_DATA_SCALE3 : bit_vector := x"0"; PM_DATA4 : bit_vector := x"04"; PM_DATA_SCALE4 : bit_vector := x"0"; PM_DATA5 : bit_vector := x"00"; PM_DATA_SCALE5 : bit_vector := x"0"; PM_DATA6 : bit_vector := x"00"; PM_DATA_SCALE6 : bit_vector := x"0"; PM_DATA7 : bit_vector := x"00"; PM_DATA_SCALE7 : bit_vector := x"0"; PCIE_GENERIC : bit_vector := "000011101111"; GTP_SEL : integer := 0; CFG_VEN_ID : std_logic_vector(15 downto 0) := x"10EE"; CFG_DEV_ID : std_logic_vector(15 downto 0) := x"BADD"; CFG_REV_ID : std_logic_vector(7 downto 0) := x"00"; CFG_SUBSYS_VEN_ID : std_logic_vector(15 downto 0) := x"10EE"; CFG_SUBSYS_ID : std_logic_vector(15 downto 0) := x"1234"; REF_CLK_FREQ : integer := 0 ); port ( -- PCI Express Fabric Interface pci_exp_txp : out std_logic; pci_exp_txn : out std_logic; pci_exp_rxp : in std_logic; pci_exp_rxn : in std_logic; -- Transaction (TRN) Interface trn_lnk_up_n : out std_logic; -- Tx trn_td : in std_logic_vector(31 downto 0); trn_tsof_n : in std_logic; trn_teof_n : in std_logic; trn_tsrc_rdy_n : in std_logic; trn_tdst_rdy_n : out std_logic; trn_terr_drop_n : out std_logic; trn_tsrc_dsc_n : in std_logic; trn_terrfwd_n : in std_logic; trn_tbuf_av : out std_logic_vector(5 downto 0); trn_tstr_n : in std_logic; trn_tcfg_req_n : out std_logic; trn_tcfg_gnt_n : in std_logic; -- Rx trn_rd : out std_logic_vector(31 downto 0); trn_rsof_n : out std_logic; trn_reof_n : out std_logic; trn_rsrc_rdy_n : out std_logic; trn_rsrc_dsc_n : out std_logic; trn_rdst_rdy_n : in std_logic; trn_rerrfwd_n : out std_logic; trn_rnp_ok_n : in std_logic; trn_rbar_hit_n : out std_logic_vector(6 downto 0); trn_fc_sel : in std_logic_vector(2 downto 0); trn_fc_nph : out std_logic_vector(7 downto 0); trn_fc_npd : out std_logic_vector(11 downto 0); trn_fc_ph : out std_logic_vector(7 downto 0); trn_fc_pd : out std_logic_vector(11 downto 0); trn_fc_cplh : out std_logic_vector(7 downto 0); trn_fc_cpld : out std_logic_vector(11 downto 0); -- Host (CFG) Interface cfg_do : out std_logic_vector(31 downto 0); cfg_rd_wr_done_n : out std_logic; cfg_dwaddr : in std_logic_vector(9 downto 0); cfg_rd_en_n : in std_logic; cfg_err_ur_n : in std_logic; cfg_err_cor_n : in std_logic; cfg_err_ecrc_n : in std_logic; cfg_err_cpl_timeout_n : in std_logic; cfg_err_cpl_abort_n : in std_logic; cfg_err_posted_n : in std_logic; cfg_err_locked_n : in std_logic; cfg_err_tlp_cpl_header : in std_logic_vector(47 downto 0); cfg_err_cpl_rdy_n : out std_logic; cfg_interrupt_n : in std_logic; cfg_interrupt_rdy_n : out std_logic; cfg_interrupt_assert_n : in std_logic; cfg_interrupt_do : out std_logic_vector(7 downto 0); cfg_interrupt_di : in std_logic_vector(7 downto 0); cfg_interrupt_mmenable : out std_logic_vector(2 downto 0); cfg_interrupt_msienable : out std_logic; cfg_turnoff_ok_n : in std_logic; cfg_to_turnoff_n : out std_logic; cfg_pm_wake_n : in std_logic; cfg_pcie_link_state_n : out std_logic_vector(2 downto 0); cfg_trn_pending_n : in std_logic; cfg_dsn : in std_logic_vector(63 downto 0); cfg_bus_number : out std_logic_vector(7 downto 0); cfg_device_number : out std_logic_vector(4 downto 0); cfg_function_number : out std_logic_vector(2 downto 0); cfg_status : out std_logic_vector(15 downto 0); cfg_command : out std_logic_vector(15 downto 0); cfg_dstatus : out std_logic_vector(15 downto 0); cfg_dcommand : out std_logic_vector(15 downto 0); cfg_lstatus : out std_logic_vector(15 downto 0); cfg_lcommand : out std_logic_vector(15 downto 0); -- System Interface sys_clk : in std_logic; sys_reset_n : in std_logic; trn_clk : out std_logic; trn_reset_n : out std_logic; received_hot_reset : out std_logic ); end component pcie; COMPONENT blk_mem_gen_v4_1 PORT( clka : IN std_logic; wea : IN std_logic_vector(0 to 0); addra : IN std_logic_vector(8 downto 0); dina : IN std_logic_vector(31 downto 0); clkb : IN std_logic; addrb : IN std_logic_vector(8 downto 0); doutb : OUT std_logic_vector(31 downto 0) ); END COMPONENT; ---- ------- SYNTHESIS ATTRIBUTES: -------------------------------------------------- --attribute keep_hierarchy : string; --attribute keep_hierarchy of xilinx_pcie2wb: entity is "yes"; attribute keep : string; attribute keep of cfg_dstatus : signal is "true"; attribute keep of tlp_state : signal is "true"; -- --------ARCHITECTURE BODY BEGINS ----------------------------------------------- begin cfg_turnoff_ok_n <= '1'; -- COMPONENT INSTALLATIONS (connecting the IPs to local signals) --------------- -- COMPONENT INSTALLATIONS (connecting the IPs to local signals) --------------- inst_pcie : pcie port map ( pci_exp_txp => pci_exp_txp, pci_exp_txn => pci_exp_txn, pci_exp_rxp => pci_exp_rxp, pci_exp_rxn => pci_exp_rxn, trn_lnk_up_n => trn_lnk_up_n, trn_td => trn_td, -- Bus [31 : 0] trn_tsof_n => trn_tsof_n, trn_teof_n => trn_teof_n, trn_tsrc_rdy_n => trn_tsrc_rdy_n, trn_tdst_rdy_n => trn_tdst_rdy_n, trn_terr_drop_n => trn_terr_drop_n, trn_tsrc_dsc_n => trn_tsrc_dsc_n, trn_terrfwd_n => trn_terrfwd_n, trn_tbuf_av => trn_tbuf_av, -- Bus [31 : 0] trn_tstr_n => trn_tstr_n, trn_tcfg_req_n => trn_tcfg_req_n, trn_tcfg_gnt_n => trn_tcfg_gnt_n, trn_rd => trn_rd, -- Bus [31 : 0] trn_rsof_n => trn_rsof_n, trn_reof_n => trn_reof_n, trn_rsrc_rdy_n => trn_rsrc_rdy_n, trn_rsrc_dsc_n => trn_rsrc_dsc_n, trn_rdst_rdy_n => trn_rdst_rdy_n, trn_rerrfwd_n => trn_rerrfwd_n, trn_rnp_ok_n => trn_rnp_ok_n, trn_rbar_hit_n => trn_rbar_hit_n, -- Bus [31 : 0] trn_fc_sel => trn_fc_sel, -- Bus [31 : 0] trn_fc_nph => trn_fc_nph, -- Bus [31 : 0] trn_fc_npd => trn_fc_npd, -- Bus [31 : 0] trn_fc_ph => trn_fc_ph, -- Bus [31 : 0] trn_fc_pd => trn_fc_pd, -- Bus [31 : 0] trn_fc_cplh => trn_fc_cplh, -- Bus [31 : 0] trn_fc_cpld => trn_fc_cpld, -- Bus [31 : 0] cfg_do => cfg_do, -- Bus [31 : 0] cfg_rd_wr_done_n => cfg_rd_wr_done_n, cfg_dwaddr => cfg_dwaddr, -- Bus [31 : 0] cfg_rd_en_n => cfg_rd_en_n, cfg_err_ur_n => cfg_err_ur_n, cfg_err_cor_n => cfg_err_cor_n, cfg_err_ecrc_n => cfg_err_ecrc_n, cfg_err_cpl_timeout_n => cfg_err_cpl_timeout_n, cfg_err_cpl_abort_n => cfg_err_cpl_abort_n, cfg_err_posted_n => cfg_err_posted_n, cfg_err_locked_n => cfg_err_locked_n, cfg_err_tlp_cpl_header => cfg_err_tlp_cpl_header, -- Bus [31 : 0] cfg_err_cpl_rdy_n => cfg_err_cpl_rdy_n, cfg_interrupt_n => cfg_interrupt_n, cfg_interrupt_rdy_n => cfg_interrupt_rdy_n, cfg_interrupt_assert_n => cfg_interrupt_assert_n, cfg_interrupt_do => cfg_interrupt_do, -- Bus [31 : 0] cfg_interrupt_di => cfg_interrupt_di, -- Bus [31 : 0] cfg_interrupt_mmenable => cfg_interrupt_mmenable, -- Bus [31 : 0] cfg_interrupt_msienable => cfg_interrupt_msienable, cfg_turnoff_ok_n => cfg_turnoff_ok_n, cfg_to_turnoff_n => cfg_to_turnoff_n, cfg_pm_wake_n => cfg_pm_wake_n, cfg_pcie_link_state_n => cfg_pcie_link_state_n, -- Bus [31 : 0] cfg_trn_pending_n => cfg_trn_pending_n, cfg_dsn => cfg_dsn, -- Bus [31 : 0] cfg_bus_number => cfg_bus_number, -- Bus [31 : 0] cfg_device_number => cfg_device_number, -- Bus [31 : 0] cfg_function_number => cfg_function_number, -- Bus [31 : 0] cfg_status => cfg_status, -- Bus [31 : 0] cfg_command => cfg_command, -- Bus [31 : 0] cfg_dstatus => cfg_dstatus, -- Bus [31 : 0] cfg_dcommand => cfg_dcommand, -- Bus [31 : 0] cfg_lstatus => cfg_lstatus, -- Bus [31 : 0] cfg_lcommand => cfg_lcommand, -- Bus [31 : 0] sys_clk => sys_clk, sys_reset_n => sys_reset_n, trn_clk => trn_clk, trn_reset_n => trn_reset_n, received_hot_reset => received_hot_reset ); --block ram for RX TLP: Inst_bram_rxtlp: blk_mem_gen_v4_1 PORT MAP( clka => trn_clk, wea => bram_rxtlp_we, addra => bram_rxtlp_writeaddress(8 downto 0), dina => bram_rxtlp_writedata, clkb => trn_clk, addrb => bram_rxtlp_readaddress(8 downto 0), doutb => bram_rxtlp_readdata ); --block ram for TX TLP: Inst_bram_txtlp: blk_mem_gen_v4_1 PORT MAP( clka => trn_clk, wea => bram_txtlp_we, addra => bram_txtlp_writeaddress(8 downto 0), dina => bram_txtlp_writedata, clkb => trn_clk, addrb => bram_txtlp_readaddress(8 downto 0), doutb => bram_txtlp_readdata ); -- MAIN LOGIC: --------------------------------------------------------------------------------------------- --System Signals:-------------------------------- --Clock Input Buffer for differential system clock IBUFDS_inst : IBUFDS generic map ( DIFF_TERM => TRUE, -- Differential Termination IBUF_LOW_PWR => FALSE, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards IOSTANDARD => "DEFAULT") port map ( O => sys_clk, -- Buffer output I => sys_clk_p, -- Diff_p buffer input (connect directly to top-level port) IB => sys_clk_n -- Diff_n buffer input (connect directly to top-level port) ); --wishbone clock output: pcie_bar0_wb_clk_o <= trn_clk; --pcie_bar1_wb_clk_o <= trn_clk; --use one of these for resetting logic in this file: pciewb_localreset_n <= sys_reset_n; --dont wait for the PCIE-EP to finish its init. --pciewb_localreset_n <= trn_reset_n; --pciewb_localreset_n <= trn_reset_n and (not trn_lnk_up_n) and (not received_hot_reset); --reset to the core: --sys_reset_n comes from toplevel directly to the core. same name --reset output to other cores: pcie_resetout <= not pciewb_localreset_n; --trn_lnk_up_n --not used. --pcie ep ip config port: ---------------------------------------------------------- --trn_fc_sel <= "000"; trn_rnp_ok_n <= '0'; --trn_terrfwd_n <= '1'; --trn_tcfg_gnt_n <= '0'; cfg_err_cor_n <= '1'; cfg_err_ur_n <= '1'; cfg_err_ecrc_n <= '1'; cfg_err_cpl_timeout_n <= '1'; cfg_err_cpl_abort_n <= '1'; cfg_err_posted_n <= '0'; cfg_err_locked_n <= '1'; cfg_pm_wake_n <= '1'; cfg_trn_pending_n <= '1'; --trn_tstr_n <= '0'; --cfg_interrupt_assert_n <= '1'; --used in a process at the bottom of this file --cfg_interrupt_n <= '1'; --cfg_interrupt_di <= x"00"; --intA used cfg_err_tlp_cpl_header <= (OTHERS => '0'); cfg_dwaddr <= (OTHERS => '0'); cfg_rd_en_n <= '1'; --serial number: cfg_dsn <= (OTHERS => '0'); -- AT THE BOTTOM OF THIS FILE: -- --some fix values: -- trn_tsrc_dsc_n <= '1'; --no errors on trn bus -- trn_tstr_n <= '0'; --pipelining (0= link may begin before the entire packet has been written) -- trn_tcfg_gnt_n <= '0'; --no tlp priorities -- trn_terrfwd_n <= '1'; --no errors on trn -- --nc: trn_tbuf_av, trn_terr_drop_n, trn_tcfg_req_n --use this in read completion packets: cfg_completer_id <= cfg_bus_number & cfg_device_number & cfg_function_number; -- WISBONE BACK-end INTERFACE ---------------------------------------------------- --main state machine: set states, capture inputs, set addr/data outputs --minimum 2 clock cycles / transaction. writes are posted, reads have wait states. process (pciewb_localreset_n, trn_clk, wb0_state, start_read_wb0, start_write_wb0, pcie_bar0_wb_addr_o_feed, pcie_bar0_wb_data_o_feed, pcie_bar0_wb_sel_o_feed) begin if (pciewb_localreset_n='0') then wb0_state <= "00000000"; wb_transaction_complete <= '0'; pcie_bar0_wb_addr_o <= "0000000000000000000000000000"; pcie_bar0_wb_sel_o <= "0000"; pcie_bar0_wb_data_o <= "00000000000000000000000000000000"; wb_transaction_complete <='0'; else if (trn_clk'event and trn_clk = '1') then case ( wb0_state ) is --********** IDLE STATE ********** when "00000000" => --state 0 wb_transaction_complete <='0'; pcie_bar0_wb_sel_o <= pcie_bar0_wb_sel_o_feed; pcie_bar0_wb_addr_o <= pcie_bar0_wb_addr_o_feed; if (start_read_wb0 ='1') then --go to read wb0_state <= "00000001"; elsif (start_write_wb0 ='1') then --go to write wb0_state <= "00000010"; --no endian swap: pcie_bar0_wb_data_o <= pcie_bar0_wb_data_o_feed; pcie_bar0_wb_data_o (7 downto 0) <= pcie_bar0_wb_data_o_feed(31 downto 24); --swap endianism pcie_bar0_wb_data_o (15 downto 8) <= pcie_bar0_wb_data_o_feed(23 downto 16); --swap endianism pcie_bar0_wb_data_o (23 downto 16) <= pcie_bar0_wb_data_o_feed(15 downto 8); --swap endianism pcie_bar0_wb_data_o (31 downto 24) <= pcie_bar0_wb_data_o_feed(7 downto 0); --swap endianism end if; --********** READ STATE ********** --set the outputs, --if ACK asserted, sample the data input --The hold requirements are oversatisfyed by going back to idle, and by the fact that the slave uses the cyc/stb/wr strobes synchronously. when "00000001" => --state 1 if (pcie_bar0_wb_ack_i='1') then --no endian swap: pcie_bar0_wb_data_i_latched <= pcie_bar0_wb_data_i; --sample the incoming data pcie_bar0_wb_data_i_latched (7 downto 0) <= pcie_bar0_wb_data_i(31 downto 24); --swap endianism pcie_bar0_wb_data_i_latched (15 downto 8) <= pcie_bar0_wb_data_i(23 downto 16); --swap endianism pcie_bar0_wb_data_i_latched (23 downto 16) <= pcie_bar0_wb_data_i(15 downto 8); --swap endianism pcie_bar0_wb_data_i_latched (31 downto 24) <= pcie_bar0_wb_data_i(7 downto 0); --swap endianism wb_transaction_complete <='1'; --signalling ready, but only for one clock cycle wb0_state <= "00000000"; --go to state 0 else wb_transaction_complete <='0'; end if; --********** WRITE STATE ********** --if ACK asserted, go back to idle --The hold requirements are oversatisfyed by waiting for ACK to remove write data when "00000010" => --state 2 if (pcie_bar0_wb_ack_i='1') then wb0_state <= "00000000"; --go to state 0 wb_transaction_complete <='1'; else wb_transaction_complete <='0'; end if; when others => --error wb0_state <= "00000000"; --go to state 0 end case; end if; end if; end process; --sync control on wb-control signals: process (pciewb_localreset_n, wb0_state) begin if (pciewb_localreset_n='0') then pcie_bar0_wb_cyc_o <= '0'; pcie_bar0_wb_stb_o <= '0'; pcie_bar0_wb_wr_o <= '0'; else if (wb0_state = "00000000") then --idle pcie_bar0_wb_cyc_o <= '0'; pcie_bar0_wb_stb_o <= '0'; pcie_bar0_wb_wr_o <= '0'; elsif (wb0_state = "00000001") then --read pcie_bar0_wb_cyc_o <= '1'; pcie_bar0_wb_stb_o <= '1'; pcie_bar0_wb_wr_o <= '0'; elsif (wb0_state = "00000010") then --write pcie_bar0_wb_cyc_o <= '1'; pcie_bar0_wb_stb_o <= '1'; pcie_bar0_wb_wr_o <= '1'; else pcie_bar0_wb_cyc_o <= '0'; pcie_bar0_wb_stb_o <= '0'; pcie_bar0_wb_wr_o <= '0'; end if; end if; end process; -- INTERFACE TO THE PCIE-EP IP -------------------------------------------------------- --trn_clk and trn_reset_n are the same as the pcie_resetout and pcie_bar0_wb_clk_o, --so it is not a clock domain crossing. -- TX: INTERFACE TO THE PCIE-EP: TRANSMIT TLP PACKETS:----- --Read completion is 3DW header. This core only transmits read completion or Unbsupported request packets. process (pciewb_localreset_n, trn_clk, epif_tx_state, bram_txtlp_readdata , bram_txtlp_readaddress, pcie_there_is_a_new_tlp_to_transmit, tlp_payloadsize_dwords, txtrn_counter) begin if (pciewb_localreset_n='0') then epif_tx_state <= "00000000"; trn_tsrc_rdy_n_1 <='1'; trn_tsof_n1 <= '1'; trn_teof_n <= '1'; trn_td <= (OTHERS => '0'); pcie_tlp_tx_complete <= '0'; txtrn_counter <= "00000001"; bram_txtlp_readaddress <= (OTHERS => '0'); else if (trn_clk'event and trn_clk = '1') then case ( epif_tx_state ) is --********** idle STATE ********** when "00000000" => --state 0 --if there is a new TLP assembled and the EP is ready, --start the tx-trn bus transaction. if (pcie_there_is_a_new_tlp_to_transmit='1') then epif_tx_state <= "00000001"; --next state end if; trn_tsrc_rdy_n_1 <='1'; trn_tsof_n1 <= '1'; trn_teof_n <= '1'; trn_td <= (OTHERS => '0'); pcie_tlp_tx_complete <= '0'; txtrn_counter <= "00000001"; bram_txtlp_readaddress <= (OTHERS => '0'); --********** ready-wait STATE ********** when "00000001" => --state 1 --if there is a new TLP assembled and the EP is ready, --start the tx-trn bus transaction. if (trn_tdst_rdy_n='0') then epif_tx_state <= "00000010"; --next state end if; trn_tsrc_rdy_n_1 <='1'; trn_tsof_n1 <= '1'; trn_teof_n <= '1'; trn_td <= (OTHERS => '0'); pcie_tlp_tx_complete <= '0'; txtrn_counter <= "00000001"; bram_txtlp_readaddress <= (OTHERS => '0'); --********** transfer STATE ********** when "00000010" => --state 2 trn_tsrc_rdy_n_1 <='0'; trn_td <= bram_txtlp_readdata; if (trn_tdst_rdy_n='0') then txtrn_counter <= txtrn_counter +1; bram_txtlp_readaddress <= bram_txtlp_readaddress +1; end if; if (txtrn_counter = "00000010") then trn_tsof_n1 <= '0'; --start else trn_tsof_n1 <= '1'; end if; --test number of dwords: if (txtrn_counter = tlp_payloadsize_dwords +4) then -- "+3" is the header and "+1" is for the delay --this is the last dword, next clk is next state epif_tx_state <= "00000000"; --back to idle, since finished trn_teof_n <= '0'; --end pcie_tlp_tx_complete <= '1'; --assert for 1 clk else trn_teof_n <= '1'; --not end yet pcie_tlp_tx_complete <= '0'; --not complete yet end if; when others => --error epif_tx_state <= "00000000"; --back to idle trn_tsrc_rdy_n_1 <='1'; trn_tsof_n1 <= '1'; trn_teof_n <= '1'; trn_td <= (OTHERS => '0'); pcie_tlp_tx_complete <= '0'; txtrn_counter <= "00000001"; end case; end if; end if; end process; --this (little delay) is to fix a hold time violation created inside the pcie-ep ip: trn_tsrc_rdy_n <= trn_tsrc_rdy_n_1 or (not pciewb_localreset_n); trn_tsof_n <= trn_tsof_n1 or (not pciewb_localreset_n); --some fix values: trn_tsrc_dsc_n <= '1'; --no errors on trn bus trn_tstr_n <= '0'; --pipelining trn_tcfg_gnt_n <= '0'; --no tlp priorities trn_terrfwd_n <= '1'; --no errors on trn --nc: trn_tbuf_av, trn_terr_drop_n, trn_tcfg_req_n -- RX: INTERFACE TO THE PCIE-EP: GET thereceived TLP PACKETS:- ---- process (pciewb_localreset_n, trn_clk, epif_rx_state, tlp_state, trn_rx_counter, bram_rxtlp_writeaddress, rxstm_readytoroll, trn_rsof_n, tlpstm_isin_idle, trn_rdst_rdy_n) begin if (pciewb_localreset_n='0') then pcie_just_received_a_new_tlp <= '0'; epif_rx_state <= "00000000"; trn_rdst_rdy_n <= '1'; trn_rx_counter <= (OTHERS => '0'); bram_rxtlp_we <= "0"; bram_rxtlp_writeaddress <= (OTHERS => '0'); bram_rxtlp_writedata <= (OTHERS => '0'); rxstm_readytoroll <= '0'; else if (trn_clk'event and trn_clk = '1') then case ( epif_rx_state ) is --********** idle STATE ********** when "00000000" => --state 0 pcie_just_received_a_new_tlp <= '0'; bram_rxtlp_writedata <= trn_rd; if (trn_rsrc_rdy_n='0' and trn_rsof_n='0' and tlpstm_isin_idle = '1' and trn_rdst_rdy_n='0') then trn_rx_counter <= trn_rx_counter +1; bram_rxtlp_writeaddress <= bram_rxtlp_writeaddress +1; epif_rx_state <= "00000001"; else trn_rx_counter <= (OTHERS => '0'); bram_rxtlp_writeaddress <= (OTHERS => '0'); end if; --destination ready: if (tlpstm_isin_idle = '1')then trn_rdst_rdy_n <= '0'; else trn_rdst_rdy_n <= '1'; end if; --write into buffer: if (trn_rsrc_rdy_n='0' and trn_rsof_n='0' and tlpstm_isin_idle = '1') then bram_rxtlp_we <= "1"; rxstm_readytoroll <= '1'; else bram_rxtlp_we <= "0"; rxstm_readytoroll <= '0'; end if; --********** read STATE ********** when "00000001" => --state 1 rxstm_readytoroll <= '0'; if (trn_reof_n ='0') then --last dw epif_rx_state <= "00000010"; --for the next clk cycle trn_rdst_rdy_n <= '1'; --ok, dont send more yet end if; if (trn_rsrc_rdy_n='0') then --only act if the EP was ready trn_rx_counter <= trn_rx_counter +1; bram_rxtlp_writeaddress <= bram_rxtlp_writeaddress +1; bram_rxtlp_writedata <= trn_rd; end if; --in an early stage of this transfer, the scheduler can already --start working on the data, this way its pipelined, so the latency is lower. if (trn_rx_counter = "00000010") then pcie_just_received_a_new_tlp <= '1';--assert for one clk only else pcie_just_received_a_new_tlp <= '0'; end if; --********** finished filling up RX TLP STATE ********** when "00000010" => --state 2 epif_rx_state <= "00000000"; trn_rx_counter <= (OTHERS => '0'); when others => --error epif_rx_state <= "00000000"; --go to state 0 end case; end if; end if; end process; --fixed connections: --trn_rnp_ok_ntrn_rnp_ok_n <= '0'; --ready to receive non-posted --not connected: trn_rerrfwd_n, trn_rsrc_dsc_n, trn_rbar_hit_n -- flow control: INTERFACE TO THE PCIE-EP: - ---- --not used. pcie-ep provides information about credit status. --unconnected: trn_fc_nph, trn_fc_npd, trn_fc_ph, trn_fc_pd, trn_fc_cplh, trn_fc_cpld trn_fc_sel <= "000"; -- --- GLUE LOGIC BETWEEN THE PCIE CORE-IF AND THE WB INTERFACES ----------------------- -- --- ALSO TLP PACKET PROCESSING. --Theory of operation: --RX: If we receive a TLP (pcie_just_received_a_new_tlp goes high for one clock cycle), --then store it (pcie_received_tlp), decode it (to figure out if its read request, --posted write or non-supported request), then assert a flag (start_write_wb0 or --start_read_wb0)to initiate a wishbone cycle. --TX: At the completion of a wishbone read, the wishbone statemachine asserts the --wb_transaction_complete flag, so we can assemble the TX TLP packet (pcie_to_transmit_tlp) --and assert the flag named pcie_there_is_a_new_tlp_to_transmit. This packet will be --a read completion packet on the PCIe link. -- --This core can handle 1...8 DWORD accesses in one request (max 256bit payload ), --and can handle only one request at a time. If a new request is arriving while --processing the previous one (e.g. getting the data from a wishbone read), then --the state machine will not process it immediately, or it will hang. So the user --software has to wait for the previous read completion before issueing a new request. --The multiple DWORDs are handled separately by the WB statemachine. --Performance: WishBone bus: 62.5MHz, 32bit, 3clk/access -> 83MBytes/sec -- --TLP decoding: --Header+Payload_data+TLP_DIGEST(ECRC). --received Header: --First Dword: bit.30/29=format: 00=3DW-header+no_data, 01=4DW-header+no_data, --10=3DW-header+data, 11=4DW-header+data. bit.28:24=type: 00000 or 00001 are memory --read requests, 00000 or 00001 are memory write request if type=1x. read request --completion is 01010 and type=10. bit.9:0 is payload size [DW]. --Second Dword: bit.31:16 is requester ID. bit3:0 is first dword byte enable, bit.7:4 is --byte enable for last dword data. intermediate dwords have all bytes enabled. --Third DWORD: address, where bit.1:0=00b. 4DW headers are for 64bit. 64bit adressing --uses 3rd-dword for addre63:32, 4th dword for addr31:0. -- --The TLP variables in this core: BRAM memory used store TLP, up to 1-2kBytes -- --Read completion is 3DW header and routed by completer-ID and requester-ID, not address. --The core has to store the requester ID and feed it back in the completion packet. --Completion status: 000=successful, 100=completer_abort, 001=unsupported request. byte --count is N.of bytes left. lower_address is the first enabled byte of data returned --with the Completion. -- -- Completion packet header: --DW1 > --7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 --r FMT type----- r TC--- reserv- T E att r r lenght------------- -- x 0 D P rib --DW2 > --7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 --COMPLETER_ID------------------- statu B byte_count------------- -- CM --DW3 > --7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 --REQUESTER_ID------------------- tag------------ r lower_address --TLP-protocol statemachine: process (pciewb_localreset_n, trn_clk, tlp_state, pcie_just_received_a_new_tlp, tlp_datacount, bram_rxtlp_readdata, bram_txtlp_writeaddress, bram_rxtlp_readaddress, tlp_state_copy, rxtlp_decodedaddress, rxtlp_header_dw1, rxtlp_header_dw2, rxtlp_header_dw3, rxtlp_header_dw4, bit10, rxtlp_firstdw_be, wb_transaction_complete, flag1, rxdw1_23_0, pcie_rxtlp_tag, tlp_payloadsize_dwords, pcie_bar0_wb_data_i_latched, cfg_completer_id, rxtlp_requesterid) begin if (pciewb_localreset_n='0') then start_read_wb0 <= '0'; start_write_wb0 <= '0'; pcie_bar0_wb_data_o_feed <= (others => '0'); pcie_bar0_wb_addr_o_feed <= (others => '0'); pcie_bar0_wb_sel_o_feed <= (others => '0'); pcie_there_is_a_new_tlp_to_transmit <= '0'; rxtlp_decodedaddress<= (others => '0'); tlp_payloadsize_dwords <= (others => '0'); rxtlp_firstdw_be <= (others => '0'); rxtlp_lastdw_be <= (others => '0'); rxtlp_requesterid <= (others => '0'); tlp_state <= (others => '0'); tlp_state_copy <= (others => '0'); bram_txtlp_we <= "0"; bram_txtlp_writeaddress <= (others => '0'); bram_txtlp_writedata <= (others => '0'); bram_rxtlp_readaddress <= (others => '0'); rxtlp_header_dw1 <= "01111111000000000000000000000000"; rxtlp_header_dw2 <= (others => '0'); rxtlp_header_dw3 <= (others => '0'); rxtlp_header_dw4 <= (others => '0'); flag1 <= '0'; rxdw1_23_0 <= (others => '0'); pcie_rxtlp_tag <= (others => '0'); rcompl_bytecount_field <= (others => '0'); tlpstm_isin_idle <= '1'; else if (trn_clk'event and trn_clk = '1') then case ( tlp_state ) is --********** IDLE STATE ********** --also re-initialize signals... when "00000000" => --state 0 if (pcie_just_received_a_new_tlp='1') then tlp_state <= "00000001"; --to tlp decoding state tlpstm_isin_idle <= '0'; else tlpstm_isin_idle <= '1'; end if; start_write_wb0 <= '0'; start_read_wb0 <= '0'; tlp_state_copy <= tlp_state; bram_txtlp_we <= "0"; bram_txtlp_writeaddress <= (others => '0'); bram_txtlp_writedata <= (others => '0'); bram_rxtlp_readaddress <= (others => '0'); tlp_datacount <= "00000001"; rxtlp_header_dw1 <= "01111111000000000000000000000000"; --this is to prevent false decode pcie_bar0_wb_data_o_feed <= (others => '0'); pcie_bar0_wb_addr_o_feed <= (others => '0'); pcie_bar0_wb_sel_o_feed <= (others => '0'); rxtlp_header_dw2 <= (others => '0'); rxtlp_header_dw3 <= (others => '0'); rxtlp_header_dw4 <= (others => '0'); rxdw1_23_0 <= (others => '0'); pcie_rxtlp_tag <= (others => '0'); pcie_there_is_a_new_tlp_to_transmit <= '0'; rxtlp_decodedaddress<= (others => '0'); tlp_payloadsize_dwords <= (others => '0'); rxtlp_firstdw_be <= (others => '0'); rxtlp_lastdw_be <= (others => '0'); rxtlp_requesterid <= (others => '0'); rcompl_bytecount_field <= (others => '0'); --********** TLP ARRIVED STATE ********** --read TLP out of EP, decode and decide, --latch address/sel/wr_data --All the "IF"-statements use address+1, because the BRAM read side has data available 1clk late!!! --Added an ectra clock delay, based on testing, since the data is one more CLK late. when "00000001" => --state 1 --latch the header: bram_rxtlp_readaddress <= bram_rxtlp_readaddress +1; if (bram_rxtlp_readaddress = "000000010") then rxtlp_header_dw1 <= bram_rxtlp_readdata; elsif (bram_rxtlp_readaddress = "000000011") then rxtlp_header_dw2 <= bram_rxtlp_readdata; elsif (bram_rxtlp_readaddress = "000000100") then rxtlp_header_dw3 <= bram_rxtlp_readdata; elsif (bram_rxtlp_readaddress = "000000101") then rxtlp_header_dw4 <= bram_rxtlp_readdata; end if; --decode some parameters: tlp_payloadsize_dwords <= rxtlp_header_dw1(7 downto 0); rxtlp_firstdw_be <= rxtlp_header_dw2(3 downto 0); rxtlp_lastdw_be <= rxtlp_header_dw2(7 downto 4); rxtlp_requesterid <= rxtlp_header_dw2(31 downto 16); flag1 <= rxtlp_header_dw1(31); rxdw1_23_0 <= rxtlp_header_dw1(23 downto 0); --various fields pcie_received_tlp (22 downto 0); pcie_rxtlp_tag <= rxtlp_header_dw2(15 downto 8) ; --pcie_received_tlp (47 downto 40);--tag --decide based on header: if (rxtlp_header_dw1(30 downto 24)="0000000") then --32bit read if (bram_rxtlp_readaddress = "000000100") then rxtlp_decodedaddress <= bram_rxtlp_readdata; bram_txtlp_writeaddress(8 downto 0) <= "000000011"; --point after the 3dw readcompl header tlp_state <= "00000011"; end if; elsif (rxtlp_header_dw1(30 downto 24)="0100000") then --64bit read if (bram_rxtlp_readaddress = "000000101") then rxtlp_decodedaddress <= bram_rxtlp_readdata; bram_txtlp_writeaddress(8 downto 0) <= "000000011"; --point after the 3dw readcompl header tlp_state <= "00000011"; end if; elsif (rxtlp_header_dw1(30 downto 24)="1000000") then --32bit write if (bram_rxtlp_readaddress = "000000100") then rxtlp_decodedaddress <= bram_rxtlp_readdata; tlp_state <= "00000010"; end if; elsif (rxtlp_header_dw1(30 downto 24)="1100000") then --64bit write if (bram_rxtlp_readaddress = "000000101") then rxtlp_decodedaddress <= bram_rxtlp_readdata; tlp_state <= "00000010"; end if; elsif (rxtlp_header_dw1(30 downto 24)="1111111") then --just wait until this gets a real value rxtlp_decodedaddress <= bram_rxtlp_readdata; else --unsupported request if (bram_rxtlp_readaddress = "000000100") then tlp_state <= "00000101"; bram_txtlp_writeaddress <= "111111111"; end if; end if; --********** WRITE STATE ********** --initiate WB write(s) (1...N DWORD accesses) when "00000010" => --state 2 pcie_bar0_wb_addr_o_feed(27 downto 2) <= rxtlp_decodedaddress(27 downto 2) + tlp_datacount -1; --256MBytes size is hardcoded here, by cutting 4-MSB off pcie_bar0_wb_addr_o_feed(1 downto 0) <= bit10(1 downto 0); pcie_bar0_wb_sel_o_feed <= rxtlp_firstdw_be; pcie_bar0_wb_data_o_feed <= bram_rxtlp_readdata; tlp_state_copy <= tlp_state; if (tlp_state_copy = tlp_state) then start_write_wb0 <= '0'; else --generate just one pulse, at the first clk cycle in this state start_write_wb0 <= '1'; end if; if (wb_transaction_complete='1') then --one DW transfer completed if (tlp_payloadsize_dwords = tlp_datacount) then --all data completed tlp_state <= "00000000"; --to idle else tlp_state <= "00010100"; --restart wb transaction with new data bram_rxtlp_readaddress <= bram_rxtlp_readaddress +1; tlp_datacount <= tlp_datacount +1; end if; end if; --* Write restart state * when "00010100" => --state 20 tlp_state <= "00000010"; --********** READ STATE ********** --initiate WB read, then go to completion state when "00000011" => --state 3 pcie_bar0_wb_addr_o_feed(27 downto 2) <= rxtlp_decodedaddress(27 downto 2) + tlp_datacount -1; pcie_bar0_wb_addr_o_feed(1 downto 0) <= bit10(1 downto 0); pcie_bar0_wb_sel_o_feed <= rxtlp_firstdw_be; tlp_state_copy <= tlp_state; if (tlp_state_copy = tlp_state) then start_read_wb0 <= '0'; else --generate just one pulse start_read_wb0 <= '1'; end if; if (wb_transaction_complete='1') then bram_txtlp_writedata <= pcie_bar0_wb_data_i_latched; bram_txtlp_we <= "1"; if (tlp_payloadsize_dwords = tlp_datacount)then tlp_state <= "01111110"; --read completion --bram_txtlp_writeaddress remains the same to capture data in next clock cycle else tlp_state <= "00011110"; --one more wb read bram_txtlp_writeaddress <= bram_txtlp_writeaddress +1; tlp_datacount <= tlp_datacount +1; end if; else bram_txtlp_we <= "0"; end if; --* read restart STATE * when "00011110" => --state 30 tlp_state <= "00000011"; bram_txtlp_we <= "0"; --intermediate state before completion (to ensure data latch at address-4) when "01111110" => --state 126 tlp_state <= "00000100"; bram_txtlp_writeaddress <= (OTHERS => '0'); --pre-write header-DW1: bram_txtlp_writedata (31) <= flag1; --reserved bram_txtlp_writedata (30 downto 24) <= "1001010"; --type= rd completion bram_txtlp_writedata (23 downto 0) <= rxdw1_23_0; --various fields pcie_received_tlp (23 downto 0); --Calculate completion header's "rcompl_bytecount_field" from rxtlp_firstdw_be, rxtlp_lastdw_be, tlp_payloadsize_dwords if (rxtlp_lastdw_be="0000") then --max 1DW if (rxtlp_firstdw_be="1111") then --4bytes rcompl_bytecount_field <= "0000000100"; elsif (rxtlp_firstdw_be="0111" or rxtlp_firstdw_be="1110") then rcompl_bytecount_field <= "0000000011"; elsif (rxtlp_firstdw_be="0011" or rxtlp_firstdw_be="1100" or rxtlp_firstdw_be="0110") then rcompl_bytecount_field <= "0000000010"; else rcompl_bytecount_field <= "0000000001"; end if; else --more than 1DW: right now we dont support non-aligned multi-Dword accesses rcompl_bytecount_field(9 downto 2) <= tlp_payloadsize_dwords; rcompl_bytecount_field(1 downto 0) <= "00"; end if; --********** READ COMPLETION STATE ********** --assemble the tx TLP and initiate the transmit --buffer signals bram_txtlp_we, bram_txtlp_writeaddress, bram_txtlp_writedata when "00000100" => --state 4 tlp_state_copy <= tlp_state; bram_txtlp_writeaddress <= bram_txtlp_writeaddress +1; if (bram_txtlp_writeaddress="000000000") then --if address is 0: launch data for next lock/address(1): header-2.dw bram_txtlp_writedata (31 downto 16) <= cfg_completer_id; --completer ID bram_txtlp_writedata (15 downto 13) <= "000"; --status= succesful*** bram_txtlp_writedata (12) <= '0'; --reserved bram_txtlp_writedata (11 downto 10) <= "00"; bram_txtlp_writedata (9 downto 0) <= rcompl_bytecount_field; --total bytes returned bram_txtlp_we <= "1"; elsif (bram_txtlp_writeaddress="000000001") then --if address is 1: launch data for next lock/address(2): header-3.dw bram_txtlp_writedata (31 downto 16) <= rxtlp_requesterid; --requester ID bram_txtlp_writedata (15 downto 8) <= pcie_rxtlp_tag ; --pcie_received_tlp (47 downto 40);--tag bram_txtlp_writedata (7) <= '0'; --reserved bram_txtlp_writedata (6 downto 2) <= rxtlp_decodedaddress(6 downto 2); --lower address bram_txtlp_writedata (1 downto 0) <= bit10(1 downto 0); --lower address else --data dwords, disable writes from next clock cycle bram_txtlp_we <= "0"; end if; --one pulse to start the ep-if statemachine, upon arriving to this state if (tlp_state_copy = tlp_state) then pcie_there_is_a_new_tlp_to_transmit <= '0'; else pcie_there_is_a_new_tlp_to_transmit <= '1'; end if; --back to idle when the ep-if tx is finished: (wait to avoid overwrite) if (pcie_tlp_tx_complete='1') then tlp_state <= "00000000"; end if; --********** UNSUPPORTED REQUEST STATE ********** --completion response with status=001 when "00000101" => --state 5 tlp_state_copy <= tlp_state; tlp_payloadsize_dwords <= "00000000"; bram_txtlp_writeaddress <= bram_txtlp_writeaddress +1; --assembling the TLP packet: ) if (bram_txtlp_writeaddress="111111111") then --header 1.dw bram_txtlp_we <= "1"; bram_txtlp_writedata (31) <= flag1; --reserved bram_txtlp_writedata (30 downto 24) <= "1001010"; --type= rd completion bram_txtlp_writedata (23 downto 0) <= rxdw1_23_0; --various fields pcie_received_tlp (23 downto 0); elsif (bram_txtlp_writeaddress="000000000") then --header 2.dw bram_txtlp_we <= "1"; bram_txtlp_writedata (31 downto 16) <= cfg_completer_id; --completer ID bram_txtlp_writedata (15 downto 13) <= "000"; --status= UNSUPPORTED REQUEST *** bram_txtlp_writedata (12) <= '0'; --reserved bram_txtlp_writedata (11 downto 0) <= "000000000000"; --remaining byte count elsif (bram_txtlp_writeaddress="000000001") then --header 3.dw bram_txtlp_we <= "1"; bram_txtlp_writedata (31 downto 16) <= rxtlp_requesterid; --requester ID bram_txtlp_writedata (15 downto 8) <= pcie_rxtlp_tag ; --pcie_received_tlp (47 downto 40);--tag bram_txtlp_writedata (7) <= '0'; --reserved bram_txtlp_writedata (6 downto 2) <= rxtlp_decodedaddress(6 downto 2); --lower address bram_txtlp_writedata (1 downto 0) <= bit10(1 downto 0); --lower address else --data dwords bram_txtlp_we <= "0"; end if; --one pulse to start the ep-if statemachine, upon arriving to this state if (tlp_state_copy = tlp_state) then pcie_there_is_a_new_tlp_to_transmit <= '0'; else pcie_there_is_a_new_tlp_to_transmit <= '1'; end if; --back to idle when finished: if (pcie_tlp_tx_complete='1') then tlp_state <= "00000000"; end if; when others => --error tlp_state <= "00000000"; --go to state 0 end case; end if; end if; end process; --end tlp statemachine --byte enable encoding to wb_address bit1:0 --this does not swap the endian, since only the data is swapped in the pcie packets. process ( pciewb_localreset_n, rxtlp_firstdw_be ) begin if (pciewb_localreset_n = '0') then bit10(1 downto 0) <="00"; else if (rxtlp_firstdw_be ="0001") then bit10(1 downto 0) <= "00"; elsif (rxtlp_firstdw_be ="0010") then bit10(1 downto 0) <= "01"; elsif (rxtlp_firstdw_be ="0100") then bit10(1 downto 0) <= "10"; elsif (rxtlp_firstdw_be ="1000") then bit10(1 downto 0) <= "11"; elsif (rxtlp_firstdw_be ="0011") then bit10(1 downto 0) <= "00"; elsif (rxtlp_firstdw_be ="1100") then bit10(1 downto 0) <= "10"; elsif (rxtlp_firstdw_be ="1111") then bit10(1 downto 0) <= "00"; else --this should never happen bit10(1 downto 0) <= "00"; end if; end if; end process; -- INTERRUPTS: ------------------------------------------------------------------------- --to assert an interrupt, use the cfg_interrupt_assert_n pin. --datasheet text: --As shown in Figure 6-30, the user application first asserts cfg_interrupt_n and --cfg_interrupt_assert_n to assert the interrupt. The user application should select a --specific interrupt (INTA, INTB, INTC, or INTD) using cfg_interrupt_di[7:0] as shown --in Table 6-19. -- The core then asserts cfg_interrupt_rdy_n to indicate the interrupt has been accepted. --On the following clock cycle, the user application deasserts cfg_interrupt_n and, if the --Interrupt Disable bit in the PCI Command register is set to 0, the core sends an assert --interrupt message (Assert_INTA, Assert_INTB, and so forth). -- After the user application has determined that the interrupt has been serviced, it --asserts cfg_interrupt_n while deasserting cfg_interrupt_assert_n to deassert the --interrupt. The appropriate interrupt must be indicated via cfg_interrupt_di[7:0]. -- The core then asserts cfg_interrupt_rdy_n to indicate the interrupt deassertion has --been accepted. On the following clock cycle, the user application deasserts --cfg_interrupt_n and the core sends a deassert interrupt message (Deassert_INTA, --Deassert_INTB, and so forth). --cfg_interrupt_di[7:0] value Legacy Interrupt --00h INTA --01h INTB --02h INTC --03h INTD cfg_interrupt_di <= "00000000"; --intA used --prohibit IRQ assert when TLP state machine not idle. -- if an IRQ is asserted between a read request and completion, it causes an error in the endpoint block. -- added by StBa, AAC Microtec, 2012 irq_prohibit <= not tlpstm_isin_idle; process (pciewb_localreset_n, trn_clk, pcie_irq, pcieirq_state, cfg_interrupt_rdy_n) begin if (pciewb_localreset_n='0') then pcieirq_state <= "00000000"; cfg_interrupt_n <= '1'; cfg_interrupt_assert_n_1 <= '1'; else if (trn_clk'event and trn_clk = '1') then case ( pcieirq_state ) is --********** idle STATE ********** when "00000000" => --state 0 if (pcie_irq = '1' and irq_prohibit = '0') then pcieirq_state <= "00000001"; cfg_interrupt_n <= '0'; --active else cfg_interrupt_n <= '1'; --inactive end if; cfg_interrupt_assert_n_1 <= '0'; --0=assert, 1=deassert --********** assert STATE ********** when "00000001" => --state 1 if (cfg_interrupt_rdy_n ='0') then --ep accepted it cfg_interrupt_n <= '1'; --deassert the request pcieirq_state <= "00000010"; else cfg_interrupt_n <= '0'; --request INTA assertion end if; --********** pcie_irq kept asserted STATE ********** when "00000010" => --state 2 if (pcie_irq = '0' and irq_prohibit='0') then --pcie_irq gets deasserted pcieirq_state <= "00000011"; end if; cfg_interrupt_n <= '1'; --inactive cfg_interrupt_assert_n_1 <= '1'; --0=assert, 1=deassert --********** DEassert STATE ********** when "00000011" => --state 3 if (cfg_interrupt_rdy_n ='0') then --ep accepted it cfg_interrupt_n <= '1'; --deassert the request pcieirq_state <= "00000000"; else cfg_interrupt_n <= '0'; --request INTA DEassertion end if; when others => --error pcieirq_state <= "00000000"; --go to state 0 end case; end if; end if; end process; --this (little delay) is to fix a hold time violation created inside the pcie-ep ip: cfg_interrupt_assert_n <= cfg_interrupt_assert_n_1 or (not pciewb_localreset_n); -- -------- END OF FILE ------------------------------------------------------------------------------------- end Behavioral;