--- /dev/null
+--+-------------------------------------------------------------------------------------------------+\r
+--| |\r
+--| File: pciwbsequ.vhd |\r
+--| |\r
+--| Project: pci32tlite_oc |\r
+--| |\r
+--| Description: FSM controlling PCI to Whisbone sequence. |\r
+--| |\r
+--+-------------------------------------------------------------------------------------------------+\r
+--| |\r
+--| Revision history : |\r
+--| Date Version Author Description |\r
+--| 2005-05-13 R00A00 PAU First alfa revision (eng) |\r
+--| 2006-01-09 MS added debug signals debug_init, debug_access | |\r
+--| |\r
+--| To do: |\r
+--| |\r
+--+-------------------------------------------------------------------------------------------------+\r
+--+-----------------------------------------------------------------+\r
+--| |\r
+--| Copyright (C) 2005 Peio Azkarate, peio@opencores.org | \r
+--| |\r
+--| This source file may be used and distributed without |\r
+--| restriction provided that this copyright statement is not |\r
+--| removed from the file and that any derivative work contains |\r
+--| the original copyright notice and the associated disclaimer. |\r
+--| |\r
+--| This source file is free software; you can redistribute it |\r
+--| and/or modify it under the terms of the GNU Lesser General |\r
+--| Public License as published by the Free Software Foundation; |\r
+--| either version 2.1 of the License, or (at your option) any |\r
+--| later version. |\r
+--| |\r
+--| This source is distributed in the hope that it will be |\r
+--| useful, but WITHOUT ANY WARRANTY; without even the implied |\r
+--| warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |\r
+--| PURPOSE. See the GNU Lesser General Public License for more |\r
+--| details. |\r
+--| |\r
+--| You should have received a copy of the GNU Lesser General |\r
+--| Public License along with this source; if not, download it |\r
+--| from http://www.opencores.org/lgpl.shtml |\r
+--| |\r
+--+-----------------------------------------------------------------+ \r
+\r
+\r
+--+-----------------------------------------------------------------------------+\r
+--| LIBRARIES |\r
+--+-----------------------------------------------------------------------------+\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+\r
+--+-----------------------------------------------------------------------------+\r
+--| ENTITY |\r
+--+-----------------------------------------------------------------------------+\r
+\r
+entity pciwbsequ is\r
+port (\r
+\r
+ -- General \r
+ clk_i : in std_logic;\r
+ nrst_i : in std_logic;\r
+ -- pci \r
+ --adr_i\r
+ cmd_i : in std_logic_vector(3 downto 0);\r
+ cbe_i : in std_logic_vector(3 downto 0);\r
+ frame_i : in std_logic;\r
+ irdy_i : in std_logic;\r
+ devsel_o : out std_logic;\r
+ trdy_o : out std_logic;\r
+ -- control\r
+ adrcfg_i : in std_logic;\r
+ adrmem_i : in std_logic;\r
+ pciadrLD_o : out std_logic;\r
+ pcidOE_o : out std_logic;\r
+ parOE_o : out std_logic;\r
+ wbdatLD_o : out std_logic;\r
+ wbrgdMX_o : out std_logic;\r
+ wbd16MX_o : out std_logic; \r
+ wrcfg_o : out std_logic;\r
+ rdcfg_o : out std_logic;\r
+ -- whisbone\r
+ wb_sel_o : out std_logic_vector(1 downto 0);\r
+ wb_we_o : out std_logic;\r
+ wb_stb_o : inout std_logic; \r
+ wb_cyc_o : out std_logic;\r
+ wb_ack_i : in std_logic;\r
+ wb_err_i : in std_logic; \r
+ -- debug signals\r
+ debug_init : out std_logic;\r
+ debug_access : out std_logic \r
+); \r
+end pciwbsequ;\r
+\r
+\r
+architecture rtl of pciwbsequ is\r
+\r
+\r
+--+-----------------------------------------------------------------------------+\r
+--| COMPONENTS |\r
+--+-----------------------------------------------------------------------------+\r
+--+-----------------------------------------------------------------------------+\r
+--| CONSTANTS |\r
+--+-----------------------------------------------------------------------------+\r
+--+-----------------------------------------------------------------------------+\r
+--| SIGNALS |\r
+--+-----------------------------------------------------------------------------+\r
+\r
+ type PciFSM is ( PCIIDLE, B_BUSY, S_DATA1, S_DATA2, TURN_AR ); \r
+ signal pst_pci : PciFSM;\r
+ signal nxt_pci : PciFSM;\r
+\r
+ signal sdata1 : std_logic;\r
+ signal sdata2 : std_logic;\r
+ signal idleNX : std_logic;\r
+ signal sdata1NX : std_logic;\r
+ signal sdata2NX : std_logic;\r
+ signal turnarNX : std_logic;\r
+ signal idle : std_logic;\r
+ signal devselNX_n : std_logic;\r
+ signal trdyNX_n : std_logic;\r
+ signal devsel : std_logic;\r
+ signal trdy : std_logic;\r
+ signal adrpci : std_logic;\r
+ signal acking : std_logic;\r
+ signal rdcfg : std_logic;\r
+ signal targOE : std_logic;\r
+ signal pcidOE : std_logic;\r
+\r
+\r
+begin\r
+ \r
+ --+-------------------------------------------------------------------------+\r
+ --| PCI-Whisbone Sequencer |\r
+ --+-------------------------------------------------------------------------+\r
+ \r
+ \r
+ --+-------------------------------------------------------------+\r
+ --| FSM PCI-Whisbone |\r
+ --+-------------------------------------------------------------+\r
+ \r
+ PCIFSM_CLOCKED: process( nrst_i, clk_i, nxt_pci )\r
+ begin\r
+ \r
+ if( nrst_i = '0' ) then\r
+ pst_pci <= PCIIDLE;\r
+ elsif( rising_edge(clk_i) ) then\r
+ pst_pci <= nxt_pci; \r
+ end if;\r
+ \r
+ end process PCIFSM_CLOCKED;\r
+\r
+\r
+ PCIFSM_COMB: process( pst_pci, frame_i, irdy_i, adrcfg_i, adrpci, acking )\r
+ begin\r
+ \r
+ devselNX_n <= '1';\r
+ trdyNX_n <= '1'; \r
+ case pst_pci is\r
+\r
+ when PCIIDLE =>\r
+ if ( frame_i = '0' ) then \r
+ nxt_pci <= B_BUSY; \r
+ else\r
+ nxt_pci <= PCIIDLE;\r
+ end if; \r
+ \r
+ when B_BUSY =>\r
+ if ( adrpci = '0' ) then\r
+ nxt_pci <= TURN_AR;\r
+ else\r
+ nxt_pci <= S_DATA1;\r
+ devselNX_n <= '0'; \r
+ end if;\r
+\r
+ when S_DATA1 =>\r
+ if ( acking = '1' ) then \r
+ nxt_pci <= S_DATA2;\r
+ devselNX_n <= '0'; \r
+ trdyNX_n <= '0'; \r
+ else\r
+ nxt_pci <= S_DATA1;\r
+ devselNX_n <= '0'; \r
+ end if; \r
+ \r
+ when S_DATA2 => \r
+ if ( frame_i = '1' and irdy_i = '0' ) then \r
+ nxt_pci <= TURN_AR;\r
+ else\r
+ nxt_pci <= S_DATA2;\r
+ devselNX_n <= '0'; \r
+ trdyNX_n <= '0'; \r
+ end if; \r
+ \r
+ when TURN_AR =>\r
+ if ( frame_i = '1' ) then\r
+ nxt_pci <= PCIIDLE;\r
+ else\r
+ nxt_pci <= TURN_AR;\r
+ end if;\r
+ \r
+ end case;\r
+ \r
+ end process PCIFSM_COMB; \r
+\r
+\r
+ --+-------------------------------------------------------------+\r
+ --| FSM control signals |\r
+ --+-------------------------------------------------------------+\r
+\r
+ adrpci <= adrmem_i or adrcfg_i;\r
+ acking <= '1' when ( wb_ack_i = '1' or wb_err_i = '1' ) or ( adrcfg_i = '1' and irdy_i = '0')\r
+ else '0'; \r
+\r
+\r
+ --+-------------------------------------------------------------+\r
+ --| FSM derived Control signals |\r
+ --+-------------------------------------------------------------+\r
+ idle <= '1' when ( pst_pci = PCIIDLE ) else '0';\r
+ sdata1 <= '1' when ( pst_pci = S_DATA1 ) else '0';\r
+ sdata2 <= '1' when ( pst_pci = S_DATA2 ) else '0';\r
+ idleNX <= '1' when ( nxt_pci = PCIIDLE ) else '0';\r
+ sdata1NX <= '1' when ( nxt_pci = S_DATA1 ) else '0'; \r
+ sdata2NX <= '1' when ( nxt_pci = S_DATA2 ) else '0';\r
+ turnarNX <= '1' when ( nxt_pci = TURN_AR ) else '0';\r
+ \r
+\r
+\r
+ --+-------------------------------------------------------------+\r
+ --| PCI Data Output Enable |\r
+ --+-------------------------------------------------------------+\r
+\r
+ PCIDOE_P: process( nrst_i, clk_i, cmd_i(0), sdata1NX, turnarNX )\r
+ begin\r
+\r
+ if ( nrst_i = '0' ) then \r
+ pcidOE <= '0';\r
+ elsif ( rising_edge(clk_i) ) then \r
+\r
+ if ( sdata1NX = '1' and cmd_i(0) = '0' ) then\r
+ pcidOE <= '1';\r
+ elsif ( turnarNX = '1' ) then\r
+ pcidOE <= '0';\r
+ end if; \r
+ \r
+ end if;\r
+\r
+ end process PCIDOE_P;\r
+\r
+ pcidOE_o <= pcidOE;\r
+\r
+\r
+ --+-------------------------------------------------------------+\r
+ --| PAR Output Enable |\r
+ --| PCI Read data phase |\r
+ --| PAR is valid 1 cicle after data is valid |\r
+ --+-------------------------------------------------------------+\r
+\r
+ PAROE_P: process( nrst_i, clk_i, cmd_i(0), sdata2NX, turnarNX )\r
+ begin\r
+\r
+ if ( nrst_i = '0' ) then \r
+ parOE_o <= '0';\r
+ elsif ( rising_edge(clk_i) ) then \r
+\r
+ if ( ( sdata2NX = '1' or turnarNX = '1' ) and cmd_i(0) = '0' ) then\r
+ parOE_o <= '1';\r
+ else\r
+ parOE_o <= '0';\r
+ end if; \r
+ \r
+ end if;\r
+ \r
+ end process PAROE_P;\r
+\r
+ \r
+ --+-------------------------------------------------------------+\r
+ --| Target s/t/s signals OE control |\r
+ --+-------------------------------------------------------------+\r
+\r
+-- targOE <= '1' when ( idle = '0' and adrpci = '1' ) else '0';\r
+ TARGOE_P: process( nrst_i, clk_i, sdata1NX, idleNX )\r
+ begin\r
+\r
+ if ( nrst_i = '0' ) then \r
+ targOE <= '0';\r
+ elsif ( rising_edge(clk_i) ) then \r
+\r
+ if ( sdata1NX = '1' ) then\r
+ targOE <= '1';\r
+ elsif ( idleNX = '1' ) then\r
+ targOE <= '0';\r
+ end if; \r
+ \r
+ end if;\r
+\r
+ end process TARGOE_P;\r
+ \r
+\r
+ --+-------------------------------------------------------------------------+\r
+ --| WHISBONE outs |\r
+ --+-------------------------------------------------------------------------+\r
+ \r
+ wb_cyc_o <= '1' when ( adrmem_i = '1' and sdata1 = '1' ) else '0';\r
+ wb_stb_o <= '1' when ( adrmem_i = '1' and sdata1 = '1' and irdy_i = '0' ) else '0';\r
+\r
+ -- PCI(Little endian) to WB(Big endian)\r
+ wb_sel_o(1) <= (not cbe_i(0)) or (not cbe_i(2));\r
+ wb_sel_o(0) <= (not cbe_i(1)) or (not cbe_i(3)); \r
+ -- \r
+ wb_we_o <= cmd_i(0);\r
+ \r
+\r
+ --+-------------------------------------------------------------------------+\r
+ --| Syncronized PCI outs |\r
+ --+-------------------------------------------------------------------------+\r
+ \r
+ PCISIG: process( nrst_i, clk_i, devselNX_n, trdyNX_n)\r
+ begin\r
+\r
+ if( nrst_i = '0' ) then \r
+ devsel <= '1';\r
+ trdy <= '1';\r
+ elsif( rising_edge(clk_i) ) then \r
+ \r
+ devsel <= devselNX_n;\r
+ trdy <= trdyNX_n;\r
+ \r
+ end if;\r
+ \r
+ end process PCISIG;\r
+\r
+ devsel_o <= devsel when ( targOE = '1' ) else 'Z';\r
+ trdy_o <= trdy when ( targOE = '1' ) else 'Z';\r
+ \r
+\r
+ --+-------------------------------------------------------------------------+\r
+ --| Other outs |\r
+ --+-------------------------------------------------------------------------+\r
+\r
+ -- rd/wr Configuration Space Registers\r
+ wrcfg_o <= '1' when ( adrcfg_i = '1' and cmd_i(0) = '1' and sdata2 = '1' ) else '0';\r
+ rdcfg <= '1' when ( adrcfg_i = '1' and cmd_i(0) = '0' and ( sdata1 = '1' or sdata2 = '1' ) ) else '0';\r
+ rdcfg_o <= rdcfg;\r
+ \r
+ -- LoaD enable signals\r
+ pciadrLD_o <= not frame_i;\r
+ wbdatLD_o <= wb_ack_i;\r
+\r
+ -- Mux control signals\r
+ wbrgdMX_o <= not rdcfg;\r
+ wbd16MX_o <= '1' when ( cbe_i(3) = '0' or cbe_i(2) = '0' ) else '0';\r
+ \r
+ --+-------------------------------------------------------------------------+\r
+ --| debug outs |\r
+ --+-------------------------------------------------------------------------+\r
+ \r
+ process (nrst_i, clk_i)\r
+ begin\r
+ if ( nrst_i = '0' ) then\r
+ debug_init <= '0';\r
+ elsif clk_i'event and clk_i = '1' then\r
+ if devsel = '0' then\r
+ debug_init <= '1';\r
+ end if;\r
+ end if;\r
+ end process; \r
+ \r
+ process (nrst_i, clk_i)\r
+ begin\r
+ if ( nrst_i = '0' ) then\r
+ debug_access <= '0';\r
+ elsif clk_i'event and clk_i = '1' then\r
+ if wb_stb_o = '1' then\r
+ debug_access <= '1';\r
+ end if;\r
+ end if;\r
+ end process; \r
+\r
+end rtl;\r