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; |
|