library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity pcie_altera is port( clk125_i : in std_logic; -- 125 MHz, free running cal_clk50_i : in std_logic; -- 50 MHz, shared between all PHYs rstn_i : in std_logic; -- Power on reset rstn_o : out std_logic; -- If PCIe resets pcie_refclk_i : in std_logic; -- 100 MHz, must not derive clk125_i or cal_clk50_i pcie_rstn_i : in std_logic; -- PCIe reset pin pcie_rx_i : in std_logic_vector(3 downto 0); pcie_tx_o : out std_logic_vector(3 downto 0); cfg_busdev : out std_logic_vector(12 downto 0); -- Configured Bus#:Dev# -- Simplified wishbone output stream wb_clk_o : out std_logic; rx_wb_stb_o : out std_logic; rx_wb_dat_o : out std_logic_vector(31 downto 0); rx_wb_stall_i : in std_logic; tx_wb_stb_i : in std_logic; tx_wb_dat_i : in std_logic_vector(31 downto 0); tx_wb_stall_o : out std_logic); end pcie_altera; architecture rtl of pcie_altera is component altera_reconfig is port( reconfig_clk : in std_logic; reconfig_fromgxb : in std_logic_vector(16 downto 0); busy : out std_logic; reconfig_togxb : out std_logic_vector(3 downto 0)); end component; component altera_pcie is port ( signal app_int_sts : in std_logic; signal app_msi_num : in std_logic_vector (4 downto 0); signal app_msi_req : in std_logic; signal app_msi_tc : in std_logic_vector (2 downto 0); signal busy_altgxb_reconfig : in std_logic; signal cal_blk_clk : in std_logic; signal cpl_err : in std_logic_vector (6 downto 0); signal cpl_pending : in std_logic; signal crst : in std_logic; signal fixedclk_serdes : in std_logic; signal gxb_powerdown : in std_logic; signal hpg_ctrler : in std_logic_vector (4 downto 0); signal lmi_addr : in std_logic_vector (11 downto 0); signal lmi_din : in std_logic_vector (31 downto 0); signal lmi_rden : in std_logic; signal lmi_wren : in std_logic; signal npor : in std_logic; signal pclk_in : in std_logic; signal pex_msi_num : in std_logic_vector (4 downto 0); signal phystatus_ext : in std_logic; signal pipe_mode : in std_logic; signal pld_clk : in std_logic; signal pll_powerdown : in std_logic; signal pm_auxpwr : in std_logic; signal pm_data : in std_logic_vector (9 downto 0); signal pm_event : in std_logic; signal pme_to_cr : in std_logic; signal reconfig_clk : in std_logic; signal reconfig_togxb : in std_logic_vector (3 downto 0); signal refclk : in std_logic; signal rx_in0 : in std_logic; signal rx_in1 : in std_logic; signal rx_in2 : in std_logic; signal rx_in3 : in std_logic; signal rx_st_mask0 : in std_logic; signal rx_st_ready0 : in std_logic; signal rxdata0_ext : in std_logic_vector (7 downto 0); signal rxdata1_ext : in std_logic_vector (7 downto 0); signal rxdata2_ext : in std_logic_vector (7 downto 0); signal rxdata3_ext : in std_logic_vector (7 downto 0); signal rxdatak0_ext : in std_logic; signal rxdatak1_ext : in std_logic; signal rxdatak2_ext : in std_logic; signal rxdatak3_ext : in std_logic; signal rxelecidle0_ext : in std_logic; signal rxelecidle1_ext : in std_logic; signal rxelecidle2_ext : in std_logic; signal rxelecidle3_ext : in std_logic; signal rxstatus0_ext : in std_logic_vector (2 downto 0); signal rxstatus1_ext : in std_logic_vector (2 downto 0); signal rxstatus2_ext : in std_logic_vector (2 downto 0); signal rxstatus3_ext : in std_logic_vector (2 downto 0); signal rxvalid0_ext : in std_logic; signal rxvalid1_ext : in std_logic; signal rxvalid2_ext : in std_logic; signal rxvalid3_ext : in std_logic; signal srst : in std_logic; signal test_in : in std_logic_vector (39 downto 0); signal tx_st_data0 : in std_logic_vector (63 downto 0); signal tx_st_eop0 : in std_logic; signal tx_st_err0 : in std_logic; signal tx_st_sop0 : in std_logic; signal tx_st_valid0 : in std_logic; signal app_int_ack : out std_logic; signal app_msi_ack : out std_logic; signal clk250_out : out std_logic; signal clk500_out : out std_logic; signal core_clk_out : out std_logic; signal derr_cor_ext_rcv0 : out std_logic; signal derr_cor_ext_rpl : out std_logic; signal derr_rpl : out std_logic; signal dlup_exit : out std_logic; signal hotrst_exit : out std_logic; signal ko_cpl_spc_vc0 : out std_logic_vector (19 downto 0); signal l2_exit : out std_logic; signal lane_act : out std_logic_vector (3 downto 0); signal lmi_ack : out std_logic; signal lmi_dout : out std_logic_vector (31 downto 0); signal ltssm : out std_logic_vector (4 downto 0); signal npd_alloc_1cred_vc0 : out std_logic; signal npd_cred_vio_vc0 : out std_logic; signal nph_alloc_1cred_vc0 : out std_logic; signal nph_cred_vio_vc0 : out std_logic; signal pme_to_sr : out std_logic; signal powerdown_ext : out std_logic_vector (1 downto 0); signal r2c_err0 : out std_logic; signal rate_ext : out std_logic; signal rc_pll_locked : out std_logic; signal rc_rx_digitalreset : out std_logic; signal reconfig_fromgxb : out std_logic_vector (16 downto 0); signal reset_status : out std_logic; signal rx_fifo_empty0 : out std_logic; signal rx_fifo_full0 : out std_logic; signal rx_st_bardec0 : out std_logic_vector (7 downto 0); signal rx_st_be0 : out std_logic_vector (7 downto 0); signal rx_st_data0 : out std_logic_vector (63 downto 0); signal rx_st_eop0 : out std_logic; signal rx_st_err0 : out std_logic; signal rx_st_sop0 : out std_logic; signal rx_st_valid0 : out std_logic; signal rxpolarity0_ext : out std_logic; signal rxpolarity1_ext : out std_logic; signal rxpolarity2_ext : out std_logic; signal rxpolarity3_ext : out std_logic; signal suc_spd_neg : out std_logic; signal test_out : out std_logic_vector (8 downto 0); signal tl_cfg_add : out std_logic_vector (3 downto 0); signal tl_cfg_ctl : out std_logic_vector (31 downto 0); signal tl_cfg_ctl_wr : out std_logic; signal tl_cfg_sts : out std_logic_vector (52 downto 0); signal tl_cfg_sts_wr : out std_logic; signal tx_cred0 : out std_logic_vector (35 downto 0); signal tx_fifo_empty0 : out std_logic; signal tx_fifo_full0 : out std_logic; signal tx_fifo_rdptr0 : out std_logic_vector (3 downto 0); signal tx_fifo_wrptr0 : out std_logic_vector (3 downto 0); signal tx_out0 : out std_logic; signal tx_out1 : out std_logic; signal tx_out2 : out std_logic; signal tx_out3 : out std_logic; signal tx_st_ready0 : out std_logic; signal txcompl0_ext : out std_logic; signal txcompl1_ext : out std_logic; signal txcompl2_ext : out std_logic; signal txcompl3_ext : out std_logic; signal txdata0_ext : out std_logic_vector (7 downto 0); signal txdata1_ext : out std_logic_vector (7 downto 0); signal txdata2_ext : out std_logic_vector (7 downto 0); signal txdata3_ext : out std_logic_vector (7 downto 0); signal txdatak0_ext : out std_logic; signal txdatak1_ext : out std_logic; signal txdatak2_ext : out std_logic; signal txdatak3_ext : out std_logic; signal txdetectrx_ext : out std_logic; signal txelecidle0_ext : out std_logic; signal txelecidle1_ext : out std_logic; signal txelecidle2_ext : out std_logic; signal txelecidle3_ext : out std_logic); end component; function is_zero(x : std_logic_vector) return std_logic is constant zero : std_logic_vector(x'length-1 downto 0) := (others => '0'); begin if x = zero then return '1'; else return '0'; end if; end is_zero; signal core_clk_out : std_logic; signal rstn : std_logic; signal reconfig_clk : std_logic; signal reconfig_busy : std_logic; signal reconfig_fromgxb : std_logic_vector(16 downto 0); signal reconfig_togxb : std_logic_vector(3 downto 0); signal tl_cfg_add : std_logic_vector(3 downto 0); signal tl_cfg_ctl : std_logic_vector(31 downto 0); signal tl_cfg_delay : std_logic_vector(3 downto 0); signal l2_exit, hotrst_exit, dlup_exit : std_logic; signal npor, crst, srst, rst_reg : std_logic; signal pme_shift : std_logic_vector(4 downto 0); signal rx_st_ready0, rx_st_valid0 : std_logic; signal rx_st_be0 : std_logic_vector(7 downto 0); signal rx_st_data0 : std_logic_vector(63 downto 0); signal r64_ready : std_logic_vector(1 downto 0); -- length must equal the latency of the Avalon RX bus signal r64_dat, s64_dat : std_logic_vector(63 downto 0); signal s64_need_refill, s64_filling, s64_valid, s64_advance, r64_full, r64_skip, s64_skip : std_logic; signal r32_word, s32_word, s32_progress, r32_full, s32_need_refill, r32_skip, s32_enter0 : std_logic; signal r32_dat0, r32_dat1 : std_logic_vector(31 downto 0); begin reconfig_clk <= cal_clk50_i; wb_clk_o <= core_clk_out; reconfig : altera_reconfig port map( reconfig_clk => reconfig_clk, reconfig_fromgxb => reconfig_fromgxb, busy => reconfig_busy, reconfig_togxb => reconfig_togxb); pcie : altera_pcie port map( -- Clocking refclk => pcie_refclk_i, pld_clk => core_clk_out, core_clk_out => core_clk_out, -- Simulation only clocks: pclk_in => pcie_refclk_i, clk250_out => open, clk500_out => open, -- Transceiver control cal_blk_clk => cal_clk50_i, -- All transceivers in FPGA must use the same calibration clock reconfig_clk => reconfig_clk, fixedclk_serdes => clk125_i, gxb_powerdown => '0', pll_powerdown => '0', reconfig_togxb => reconfig_togxb, reconfig_fromgxb => reconfig_fromgxb, busy_altgxb_reconfig => reconfig_busy, -- PCIe lanes rx_in0 => pcie_rx_i(0), rx_in1 => pcie_rx_i(1), rx_in2 => pcie_rx_i(2), rx_in3 => pcie_rx_i(3), tx_out0 => pcie_tx_o(0), tx_out1 => pcie_tx_o(1), tx_out2 => pcie_tx_o(2), tx_out3 => pcie_tx_o(3), -- Avalon RX rx_st_mask0 => '0', rx_st_ready0 => rx_st_ready0, rx_st_bardec0 => open, -- 7 downto 0 rx_st_be0 => rx_st_be0, -- 7 downto 0 rx_st_data0 => rx_st_data0, -- 63 downto 0 rx_st_eop0 => open, rx_st_err0 => open, rx_st_sop0 => open, rx_st_valid0 => rx_st_valid0, rx_fifo_empty0 => open, -- informative/debug only (ignore in real design) rx_fifo_full0 => open, -- informative/debug only (ignore in real design) -- Errors in RX buffer derr_cor_ext_rcv0 => open, derr_cor_ext_rpl => open, derr_rpl => open, r2c_err0 => open, -- Avalon TX tx_st_data0 => (others => '0'), tx_st_eop0 => '0', tx_st_err0 => '0', tx_st_sop0 => '0', tx_st_valid0 => '0', tx_st_ready0 => open, tx_fifo_empty0 => open, tx_fifo_full0 => open, tx_fifo_rdptr0 => open, -- 3 downto 0 tx_fifo_wrptr0 => open, -- 3 downto 0 -- Avalon TX credit management tx_cred0 => open, -- 35 downto 0 npd_alloc_1cred_vc0 => open, npd_cred_vio_vc0 => open, nph_alloc_1cred_vc0 => open, nph_cred_vio_vc0 => open, -- Report completion error status cpl_err => (others => '0'), -- 6 downto 0 cpl_pending => '0', lmi_addr => (others => '0'), -- 11 downto 0 lmi_din => (others => '0'), -- 31 downto 0 lmi_rden => '0', lmi_wren => '0', lmi_ack => open, lmi_dout => open, -- 31 downto 0 ko_cpl_spc_vc0 => open, -- 19 downto 0 -- External PHY (PIPE). Not used; using altera PHY. pipe_mode => '0', rxdata0_ext => (others => '0'), -- 7 downto 0 rxdata1_ext => (others => '0'), -- 7 downto 0 rxdata2_ext => (others => '0'), -- 7 downto 0 rxdata3_ext => (others => '0'), -- 7 downto 0 rxdatak0_ext => '0', rxdatak1_ext => '0', rxdatak2_ext => '0', rxdatak3_ext => '0', rxelecidle0_ext => '0', rxelecidle1_ext => '0', rxelecidle2_ext => '0', rxelecidle3_ext => '0', rxstatus0_ext => (others => '0'), -- 2 downto 0 rxstatus1_ext => (others => '0'), -- 2 downto 0 rxstatus2_ext => (others => '0'), -- 2 downto 0 rxstatus3_ext => (others => '0'), -- 2 downto 0 rxvalid0_ext => '0', rxvalid1_ext => '0', rxvalid2_ext => '0', rxvalid3_ext => '0', rxpolarity0_ext => open, rxpolarity1_ext => open, rxpolarity2_ext => open, rxpolarity3_ext => open, txcompl0_ext => open, txcompl1_ext => open, txcompl2_ext => open, txcompl3_ext => open, txdata0_ext => open, txdata1_ext => open, -- 7 downto 0 txdata2_ext => open, -- 7 downto 0 txdata3_ext => open, -- 7 downto 0 txdatak0_ext => open, txdatak1_ext => open, txdatak2_ext => open, txdatak3_ext => open, txdetectrx_ext => open, txelecidle0_ext => open, txelecidle1_ext => open, txelecidle2_ext => open, txelecidle3_ext => open, phystatus_ext => '0', powerdown_ext => open, -- 1 downto 0 rate_ext => open, -- PCIe interrupts (for endpoint) app_int_sts => '0', app_msi_num => (others => '0'), -- 4 downto 0 app_msi_req => '0', app_msi_tc => (others => '0'), -- 2 downto 0 pex_msi_num => (others => '0'), -- 4 downto 0 app_int_ack => open, app_msi_ack => open, -- PCIe configuration space hpg_ctrler => (others => '0'), -- 4 downto 0 tl_cfg_add => tl_cfg_add, -- 3 downto 0 tl_cfg_ctl => tl_cfg_ctl, -- 31 downto 0 tl_cfg_ctl_wr => open, tl_cfg_sts => open, -- 52 downto 0 tl_cfg_sts_wr => open, -- Power management signals pm_auxpwr => '0', pm_data => (others => '0'), -- 9 downto 0 pm_event => '0', pme_to_cr => pme_shift(pme_shift'length-1), pme_to_sr => pme_shift(0), -- Reset and link training npor => npor, srst => srst, crst => crst, l2_exit => l2_exit, hotrst_exit => hotrst_exit, dlup_exit => dlup_exit, suc_spd_neg => open, ltssm => open, -- 4 downto 0 rc_pll_locked => open, reset_status => open, -- Debugging signals lane_act => open, -- 3 downto 0 test_in => (others => '0'), -- 39 downto 0 test_out => open, -- 8 downto 0 -- WTF? Not documented rc_rx_digitalreset => open); reset : process(core_clk_out) begin if rising_edge(core_clk_out) then pme_shift(pme_shift'length-1 downto 1) <= pme_shift(pme_shift'length-2 downto 0); if (l2_exit and hotrst_exit and dlup_exit) = '0' then rst_reg <= '1'; crst <= '1'; srst <= '1'; else rst_reg <= '0'; crst <= rst_reg; srst <= rst_reg; end if; end if; end process; npor <= rstn_i and pcie_rstn_i; rstn <= rstn_i or rst_reg; rstn_o <= rstn; -- Recover bus:device IDs from config space cfg : process(core_clk_out) begin if rising_edge(core_clk_out) then -- There is some instability on tl_cfg_ctl. -- We make sure to latch it in the middle of one of its 8 cycle periods tl_cfg_delay(tl_cfg_delay'left downto 1) <= tl_cfg_delay(tl_cfg_delay'left-1 downto 0); if tl_cfg_add = x"f" then tl_cfg_delay(0) <= '0'; else tl_cfg_delay(0) <= '1'; end if; if tl_cfg_delay(tl_cfg_delay'left) = '1' and is_zero(tl_cfg_delay(tl_cfg_delay'left-1 downto 0)) = '1' then cfg_busdev <= tl_cfg_ctl(12 downto 0); end if; end if; end process; -- Stream rx data out as wishbone rx_wb_stb_o <= r32_full; rx_wb_dat_o <= r32_dat0; -- Advance state if the WB RX bus made progress s32_progress <= r32_full and not rx_wb_stall_i; s32_word <= (not r32_word and not r32_skip) when s32_progress = '1' else r32_word; s32_enter0 <= (r32_word or r32_skip) and s32_progress; -- The 32-bit buffers become empty when transitioning to word0 s32_need_refill <= not r32_full or s32_enter0; -- Grab data when we need data and there is some ready s64_advance <= s64_valid and s32_need_refill; rx_data32 : process(core_clk_out) begin if rising_edge(core_clk_out) then if rstn = '0' then r32_word <= '0'; r32_full <= '0'; else r32_full <= s64_valid or not s32_need_refill; r32_word <= s32_word; end if; if s64_advance = '1' then r32_dat0 <= s64_dat(31 downto 0); r32_dat1 <= s64_dat(63 downto 32); r32_skip <= s64_skip; end if; if s32_word = '1' then r32_dat0 <= r32_dat1; end if; end if; end process; -- Is the Avalon bus filling data this cycle? s64_filling <= rx_st_valid0 and r64_ready(r64_ready'length-1); -- Can we provide data to the 32-bit layer on this cycle? s64_valid <= r64_full or s64_filling; -- We need to refill our buffer if we were empty or just got drained s64_need_refill <= s64_advance or not s64_valid; -- Supply the 64-bit data to the 32-bit stream with possible asynchronous bypass s64_dat <= r64_dat when r64_full = '1' else rx_st_data0; s64_skip <= r64_skip when r64_full = '1' else is_zero(rx_st_be0(7 downto 4)); -- Issue a fetch only if we need refill and no fetch is pending rx_st_ready0 <= s64_need_refill and is_zero(r64_ready(r64_ready'length-2 downto 0)); rx_data64: process(core_clk_out) begin if rising_edge(core_clk_out) then if rstn = '0' then r64_full <= '0'; r64_ready <= (others => '0'); else r64_full <= not s64_need_refill; r64_ready <= r64_ready(r64_ready'length-2 downto 0) & rx_st_ready0; end if; r64_dat <= s64_dat; r64_skip <= s64_skip; end if; end process; end rtl;