Line 4... |
Line 4... |
--
|
--
|
-- Create Date: 05/30/2010
|
-- Create Date: 05/30/2010
|
-- Modify date: 08/10/2012
|
-- Modify date: 08/10/2012
|
-- Design Name: pcie_mini
|
-- Design Name: pcie_mini
|
-- Module Name: xilinx_pcie2wb - Behavioral
|
-- Module Name: xilinx_pcie2wb - Behavioral
|
-- Version: 1.2
|
-- Version: 1.4
|
-- Project Name:
|
-- Project Name:
|
-- Target Devices: Xilinx Series-5/6/7 FPGAs
|
-- Target Devices: Xilinx Series-5/6/7 FPGAs
|
-- Tool versions: ISE-DS 12.1
|
-- Tool versions: ISE-DS 12.1
|
-- Description:
|
-- Description:
|
-- PCI-express endpoint block, transaction layer logic and back-end logic. The main
|
-- PCI-express endpoint block, transaction layer logic and back-end logic. The main
|
Line 44... |
Line 44... |
--
|
--
|
-- Revision:
|
-- Revision:
|
-- Revision 1.0 - File Created by Istvan Nagy
|
-- Revision 1.0 - File Created by Istvan Nagy
|
-- Revision 1.1 - some fixes by Istvan Nagy
|
-- Revision 1.1 - some fixes by Istvan Nagy
|
-- Revision 1.2 - interrupt fix by Stephen Battazzo
|
-- Revision 1.2 - interrupt fix by Stephen Battazzo
|
|
-- Revision 1.3 - 64-bit read fix, support for unaligned 32-bit read, and custom BAR0 address space size by Scott Cogan, FRIB
|
|
-- Revision 1.4 - Compatibility for MSI and Legacy interrupts by Scott Cogan, FRIB
|
--
|
--
|
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
|
|
library IEEE;
|
library IEEE;
|
use IEEE.STD_LOGIC_1164.ALL;
|
use IEEE.STD_LOGIC_1164.ALL;
|
Line 60... |
Line 62... |
use UNISIM.VComponents.all;
|
use UNISIM.VComponents.all;
|
|
|
|
|
|
|
entity xilinx_pcie2wb is
|
entity xilinx_pcie2wb is
|
|
generic (
|
|
-- BAR0_WIDTH = 28 sets address space for 2^28 bytes = 256MB, BARO = x"F0000000"
|
|
-- BAR0_WIDTH = 22 sets address space for 2^22 bytes = 4MB, BARO = x"FFC00000"
|
|
BAR0 : bit_vector := x"FFC00000";
|
|
BAR0_WIDTH : integer := 22
|
|
);
|
Port ( --FPGA PINS(EXTERNAL):
|
Port ( --FPGA PINS(EXTERNAL):
|
pci_exp_txp : out std_logic;
|
pci_exp_txp : out std_logic;
|
pci_exp_txn : out std_logic;
|
pci_exp_txn : out std_logic;
|
pci_exp_rxp : in std_logic;
|
pci_exp_rxp : in std_logic;
|
pci_exp_rxn : in std_logic;
|
pci_exp_rxn : in std_logic;
|
Line 81... |
Line 89... |
pcie_bar0_wb_ack_i : in std_logic;
|
pcie_bar0_wb_ack_i : in std_logic;
|
pcie_bar0_wb_clk_o : out std_logic; --62.5MHz
|
pcie_bar0_wb_clk_o : out std_logic; --62.5MHz
|
pcie_bar0_wb_sel_o : out std_logic_vector(3 downto 0);
|
pcie_bar0_wb_sel_o : out std_logic_vector(3 downto 0);
|
--OTHER:
|
--OTHER:
|
pcie_irq : in std_logic;
|
pcie_irq : in std_logic;
|
|
pcie_msi_enabled : out std_logic; -- added to monitor if MSI interrupt is enabled
|
pcie_resetout : out std_logic --active high
|
pcie_resetout : out std_logic --active high
|
);
|
);
|
end xilinx_pcie2wb;
|
end xilinx_pcie2wb;
|
|
|
|
|
Line 211... |
Line 220... |
SIGNAL pcie_tlp_tx_complete : std_logic;
|
SIGNAL pcie_tlp_tx_complete : std_logic;
|
|
|
--this signal added by StBa, AAC Microtec
|
--this signal added by StBa, AAC Microtec
|
SIGNAL irq_prohibit : std_logic;
|
SIGNAL irq_prohibit : std_logic;
|
|
|
SIGNAL pcieirq_state : std_logic_vector(7 downto 0);
|
SIGNAL pcieirq_state : std_logic_vector(2 downto 0);
|
SIGNAL txtrn_counter : 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 trn_rx_counter : std_logic_vector(7 downto 0);
|
SIGNAL cfg_completer_id : std_logic_vector(15 downto 0);
|
SIGNAL cfg_completer_id : std_logic_vector(15 downto 0);
|
SIGNAL wb0_state : std_logic_vector(7 downto 0);
|
SIGNAL wb0_state : std_logic_vector(7 downto 0);
|
SIGNAL epif_tx_state : std_logic_vector(7 downto 0);
|
SIGNAL epif_tx_state : std_logic_vector(7 downto 0);
|
Line 274... |
Line 283... |
VC0_TOTAL_CREDITS_PD : integer := 211;
|
VC0_TOTAL_CREDITS_PD : integer := 211;
|
VC0_TOTAL_CREDITS_NPH : integer := 8;
|
VC0_TOTAL_CREDITS_NPH : integer := 8;
|
VC0_TOTAL_CREDITS_CH : integer := 40;
|
VC0_TOTAL_CREDITS_CH : integer := 40;
|
VC0_TOTAL_CREDITS_CD : integer := 211;
|
VC0_TOTAL_CREDITS_CD : integer := 211;
|
VC0_CPL_INFINITE : boolean := TRUE;
|
VC0_CPL_INFINITE : boolean := TRUE;
|
BAR0 : bit_vector := x"F0000000";
|
BAR0 : bit_vector := BAR0; --x"F0000000";
|
BAR1 : bit_vector := x"00000000";
|
BAR1 : bit_vector := x"00000000";
|
BAR2 : bit_vector := x"00000000";
|
BAR2 : bit_vector := x"00000000";
|
BAR3 : bit_vector := x"00000000";
|
BAR3 : bit_vector := x"00000000";
|
BAR4 : bit_vector := x"00000000";
|
BAR4 : bit_vector := x"00000000";
|
BAR5 : bit_vector := x"00000000";
|
BAR5 : bit_vector := x"00000000";
|
Line 1152... |
Line 1161... |
|
|
|
|
--********** WRITE STATE **********
|
--********** WRITE STATE **********
|
--initiate WB write(s) (1...N DWORD accesses)
|
--initiate WB write(s) (1...N DWORD accesses)
|
when "00000010" => --state 2
|
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(BAR0_WIDTH-1 downto 2) <= rxtlp_decodedaddress(BAR0_WIDTH-1 downto 2) + tlp_datacount -1; -- BAR0 size is hardcoded here, by cutting MSB's off
|
pcie_bar0_wb_addr_o_feed(1 downto 0) <= bit10(1 downto 0);
|
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_sel_o_feed <= rxtlp_firstdw_be;
|
pcie_bar0_wb_data_o_feed <= bram_rxtlp_readdata;
|
pcie_bar0_wb_data_o_feed <= bram_rxtlp_readdata;
|
tlp_state_copy <= tlp_state;
|
tlp_state_copy <= tlp_state;
|
if (tlp_state_copy = tlp_state) then
|
if (tlp_state_copy = tlp_state) then
|
Line 1180... |
Line 1189... |
|
|
|
|
--********** READ STATE **********
|
--********** READ STATE **********
|
--initiate WB read, then go to completion state
|
--initiate WB read, then go to completion state
|
when "00000011" => --state 3
|
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(BAR0_WIDTH-1 downto 2) <= rxtlp_decodedaddress(BAR0_WIDTH-1 downto 2) + tlp_datacount -1;
|
pcie_bar0_wb_addr_o_feed(1 downto 0) <= bit10(1 downto 0);
|
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_sel_o_feed <= rxtlp_firstdw_be;
|
tlp_state_copy <= tlp_state;
|
tlp_state_copy <= tlp_state;
|
if (tlp_state_copy = tlp_state) then
|
if (tlp_state_copy = tlp_state) then
|
start_read_wb0 <= '0';
|
start_read_wb0 <= '0';
|
Line 1197... |
Line 1206... |
if (tlp_payloadsize_dwords = tlp_datacount)then
|
if (tlp_payloadsize_dwords = tlp_datacount)then
|
tlp_state <= "01111110"; --read completion
|
tlp_state <= "01111110"; --read completion
|
--bram_txtlp_writeaddress remains the same to capture data in next clock cycle
|
--bram_txtlp_writeaddress remains the same to capture data in next clock cycle
|
else
|
else
|
tlp_state <= "00011110"; --one more wb read
|
tlp_state <= "00011110"; --one more wb read
|
bram_txtlp_writeaddress <= bram_txtlp_writeaddress +1;
|
|
tlp_datacount <= tlp_datacount +1;
|
tlp_datacount <= tlp_datacount +1;
|
end if;
|
end if;
|
else
|
else
|
bram_txtlp_we <= "0";
|
bram_txtlp_we <= "0";
|
end if;
|
end if;
|
--* read restart STATE *
|
--* read restart STATE *
|
when "00011110" => --state 30
|
when "00011110" => --state 30
|
|
tlp_state_copy <= tlp_state; -- SC: required to re-trigger additional reads, start_read_wb0 <= '1'
|
|
bram_txtlp_writeaddress <= bram_txtlp_writeaddress +1; -- SC: increment address here (moved)
|
tlp_state <= "00000011";
|
tlp_state <= "00000011";
|
bram_txtlp_we <= "0";
|
bram_txtlp_we <= "0";
|
--intermediate state before completion (to ensure data latch at address-4)
|
--intermediate state before completion (to ensure data latch at address-4)
|
when "01111110" => --state 126
|
when "01111110" => --state 126
|
tlp_state <= "00000100";
|
tlp_state <= "00000100";
|
Line 1378... |
Line 1388... |
--prohibit IRQ assert when TLP state machine not idle.
|
--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.
|
-- 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
|
-- added by StBa, AAC Microtec, 2012
|
irq_prohibit <= not tlpstm_isin_idle;
|
irq_prohibit <= not tlpstm_isin_idle;
|
|
|
|
-- fixed compatibility with both MSI interrupts and legacy interrupts
|
|
-- added by SC, FRIB, 2016
|
|
pcie_msi_enabled <= cfg_interrupt_msienable;
|
|
|
process (pciewb_localreset_n, trn_clk, pcie_irq, pcieirq_state,
|
process (pciewb_localreset_n, trn_clk, pcie_irq, pcieirq_state,
|
cfg_interrupt_rdy_n)
|
cfg_interrupt_rdy_n)
|
begin
|
begin
|
if (pciewb_localreset_n='0') then
|
if (pciewb_localreset_n='0') then
|
pcieirq_state <= "00000000";
|
pcieirq_state <= "000";
|
cfg_interrupt_n <= '1';
|
cfg_interrupt_n <= '1';
|
cfg_interrupt_assert_n_1 <= '1';
|
cfg_interrupt_assert_n_1 <= '1';
|
else
|
else
|
if (trn_clk'event and trn_clk = '1') then
|
if (trn_clk'event and trn_clk = '1') then
|
case ( pcieirq_state ) is
|
case ( pcieirq_state ) is
|
|
|
--********** idle STATE **********
|
--********** idle STATE **********
|
when "00000000" => --state 0
|
when "000" => --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
|
cfg_interrupt_n <= '1'; --inactive
|
|
cfg_interrupt_assert_n_1 <= '1'; --0=assert, 1=deassert
|
|
if (pcie_irq = '1') then
|
|
pcieirq_state <= "001";
|
end if;
|
end if;
|
|
--********** wait for not irq_prohibit **********
|
|
when "001" => --state 1
|
|
if (irq_prohibit = '0') then
|
|
pcieirq_state <= "010";
|
|
cfg_interrupt_n <= '0'; --active
|
cfg_interrupt_assert_n_1 <= '0'; --0=assert, 1=deassert
|
cfg_interrupt_assert_n_1 <= '0'; --0=assert, 1=deassert
|
|
end if;
|
--********** assert STATE **********
|
--********** assert STATE **********
|
when "00000001" => --state 1
|
when "010" => --state 2
|
|
cfg_interrupt_n <= '0'; --request INTA assertion
|
if (cfg_interrupt_rdy_n ='0') then --ep accepted it
|
if (cfg_interrupt_rdy_n ='0') then --ep accepted it
|
cfg_interrupt_n <= '1'; --deassert the request
|
cfg_interrupt_n <= '1'; --deassert the request
|
pcieirq_state <= "00000010";
|
cfg_interrupt_assert_n_1 <= '1'; --0=assert, 1=deassert
|
else
|
pcieirq_state <= "011"; -- wait for IRQ deassert
|
cfg_interrupt_n <= '0'; --request INTA assertion
|
|
end if;
|
end if;
|
|
--********** (LEGACY) pcie_irq kept asserted STATE **********
|
--********** pcie_irq kept asserted STATE **********
|
when "011" => --state 3
|
when "00000010" => --state 2
|
if (pcie_irq='0' and irq_prohibit='0' and cfg_interrupt_msienable='0') then
|
if (pcie_irq = '0' and irq_prohibit='0') then --pcie_irq gets deasserted
|
pcieirq_state <= "100"; -- LEGACY, pcie_irq gets deasserted
|
pcieirq_state <= "00000011";
|
end if;
|
|
if (pcie_irq='0' and cfg_interrupt_msienable='1') then
|
|
pcieirq_state <= "000"; -- MSI IRQ, back to IDLE when pcie_irq deasserted
|
end if;
|
end if;
|
cfg_interrupt_n <= '1'; --inactive
|
cfg_interrupt_n <= '1'; --inactive
|
cfg_interrupt_assert_n_1 <= '1'; --0=assert, 1=deassert
|
cfg_interrupt_assert_n_1 <= '1'; --0=assert, 1=deassert
|
|
|
--********** DEassert STATE **********
|
--********** DEassert STATE **********
|
when "00000011" => --state 3
|
-- below state only used for legacy interrupts
|
|
when "100" => --state 4
|
|
cfg_interrupt_n <= '0'; --request INTA DEassertion
|
if (cfg_interrupt_rdy_n ='0') then --ep accepted it
|
if (cfg_interrupt_rdy_n ='0') then --ep accepted it
|
cfg_interrupt_n <= '1'; --deassert the request
|
cfg_interrupt_n <= '1'; --deassert the request
|
pcieirq_state <= "00000000";
|
pcieirq_state <= "000";
|
else
|
|
cfg_interrupt_n <= '0'; --request INTA DEassertion
|
|
end if;
|
end if;
|
|
|
when others => --error
|
when others => --error
|
pcieirq_state <= "00000000"; --go to state 0
|
pcieirq_state <= "000"; --go to state 0
|
end case;
|
end case;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|