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

Subversion Repositories usb11_phy_translation

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /usb11_phy_translation
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/trunk/usb_tx_phy.vhdl
1,3 → 1,4
 
--======================================================================================--
-- Verilog to VHDL conversion by Martin Neumann martin@neumnns-mail.de --
-- --
45,397 → 46,346
-- +-------+-----------+-------+------------------------------------------------------+ --
-- | Vers. | Date | Autor | Comment | --
-- +-------+-----------+-------+------------------------------------------------------+ --
-- | 1.0 |04 Feb 2011| MN | Initial version | --
-- | 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;
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;
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;
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
DataOut_i : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
TxValid_i : IN STD_LOGIC;
TxReady_o : OUT STD_LOGIC
);
end usb_tx_phy;
END usb_tx_phy;
 
architecture RTL of usb_tx_phy is
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_eop_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 append_eop : std_logic;
signal append_eop_sync1 : std_logic;
signal append_eop_sync2 : std_logic;
signal append_eop_sync3 : std_logic;
signal append_eop_sync4 : std_logic;
signal data_done : std_logic;
signal eop_done : 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, next_state : std_logic_vector(2 downto 0);
signal stuff : std_logic;
signal tx_ip : std_logic;
signal tx_ip_sync : std_logic;
signal txoe_r1, txoe_r2 : std_logic;
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 := "000";
constant SOP_STATE : std_logic_vector := "001";
constant DATA_STATE : std_logic_vector := "010";
constant EOP1_STATE : std_logic_vector := "011";
constant EOP2_STATE : std_logic_vector := "100";
constant WAIT_STATE : std_logic_vector := "101";
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
BEGIN
 
--======================================================================================--
-- Misc Logic --
--======================================================================================--
 
p_TxReady_o: process (clk, rst)
begin
if rst ='0' then
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;
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
p_ld_data: PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
ld_data <= ld_data_d;
end if;
end process;
END IF;
END PROCESS;
 
--======================================================================================--
-- Transmit in progress indicator --
--======================================================================================--
 
p_tx_ip: process (clk, rst)
begin
if rst ='0' then
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
ELSIF rising_edge(clk) THEN
IF ld_sop_d ='1' THEN
tx_ip <= '1';
elsif eop_done ='1' then
ELSIF append_eop ='1' THEN
tx_ip <= '0';
end if;
end if;
end process;
END IF;
END IF;
END PROCESS;
 
p_tx_ip_sync: process (clk, rst)
begin
if rst ='0' then
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
ELSIF rising_edge(clk) THEN
IF fs_ce ='1' THEN
tx_ip_sync <= tx_ip;
end if;
end if;
end process;
END IF;
END IF;
END PROCESS;
 
-- data_done helps us to catch cases where TxValid drops due to
-- packet end and then gets re-asserted as a new packet starts.
-- 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_done should solve those cases ...
p_data_done: process (clk, rst)
begin
if rst ='0' then
data_done <= '0';
elsif rising_edge(clk) then
if TxValid_i ='1' and tx_ip ='0' then
data_done <= '1';
elsif TxValid_i = '0' then
data_done <= '0';
end if;
end if;
end process;
-- 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
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
ELSIF rising_edge(clk) THEN
IF tx_ip_sync ='0' THEN
bit_cnt <= "000";
elsif fs_ce ='1' and stuff ='0' then
ELSIF fs_ce ='1' AND stuff ='0' THEN
bit_cnt <= bit_cnt + 1;
end if;
end if;
end process;
END IF;
END IF;
END PROCESS;
 
p_sd_raw_o: process (clk)
begin
if rising_edge(clk) then
if tx_ip_sync ='0' then
p_sd_raw_o: PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF tx_ip_sync ='0' THEN
sd_raw_o <= '0';
else
ELSE
sd_raw_o <= hold_reg_d(CONV_INTEGER(UNSIGNED(bit_cnt)));
end if;
end if;
end process;
END IF;
END IF;
END PROCESS;
 
p_sft_done: process (clk)
begin
if rising_edge(clk) then
if bit_cnt = "111" then
sft_done <= not stuff;
else
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;
end if;
end process;
END IF;
sft_done_r <= sft_done;
END IF;
END PROCESS;
 
p_sft_done_r: process (clk)
begin
if rising_edge(clk) then
sft_done_r <= sft_done;
end if;
end process;
sft_done_e <= sft_done AND NOT sft_done_r;
 
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
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
ELSIF rising_edge(clk) THEN
IF ld_sop_d ='1' THEN
hold_reg <= X"80";
elsif ld_data ='1' then
ELSIF ld_data ='1' THEN
hold_reg <= DataOut_i;
end if;
END IF;
hold_reg_d <= hold_reg;
end if;
end process;
END IF;
END PROCESS;
 
--======================================================================================--
-- Bit Stuffer --
--======================================================================================--
 
p_one_cnt: process (clk, rst)
begin
if rst ='0' then
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
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
ELSIF fs_ce ='1' THEN
IF sd_raw_o ='0' OR stuff = '1' THEN
one_cnt <= "000";
else
ELSE
one_cnt <= one_cnt + 1;
end if;
end if;
end if;
end process;
END IF;
END IF;
END IF;
END PROCESS;
 
stuff <= '1' when one_cnt = "110" else '0';
stuff <= '1' WHEN one_cnt = "110" ELSE '0';
 
p_sd_bs_o: process (clk, rst)
begin
if rst ='0' then
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
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
ELSE
IF stuff ='1' THEN
sd_bs_o <= '0';
else
ELSE
sd_bs_o <= sd_raw_o;
end if;
end if;
end if;
end if;
end process;
END IF;
END IF;
END IF;
END IF;
END PROCESS;
 
--======================================================================================--
-- NRZI Encoder --
--======================================================================================--
 
p_sd_nrzi_o: process (clk, rst)
begin
if rst ='0' then
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
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
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;
ELSE
sd_nrzi_o <= NOT sd_nrzi_o;
END IF;
END IF;
END IF;
END PROCESS;
 
--======================================================================================--
-- EOP append logic --
--======================================================================================--
 
p_append_eop: process (clk, rst)
begin
if rst ='0' then
append_eop <= '0';
elsif rising_edge(clk) then
if ld_eop_d ='1' then
append_eop <= '1';
elsif append_eop_sync2 ='1' then
append_eop <= '0';
end if;
end if;
end process;
 
p_append_eop_sync: process (clk, rst)
begin
if rst ='0' then
append_eop_sync1 <= '0';
append_eop_sync2 <= '0';
append_eop_sync3 <= '0';
append_eop_sync4 <= '0';
elsif rising_edge(clk) then
if fs_ce ='1' then
append_eop_sync1 <= append_eop;
append_eop_sync2 <= append_eop_sync1;
append_eop_sync3 <= append_eop_sync2 or -- Make sure always 2 bit wide
(append_eop_sync3 and not append_eop_sync4);
append_eop_sync4 <= append_eop_sync3;
end if;
end if;
end process;
 
eop_done <= append_eop_sync3;
 
--======================================================================================--
-- Output Enable Logic --
--======================================================================================--
 
p_txoe: process (clk, rst)
begin
if rst ='0' then
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
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;
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
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_sync3 and sd_nrzi_o;
txdn <= not append_eop_sync3 and not sd_nrzi_o;
else
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_sync3;
end if;
end if;
end if;
end process;
txdn <= append_eop;
END IF;
END IF;
END IF;
END PROCESS;
 
--======================================================================================--
-- Tx Statemashine --
--======================================================================================--
 
p_state: process (clk, rst)
begin
if rst ='0' then
any_eop_state <= state(3);
 
p_state: PROCESS (clk, rst)
BEGIN
IF rst ='0' THEN
state <= IDLE_STATE;
elsif rising_edge(clk) then
state <= next_state;
end if;
end process;
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;
 
p_next_state: process (rst, state, TxValid_i, data_done, sft_done_e, eop_done, fs_ce)
begin
if rst='0' then
next_state <= IDLE_STATE;
else
case (state) is
when IDLE_STATE => if TxValid_i ='1' then
next_state <= SOP_STATE;
ELSE
next_state <= IDLE_STATE;
end if;
when SOP_STATE => if sft_done_e ='1' then
next_state <= DATA_STATE;
ELSE
next_state <= SOP_STATE;
end if;
when DATA_STATE => if data_done ='0' and sft_done_e ='1' then
next_state <= EOP1_STATE;
ELSE
next_state <= DATA_STATE;
end if;
when EOP1_STATE => if eop_done ='1' then
next_state <= EOP2_STATE;
ELSE
next_state <= EOP1_STATE;
end if;
when EOP2_STATE => if eop_done ='0' and fs_ce ='1' then
next_state <= WAIT_STATE;
ELSE
next_state <= EOP2_STATE;
end if;
when WAIT_STATE => if fs_ce = '1' then
next_state <= IDLE_STATE;
ELSE
next_state <= WAIT_STATE;
end if;
when others => next_state <= IDLE_STATE;
end case;
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';
 
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_done ='1') else '0';
ld_eop_d <= sft_done_e when state = Data_STATE and data_done ='0' else '0';
END RTL;
 
end RTL;
 

powered by: WebSVN 2.1.0

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