OpenCores
URL https://opencores.org/ocsvn/usb11_phy_translation/usb11_phy_translation/trunk

Subversion Repositories usb11_phy_translation

[/] [usb11_phy_translation/] [trunk/] [usb_tx_phy.vhdl] - Rev 4

Compare with Previous | Blame | View Log

 
--======================================================================================--
--          Verilog to VHDL conversion by Martin Neumann martin@neumnns-mail.de         --
--                                                                                      --
--          ///////////////////////////////////////////////////////////////////         --
--          //                                                               //         --
--          //  USB 1.1 PHY                                                  //         --
--          //  TX                                                           //         --
--          //                                                               //         --
--          //                                                               //         --
--          //  Author: Rudolf Usselmann                                     //         --
--          //          rudi@asics.ws                                        //         --
--          //                                                               //         --
--          //                                                               //         --
--          //  Downloaded from: http://www.opencores.org/cores/usb_phy/     //         --
--          //                                                               //         --
--          ///////////////////////////////////////////////////////////////////         --
--          //                                                               //         --
--          //  Copyright (C) 2000-2002 Rudolf Usselmann                     //         --
--          //                          www.asics.ws                         //         --
--          //                          rudi@asics.ws                        //         --
--          //                                                               //         --
--          //  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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY      //         --
--          //  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED    //         --
--          //  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    //         --
--          //  FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR       //         --
--          //  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          //         --
--          //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES     //         --
--          //  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE    //         --
--          //  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR         //         --
--          //  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF   //         --
--          //  LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT   //         --
--          //  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT   //         --
--          //  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          //         --
--          //  POSSIBILITY OF SUCH DAMAGE.                                  //         --
--          //                                                               //         --
--          ///////////////////////////////////////////////////////////////////         --
--======================================================================================--
--                                                                                      --
-- Change history                                                                       --
-- +-------+-----------+-------+------------------------------------------------------+ --
-- | Vers. | Date      | Autor | Comment                                              | --
-- +-------+-----------+-------+------------------------------------------------------+ --
-- |  2.0  | 3 Jul 2016|  MN   | Changed eop logic due to USB spec violation          | --
-- |  1.1  |23 Apr 2011|  MN   | Added missing 'rst' in process sensitivity lists     | --
-- |       |           |       | Added ELSE constructs in next_state process to       | --
-- |       |           |       |   prevent an undesired latch implementation.         | --
-- |  1.0  |04 Feb 2011|  MN   | Initial version                                      | --
--======================================================================================--
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
 
ENTITY usb_tx_phy is
  PORT (
    clk              : IN  STD_LOGIC;
    rst              : IN  STD_LOGIC;
    fs_ce            : IN  STD_LOGIC;
    phy_mode         : IN  STD_LOGIC; -- HIGH level for differential IO mode (else single-ended)
    -- Transciever Interface
    txdp, txdn, txoe : OUT STD_LOGIC;
    -- UTMI Interface
    DataOut_i        : IN  STD_LOGIC_VECTOR(7 DOWNTO 0);
    TxValid_i        : IN  STD_LOGIC;
    TxReady_o        : OUT STD_LOGIC
  );
END usb_tx_phy;
 
ARCHITECTURE RTL of usb_tx_phy is
 
  SIGNAL hold_reg           : STD_LOGIC_VECTOR(7 DOWNTO 0);
  SIGNAL ld_data            : STD_LOGIC;
  SIGNAL ld_data_d          : STD_LOGIC;
  SIGNAL ld_sop_d           : STD_LOGIC;
  SIGNAL bit_cnt            : STD_LOGIC_VECTOR(2 DOWNTO 0);
  SIGNAL sft_done_e         : STD_LOGIC;
  SIGNAL any_eop_state      : STD_LOGIC;
  SIGNAL append_eop         : STD_LOGIC;
  SIGNAL data_xmit          : STD_LOGIC;
  SIGNAL hold_reg_d         : STD_LOGIC_VECTOR(7 DOWNTO 0);
  SIGNAL one_cnt            : STD_LOGIC_VECTOR(2 DOWNTO 0);
  SIGNAL sd_bs_o            : STD_LOGIC;
  SIGNAL sd_nrzi_o          : STD_LOGIC;
  SIGNAL sd_raw_o           : STD_LOGIC;
  SIGNAL sft_done           : STD_LOGIC;
  SIGNAL sft_done_r         : STD_LOGIC;
  SIGNAL state              : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL stuff              : STD_LOGIC;
  SIGNAL tx_ip              : STD_LOGIC;
  SIGNAL tx_ip_sync         : STD_LOGIC;
  SIGNAL txoe_r1, txoe_r2   : STD_LOGIC;
 
  CONSTANT IDLE_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";
  CONSTANT SOP_STATE        : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0001";
  CONSTANT DATA_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0010";
  CONSTANT WAIT_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0011";
  CONSTANT EOP0_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1000";
  CONSTANT EOP1_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1001";
  CONSTANT EOP2_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1010";
  CONSTANT EOP3_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1011";
  CONSTANT EOP4_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1100";
  CONSTANT EOP5_STATE       : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1101";
 
BEGIN
 
--======================================================================================--
  -- Misc Logic                                                                         --
--======================================================================================--
 
  p_TxReady_o: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      TxReady_o <= '0';
    ELSIF rising_edge(clk) THEN
      TxReady_o <= ld_data_d AND TxValid_i;
    END IF;
  END PROCESS;
 
  p_ld_data: PROCESS (clk)
  BEGIN
    IF rising_edge(clk) THEN
      ld_data <= ld_data_d;
    END IF;
  END PROCESS;
 
--======================================================================================--
  -- Transmit in progress indicator                                                     --
--======================================================================================--
 
  p_tx_ip: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      tx_ip <= '0';
    ELSIF rising_edge(clk) THEN
      IF ld_sop_d  ='1' THEN
        tx_ip <= '1';
      ELSIF append_eop ='1' THEN
        tx_ip <= '0';
      END IF;
    END IF;
  END PROCESS;
 
  p_tx_ip_sync: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      tx_ip_sync <= '0';
    ELSIF rising_edge(clk) THEN
      IF fs_ce ='1' THEN
        tx_ip_sync <= tx_ip;
      END IF;
    END IF;
  END PROCESS;
 
  -- data_xmit helps us to catch cases where TxValid drops due to
  -- packet END and then gets re-asserted as a new packet starts.
  -- We might not see this because we are still transmitting.
  -- data_xmit should solve those cases ...
  p_data_xmit: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      data_xmit <= '0';
    ELSIF rising_edge(clk) THEN
      IF TxValid_i ='1' AND tx_ip ='0' THEN
        data_xmit <= '1';
      ELSIF TxValid_i = '0' THEN
        data_xmit <= '0';
      END IF;
    END IF;
  END PROCESS;
 
--======================================================================================--
  -- Shift Register                                                                     --
--======================================================================================--
 
  p_bit_cnt: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      bit_cnt <= "000";
    ELSIF rising_edge(clk) THEN
      IF tx_ip_sync ='0' THEN
        bit_cnt <= "000";
      ELSIF fs_ce ='1' AND stuff ='0' THEN
        bit_cnt <= bit_cnt + 1;
      END IF;
    END IF;
  END PROCESS;
 
  p_sd_raw_o: PROCESS (clk)
  BEGIN
    IF rising_edge(clk) THEN
      IF tx_ip_sync ='0' THEN
        sd_raw_o <= '0';
      ELSE
        sd_raw_o <= hold_reg_d(CONV_INTEGER(UNSIGNED(bit_cnt)));
      END IF;
    END IF;
  END PROCESS;
 
  p_sft_done: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      sft_done   <= '0';
      sft_done_r <= '0';
    ELSIF rising_edge(clk) THEN
      IF bit_cnt = "111" THEN
        sft_done <= NOT stuff;
      ELSE
        sft_done <= '0';
      END IF;
      sft_done_r <= sft_done;
    END IF;
  END PROCESS;
 
  sft_done_e <= sft_done AND NOT sft_done_r;
 
  -- Out Data Hold Register
  p_hold_reg: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
        hold_reg   <= X"00";
        hold_reg_d <= X"00";
    ELSIF rising_edge(clk) THEN
      IF ld_sop_d ='1' THEN
        hold_reg <= X"80";
      ELSIF ld_data ='1' THEN
        hold_reg <= DataOut_i;
      END IF;
      hold_reg_d <= hold_reg;
    END IF;
  END PROCESS;
 
--======================================================================================--
  -- Bit Stuffer                                                                        --
--======================================================================================--
 
  p_one_cnt: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      one_cnt <= "000";
    ELSIF rising_edge(clk) THEN
      IF tx_ip_sync ='0' THEN
        one_cnt <= "000";
      ELSIF fs_ce ='1' THEN
        IF sd_raw_o ='0' OR stuff = '1' THEN
          one_cnt <= "000";
        ELSE
          one_cnt <= one_cnt + 1;
        END IF;
      END IF;
    END IF;
  END PROCESS;
 
  stuff   <= '1' WHEN one_cnt = "110" ELSE '0';
 
  p_sd_bs_o: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      sd_bs_o <= '0';
    ELSIF rising_edge(clk) THEN
      IF fs_ce ='1' THEN
        IF tx_ip_sync ='0' THEN
          sd_bs_o <= '0';
        ELSE
          IF stuff ='1' THEN
            sd_bs_o <= '0';
          ELSE
            sd_bs_o <= sd_raw_o;
          END IF;
        END IF;
      END IF;
    END IF;
  END PROCESS;
 
--======================================================================================--
  -- NRZI Encoder                                                                       --
--======================================================================================--
 
  p_sd_nrzi_o: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      sd_nrzi_o <= '1';
    ELSIF rising_edge(clk) THEN
      IF tx_ip_sync ='0' OR txoe_r1 ='0' THEN
        sd_nrzi_o <= '1';
      ELSIF fs_ce ='1' THEN
        IF sd_bs_o ='1' THEN
          sd_nrzi_o <= sd_nrzi_o;
        ELSE
          sd_nrzi_o <= NOT sd_nrzi_o;
        END IF;
      END IF;
    END IF;
  END PROCESS;
 
--======================================================================================--
  -- Output Enable Logic                                                                --
--======================================================================================--
 
  p_txoe: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      txoe_r1 <= '0';
      txoe_r2 <= '0';
      txoe    <= '1';
    ELSIF rising_edge(clk) THEN
      IF fs_ce ='1' THEN
        txoe_r1 <= tx_ip_sync;
        txoe_r2 <= txoe_r1;
        txoe    <= NOT (txoe_r1 OR txoe_r2);
      END IF;
    END IF;
  END PROCESS;
 
--======================================================================================--
  -- Output Registers                                                                   --
--======================================================================================--
 
  p_txdpn: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      txdp <= '1';
      txdn <= '0';
    ELSIF rising_edge(clk) THEN
      IF fs_ce ='1' THEN
        IF phy_mode ='1' THEN
          txdp <= NOT append_eop AND     sd_nrzi_o;
          txdn <= NOT append_eop AND NOT sd_nrzi_o;
        ELSE
          txdp <= sd_nrzi_o;
          txdn <= append_eop;
        END IF;
      END IF;
    END IF;
  END PROCESS;
 
--======================================================================================--
  -- Tx Statemashine                                                                    --
--======================================================================================--
 
  any_eop_state <= state(3);
 
  p_state: PROCESS (clk, rst)
  BEGIN
    IF rst ='0' THEN
      state <= IDLE_STATE;
    ELSIF rising_edge(clk) THEN
      IF any_eop_state = '0' THEN
        CASE (state) IS
          WHEN IDLE_STATE => IF TxValid_i ='1' THEN
                               state <= SOP_STATE;
                             END IF;
          WHEN SOP_STATE  => IF sft_done_e ='1' THEN
                               state <= DATA_STATE;
                             END IF;
          WHEN DATA_STATE => IF data_xmit ='0' AND sft_done_e ='1' THEN
                               IF one_cnt = "101" AND hold_reg_d(7) = '1' THEN
                                 state <= EOP0_STATE;
                               ELSE
                                 state <= EOP1_STATE;
                               END IF;
                             END IF;
          WHEN WAIT_STATE => IF fs_ce = '1' THEN
                               state <= IDLE_STATE;
                             END IF;
          WHEN OTHERS => state <= IDLE_STATE;
        END CASE;
      ELSE
        IF fs_ce ='1' THEN
          IF state = EOP5_state THEN
            state <= WAIT_STATE;
          ELSE
            state <= unsigned(state) + 1;
          END IF;
        END IF;
      END IF;
    END IF;
  END PROCESS;
 
  append_eop <= '1' WHEN state(3 DOWNTO 2) = "11" ELSE '0';  -- EOP4_STATE OR EOP5_STATE
  ld_sop_d   <= TxValid_i  WHEN state = IDLE_STATE ELSE '0';
  ld_data_d  <= sft_done_e WHEN state = SOP_STATE OR (state = DATA_STATE AND data_xmit ='1') ELSE '0';
 
END RTL;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.