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