-- Hi Emacs, this is -*- mode: vhdl; -*- ---------------------------------------------------------------------------------------------------- -- epp2fifo.vhd - Parallel Port (EPP mode) to FIFO interface circuit -- -- Its task is simple: -- * all data sent by host (PC) is stored in the RX fifo (8-bit width data bus) -- * all data read by host (PC) is obtained from the TX fifo (8-bit width data bus) -- -- The fifos are not included, they are external to this block. It is suposed that -- the tx fifo is standard (not FWFT: First Word Fall Thought) -- -- The FSM blocks WAIT signal in case the RX fifo is full or TX fifo is empty, therefore, maintains -- the necesary control data flow. -- -- Copyright (c) Javier Valcarce. BSD License. ---------------------------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; package pkg_epp2fifo is component epp2fifo port ( n_reset : in std_logic; clk : in std_logic; -- EPP interface epp_data : inout std_logic_vector(7 downto 0); epp_astb : in std_logic; epp_dstb : in std_logic; epp_write : in std_logic; epp_wait : out std_logic; -- 2-fifo interface tx_rd : out std_logic; tx_empty : in std_logic; tx_data : in std_logic_vector(7 downto 0); -- rx_wr : out std_logic; rx_full : in std_logic; rx_data : out std_logic_vector(7 downto 0)); end component; end pkg_epp2fifo; package body pkg_epp2fifo is end pkg_epp2fifo; --------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; -- The state signals show state of the fifo. For example: in what 1/8th of capacity is -- the fifo's lenght. They are not used by this macro, only get them available for read -- in status register. -- The terms "tx" and "rx" are used from the point of view of FPGA entity epp2fifo is port ( n_reset : in std_logic; clk : in std_logic; -- EPP interface epp_data : inout std_logic_vector(7 downto 0); epp_astb : in std_logic; epp_dstb : in std_logic; epp_write : in std_logic; epp_wait : out std_logic; -- 2-fifo interface tx_rd : out std_logic; tx_empty : in std_logic; tx_data : in std_logic_vector(7 downto 0); -- rx_wr : out std_logic; rx_full : in std_logic; rx_data : out std_logic_vector(7 downto 0)); end epp2fifo; architecture epp2fifo_arch of epp2fifo is signal dir : std_logic; -- synchronized epp control signals signal sync_astb : std_logic := '1'; signal sync_dstb : std_logic := '1'; signal sync_write : std_logic := '1'; begin ------------------------------------------------------------------------------------------------ -- WARNING -- -- The data bus is bidirectional -- BE CAREFUL, only drive the bus when no other block drives it. If not, you could make a short- -- circuit and DAMAGE the output drivers (IOB) of the FPGA epp_data <= tx_data when sync_write = '1' and dir = '1' else (others => 'Z'); -- rx fifo rx_data <= epp_data; ------------------------------------------------------------------------------------------------ -- Sequencer (finite state machine) for the data path. The output signals are -- registered to avoid glitches (this is very important!) ctl1 : block type state_type is (Rdy0, A, Dwr1, Dwr2, Dwr3, Dwr4, Drd1, Drd2, Drd3, Drd4); -- state and next state signal state_q : state_type; signal state : state_type; -- outputs and next outputs signal op_q : std_logic_vector(3 downto 0); signal op : std_logic_vector(3 downto 0); begin -- State Register and Output Signals Register (must be glitch free) process (n_reset, clk) begin if n_reset = '0' then state_q <= Rdy0; op_q <= "0000"; sync_astb <= '1'; sync_dstb <= '1'; sync_write <= '1'; elsif rising_edge(clk) then state_q <= state; op_q <= op; -- sync control signals sync_astb <= epp_astb; sync_dstb <= epp_dstb; sync_write <= epp_write; end if; end process; -- Generation of registered next state process (state_q, sync_astb, sync_dstb, sync_write, tx_empty, rx_full) begin -- explicit transitions (else case), in other case, the synthetizer -- *inferres a latch* case state_q is when Rdy0 => if sync_astb = '0' then state <= A; elsif sync_dstb = '0' and sync_write = '0' then state <= Dwr1; elsif sync_dstb = '0' and sync_write = '1' then state <= Drd1; else state <= Rdy0; end if; when A => if sync_astb = '1' then state <= Rdy0; else state <= A; end if; when Dwr1 => state <= Dwr2; when Dwr2 => if rx_full = '0' then state <= Dwr3; else state <= Dwr2; end if; when Dwr3 => state <= Dwr4; when Dwr4 => if sync_dstb = '1' then state <= Rdy0; else state <= Dwr4; end if; when Drd1 => state <= Drd2; when Drd2 => if tx_empty = '0' then state <= Drd3; else state <= Drd2; end if; when Drd3 => state <= Drd4; when Drd4 => if sync_dstb = '1' then state <= Rdy0; else state <= Drd4; end if; end case; end process; -- Generation of registered output signals process (state) begin case state is when Rdy0 => op <= "0000"; when A => op <= "0001"; when Dwr1 => op <= "0000"; when Dwr2 => op <= "0000"; when Dwr3 => op <= "0100"; when Dwr4 => op <= "0001"; when Drd1 => op <= "0010"; when Drd2 => op <= "0010"; when Drd3 => op <= "1010"; when Drd4 => op <= "0011"; end case; end process; -- map control signals from the current state tx_rd <= op_q(3); rx_wr <= op_q(2); dir <= op_q(1); epp_wait <= op_q(0); end block; end epp2fifo_arch;