]> git.the-white-hart.net Git - vhdl/commitdiff
Add USB mux to support STM and EPP together
authorrs <>
Tue, 11 Nov 2025 21:48:15 +0000 (15:48 -0600)
committerrs <>
Tue, 11 Nov 2025 21:48:15 +0000 (15:48 -0600)
libraries/nexys2/eppex_wb.vhd [new file with mode: 0644]
libraries/nexys2/tests/nexys2_usb.vhd [new file with mode: 0644]
libraries/nexys2/tests/program.sh
libraries/nexys2/usb.vhd [new file with mode: 0644]
libraries/nexys2/usb_mux.vhd [new file with mode: 0644]

diff --git a/libraries/nexys2/eppex_wb.vhd b/libraries/nexys2/eppex_wb.vhd
new file mode 100644 (file)
index 0000000..f8a5d9d
--- /dev/null
@@ -0,0 +1,211 @@
+--------------------------------------------------------------------------------
+-- epp_wb - Digilent EPP to Wishbone bridge
+--
+-- Connects to a Digilent EPP bus (one of Digilent's USB interface methods) and
+-- converts EPP transactions into Wishbone bus transactions.
+--------------------------------------------------------------------------------
+-- WISHBONE DATASHEET
+--
+-- Wishbone specification used: Rev B.3
+-- Interface type: master
+-- Port size: 8-bit
+-- Operand sizes: 8-bit
+-- Endianness: undefined (port size same as granularity)
+-- Data transfer sequence: undefined
+-- Clock constraints: none
+-- Signals:
+-- * rst_i
+-- * clk_i
+-- * cyc_o
+-- * stb_o
+-- * we_o
+-- * ack_i
+-- * adr_o (8-bit)
+-- * dat_i (8-bit)
+-- * dat_o (8-bit)
+--------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+
+entity eppex_wb is
+       port (
+               -- Epp-bus signals
+               -- Assumed to be externally-registered, prefereably by clock domain crossing from DstmIFCLK to clk_50
+               EppEN:   in  std_logic;
+               EppAstb: in  std_logic;
+               EppDstb: in  std_logic;
+               EppWr:   in  std_logic;
+               EppDB_i: in  std_logic_vector(7 downto 0);
+               EppDB_o: out std_logic_vector(7 downto 0);
+               EppDB_w: out std_logic; -- '1' when EppDB_o should be put on the bus
+               EppWait: out std_logic;
+
+               -- Wishbone bus signals
+               rst_i:   in  std_logic;
+               clk_i:   in  std_logic;
+               cyc_o:   out std_logic;
+               stb_o:   out std_logic;
+               we_o:    out std_logic;
+               ack_i:   in  std_logic;
+               adr_o:   out std_logic_vector(7 downto 0);
+               dat_i:   in  std_logic_vector(7 downto 0);
+               dat_o:   out std_logic_vector(7 downto 0)
+       );
+end eppex_wb;
+
+
+architecture behavioral of eppex_wb is
+
+       type state_t is (
+               S_READY,
+               S_ADDR,
+               S_DATA,
+               S_DONE
+       );
+
+       -- Registered epp bus signals
+       signal epp_data_out_reg:   std_logic_vector(7 downto 0);
+
+       signal epp_data_out_latch: std_logic;
+       signal epp_data_out_en:    std_logic;
+
+       -- Internal address register
+       signal addr_latch: std_logic;
+       signal addr_reg: std_logic_vector(7 downto 0);
+
+       -- Registered wishbone bus signals
+       signal next_stb: std_logic;
+       signal stb_reg:  std_logic;
+       signal next_we:  std_logic;
+       signal we_reg:   std_logic;
+
+       -- State machine
+       signal cur_state_reg: state_t;
+       signal next_state: state_t;
+
+begin
+
+       -- Interface output should be in tristate until data is available for EPP to read
+       --EppDB <= epp_data_out_reg when epp_data_out_en = '1' else (others => 'Z');
+       EppDB_o <= epp_data_out_reg;
+       EppDB_w <= epp_data_out_en;
+
+       -- Output registered wishbone signals
+       cyc_o <= stb_reg;
+       stb_o <= stb_reg;
+       we_o  <= we_reg;
+
+       -- Always present the latched EPP data bus and latched address to the wishbone bus
+       dat_o <= EppDB_i;  -- epp_data_in_reg;
+       adr_o <= addr_reg;
+
+       -- State register
+       p_regs: process (clk_i, rst_i, next_state, EppEN)
+       begin
+               if rising_edge(clk_i) then
+                       if rst_i = '1' or EppEN = '0' then
+                               cur_state_reg <= S_READY;
+                       else
+                               cur_state_reg <= next_state;
+                       end if;
+               end if;
+       end process;
+
+       -- Register wishbone outputs
+       p_wb_reg: process (clk_i, rst_i, next_stb, next_we)
+       begin
+               if rising_edge(clk_i) then
+                       if rst_i = '1' then
+                               stb_reg <= '0';
+                               we_reg  <= '0';
+                       else
+                               stb_reg <= next_stb;
+                               we_reg  <= next_we;
+                       end if;
+               end if;
+       end process;
+
+       -- Address register
+       p_addr: process (clk_i, addr_latch, EppDB_i)
+       begin
+               if rising_edge(clk_i) and addr_latch = '1' then
+                       addr_reg <= EppDB_i;
+               end if;
+       end process;
+
+       -- Data register from wishbone bus to epp bus
+       p_data: process (clk_i, epp_data_out_latch, dat_i)
+       begin
+               if rising_edge(clk_i) and epp_data_out_latch = '1' then
+                       epp_data_out_reg <= dat_i;
+               end if;
+       end process;
+
+       -- State machine transitions
+       p_fsm: process(cur_state_reg,
+                      EppEN, EppAstb, EppDstb, EppWR,
+                      ack_i)
+       begin
+               -- Default to remaining in same state
+               next_state <= cur_state_reg;
+
+               -- Default to not starting a wishbone cycle
+               next_stb <= '0';
+               next_we  <= '0';
+
+               -- Default to not latching or outputting anything
+               addr_latch <= '0';
+               epp_data_out_latch <= '0';
+               epp_data_out_en <= '0';
+
+               -- Default to telling EPP-side to wait
+               EppWait <= '0';
+
+               case cur_state_reg is
+                       when S_READY =>
+                               -- Leave state when a strobe is asserted
+                               -- Check EppEN as well to prevent false strobes
+                               if EppAstb = '0' and EppEN = '1' then
+                                       next_state <= S_ADDR;
+                               elsif EppDstb = '0' and EppEN = '1' then
+                                       next_stb <= '1';
+                                       next_we <= not EppWR;
+                                       next_state <= S_DATA;
+                               end if;
+
+                       when S_DATA =>
+                               -- Ack may be combinational, so don't register it
+                               if ack_i = '1' then
+                                       -- Latch data from wishbone, as EPP may take more time to read
+                                       epp_data_out_latch <= '1';
+                                       next_state <= S_DONE;
+                               else
+                                       -- Continue asserting bus signals next cycle if not acknowledged
+                                       next_stb <= '1';
+                                       next_we <= not EppWR;
+                               end if;
+
+                       when S_ADDR =>
+                               addr_latch <= '1';
+                               next_state <= S_DONE;  -- No stretcing will occur for address access
+
+                       when S_DONE =>
+                               -- Indicate completion
+                               EppWait <= '1';
+
+                               -- If a read is being performed, take the EPP bus out of tristate
+                               epp_data_out_en <= EppWR;
+
+                               -- Wait for strobes to be deasserted before returning to READY state
+                               if EppAstb = '1' and EppDstb = '1' then
+                                       next_state <= S_READY;
+                               end if;
+
+                       when others =>
+                               next_state <= S_READY;
+               end case;
+       end process;
+
+end behavioral;
diff --git a/libraries/nexys2/tests/nexys2_usb.vhd b/libraries/nexys2/tests/nexys2_usb.vhd
new file mode 100644 (file)
index 0000000..2d1c22c
--- /dev/null
@@ -0,0 +1,125 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+
+
+entity nexys2_usb is
+       port (
+               clk_50:            in    std_logic;
+
+               EppDB_DstmDB:      inout std_logic_vector(7 downto 0);
+               EppWRITE:          in    std_logic;
+               EppASTB_DstmFLAGA: in    std_logic;
+               EppDSTB_DstmFLAGB: in    std_logic;
+               EppWAIT_DstmSLRD:  out   std_logic;
+               DstmIFCLK:         in    std_logic;
+               DstmSLCS:          in    std_logic;
+               DstmADR:           out   std_logic_vector(1 downto 0);
+               DstmSLWR:          out   std_logic;
+               DstmSLOE:          out   std_logic;
+               DstmPKTEND:        out   std_logic;
+               UsbMode:           in    std_logic;
+               UsbRdy:            in    std_logic;
+
+               seg:               out   std_logic_vector(6 downto 0);
+               dp:                out   std_logic;
+               an:                out   std_logic_vector(3 downto 0);
+               Led:               out   std_logic_vector(7 downto 0);
+               sw:                in    std_logic_vector(7 downto 0)
+       );
+end nexys2_usb;
+
+
+architecture behavioral of nexys2_usb is
+
+       signal rst:     std_logic;
+
+       signal wb_cyc:  std_logic;
+       signal wb_stb:  std_logic;
+       signal wb_we:   std_logic;
+       signal wb_ack:  std_logic;
+       signal wb_adr:  std_logic_vector(7 downto 0);
+       signal wb_miso: std_logic_vector(7 downto 0);
+       signal wb_mosi: std_logic_vector(7 downto 0);
+
+       signal stm_stb: std_logic;
+       signal stm_ack: std_logic;
+       signal stm_dat: std_logic_vector(7 downto 0);
+
+begin
+
+       e_por: entity utility.power_on_reset_opt
+               port map (
+                       clk_i => clk_50,
+                       rst_o => rst
+               );
+
+       e_usb: entity work.usb_cypress
+               port map (
+                       EppDB_DstmDB      => EppDB_DstmDB,
+                       EppWRITE          => EppWRITE,
+                       EppASTB_DstmFLAGA => EppASTB_DstmFLAGA,
+                       EppDSTB_DstmFLAGB => EppDSTB_DstmFLAGB,
+                       EppWAIT_DstmSLRD  => EppWAIT_DstmSLRD,
+                       DstmIFCLK         => DstmIFCLK,
+                       DstmSLCS          => DstmSLCS,
+                       DstmADR           => DstmADR,
+                       DstmSLWR          => DstmSLWR,
+                       DstmSLOE          => DstmSLOE,
+                       DstmPKTEND        => DstmPKTEND,
+                       UsbMode           => UsbMode,
+                       UsbRdy            => UsbRdy,
+
+                       epp_rst_i         => rst,
+                       epp_clk_i         => clk_50,
+                       epp_cyc_o         => wb_cyc,
+                       epp_stb_o         => wb_stb,
+                       epp_we_o          => wb_we,
+                       epp_ack_i         => wb_ack,
+                       epp_adr_o         => wb_adr,
+                       epp_dat_i         => wb_miso,
+                       epp_dat_o         => wb_mosi,
+
+                       stm_rst_i         => rst,
+                       stm_clk_i         => clk_50,
+                       stm_dl_stb_o      => stm_stb,
+                       stm_dl_ack_i      => stm_ack,
+                       stm_dl_dat_o      => stm_dat,
+                       stm_ul_stb_i      => stm_stb,
+                       stm_ul_ack_o      => stm_ack,
+                       stm_ul_dat_i      => stm_dat
+               );
+
+       e_regs: entity work.host_regs_opt
+               port map (
+                       rst_i   => rst,
+                       clk_i   => clk_50,
+
+                       h_cyc_i => wb_cyc,
+                       h_stb_i => wb_stb,
+                       h_we_i  => wb_we,
+                       h_ack_o => wb_ack,
+                       h_adr_i => wb_adr(2 downto 0),
+                       h_dat_i => wb_mosi,
+                       h_dat_o => wb_miso,
+
+                       d_cyc_i => '0',
+                       d_stb_i => '0',
+                       d_we_i  => '0',
+                       d_ack_o => open,
+                       d_adr_i => "000",
+                       d_dat_i => x"00",
+                       d_dat_o => open,
+
+                       ctrl    => open,
+                       flags   => open,
+                       seg     => seg,
+                       dp      => dp,
+                       an      => an,
+                       Led     => Led,
+                       sw      => sw
+               );
+
+end behavioral;
index 6d2fed46a8f7b94493da32d9a9925b094c2a7cdc..e185d2a4c6e1c95a35ece9107e7f6a481738a989 100755 (executable)
@@ -1,4 +1,7 @@
 #!/usr/bin/env bash
 
-djtgcfg -d Nexys2 -i 0 -f test_nexys2_mem_wb8_0.bit prog
+#djtgcfg -d Nexys2 -i 0 -f test_nexys2_mem_wb8_0.bit prog
+#djtgcfg -d Nexys2 -i 0 -f StreamIOvhd.bit prog
+#djtgcfg -d Nexys2 -i 0 -f nexys2_stm.bit prog
+djtgcfg -d Nexys2 -i 0 -f nexys2_usb.bit prog
 
diff --git a/libraries/nexys2/usb.vhd b/libraries/nexys2/usb.vhd
new file mode 100644 (file)
index 0000000..5ae0966
--- /dev/null
@@ -0,0 +1,258 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+library utility;
+
+library work;
+
+
+entity usb_cypress is
+       port (
+               -- Nexys2 pins
+               EppDB_DstmDB:      inout std_logic_vector(7 downto 0);
+               EppWRITE:          in    std_logic;
+               EppASTB_DstmFLAGA: in    std_logic;
+               EppDSTB_DstmFLAGB: in    std_logic;
+               EppWAIT_DstmSLRD:  out   std_logic;
+               DstmIFCLK:         in    std_logic;
+               DstmSLCS:          in    std_logic;
+               DstmADR:           out   std_logic_vector(1 downto 0);
+               DstmSLWR:          out   std_logic;
+               DstmSLOE:          out   std_logic;
+               DstmPKTEND:        out   std_logic;
+               UsbMode:           in    std_logic;
+               UsbRdy:            in    std_logic;
+
+               -- EPP-Wishbone interface
+               epp_rst_i:         in    std_logic;
+               epp_clk_i:         in    std_logic;
+
+               epp_cyc_o:         out   std_logic;
+               epp_stb_o:         out   std_logic;
+               epp_we_o:          out   std_logic;
+               epp_ack_i:         in    std_logic;
+               epp_adr_o:         out   std_logic_vector(7 downto 0);
+               epp_dat_i:         in    std_logic_vector(7 downto 0);
+               epp_dat_o:         out   std_logic_vector(7 downto 0);
+
+               -- STM-Pipeline interfaces
+               stm_rst_i:         in    std_logic;
+               stm_clk_i:         in    std_logic;
+
+               stm_dl_stb_o:      out   std_logic;
+               stm_dl_ack_i:      in    std_logic;
+               stm_dl_dat_o:      out   std_logic_vector(7 downto 0);
+
+               stm_ul_stb_i:      in    std_logic;
+               stm_ul_ack_o:      out   std_logic;
+               stm_ul_dat_i:      in    std_logic_vector(7 downto 0)
+       );
+end usb_cypress;
+
+
+architecture behavioral of usb_cypress is
+
+       -- Between USB mux and EPP interface, in DstmIFCLK domain
+       signal epp_en:      std_logic;
+       signal epp_astb:    std_logic;
+       signal epp_dstb:    std_logic;
+       signal epp_write:   std_logic;
+       signal epp_db_i:    std_logic_vector(7 downto 0);
+       signal epp_db_o:    std_logic_vector(7 downto 0);
+       signal epp_db_w:    std_logic;
+       signal epp_wait:    std_logic;
+
+       -- Between USB mux and EPP interface, in epp_clk_i domain
+       signal xclk_eppen:  std_logic;
+       signal xclk_astb:   std_logic;
+       signal xclk_dstb:   std_logic;
+       signal xclk_write:  std_logic;
+       signal xclk_db_i:   std_logic_vector(7 downto 0);
+       signal xclk_db_o:   std_logic_vector(7 downto 0);
+       signal xclk_db_w:   std_logic;
+       signal xclk_wait:   std_logic;
+
+       -- Between USB mux and STM interface
+       signal dstm_ifclk:  std_logic;
+       signal dstm_slcs:   std_logic;
+       signal dstm_flaga:  std_logic;
+       signal dstm_flagb:  std_logic;
+       signal dstm_adr:    std_logic_vector(1 downto 0);
+       signal dstm_slrd:   std_logic;
+       signal dstm_slwr:   std_logic;
+       signal dstm_sloe:   std_logic;
+       signal dstm_pktend: std_logic;
+       signal dstm_db_i:   std_logic_vector(7 downto 0);
+       signal dstm_db_o:   std_logic_vector(7 downto 0);
+
+       -- Between STM interface and FIFOs
+       signal dl_stb:      std_logic;
+       signal dl_rdy:      std_logic;
+       signal dl_dat:      std_logic_vector(7 downto 0);
+       signal dl_end:      std_logic;
+
+       signal ul_stb:      std_logic;
+       signal ul_ack:      std_logic;
+       signal ul_dat:      std_logic_vector(7 downto 0);
+       signal ul_end:      std_logic;
+
+begin
+
+       ------------------------------------------------------------------------
+       -- Sharing single USB controller interface between EPP and STM
+
+       e_mux: entity work.usb_mux
+               port map (
+                       EppDB_DstmDB       => EppDB_DstmDB,
+                       EppWRITE           => EppWRITE,
+                       EppASTB_DstmFLAGA  => EppASTB_DstmFLAGA,
+                       EppDSTB_DstmFLAGB  => EppDSTB_DstmFLAGB,
+                       EppWAIT_DstmSLRD   => EppWAIT_DstmSLRD,
+                       DstmIFCLK          => DstmIFCLK,
+                       DstmSLCS           => DstmSLCS,
+                       DstmADR            => DstmADR,
+                       DstmSLWR           => DstmSLWR,
+                       DstmSLOE           => DstmSLOE,
+                       DstmPKTEND         => DstmPKTEND,
+                       UsbMode            => UsbMode,
+                       UsbRdy             => UsbRdy,
+
+                       s0_EppEN           => epp_en,
+                       s0_EppASTB         => epp_astb,
+                       s0_EppDSTB         => epp_dstb,
+                       s0_EppWRITE        => epp_write,
+                       s0_EppDB_i         => epp_db_i,
+                       s0_EppDB_o         => epp_db_o,
+                       s0_EppDB_w         => epp_db_w,
+                       s0_EppWAIT         => epp_wait,
+
+                       s1_DstmIFCLK       => dstm_ifclk,
+                       s1_DstmSLCS        => dstm_slcs,
+                       s1_DstmFLAGA       => dstm_flaga,
+                       s1_DstmFLAGB       => dstm_flagb,
+                       s1_DstmADR         => dstm_adr,
+                       s1_DstmSLRD        => dstm_slrd,
+                       s1_DstmSLWR        => dstm_slwr,
+                       s1_DstmSLOE        => dstm_sloe,
+                       s1_DstmPKTEND      => dstm_pktend,
+                       s1_DstmDB_i        => dstm_db_i,
+                       s1_DstmDB_o        => dstm_db_o
+               );
+
+       ------------------------------------------------------------------------
+       -- EPP Interface
+
+       -- EPP clock domain crossing
+       -- Both ends are handshaken, but this end has fewer signals to cross
+       -- FIXME: it should only be necessary to synchronize the handshaking signals
+       e_xclk_eppen: entity utility.xclk_sig
+               generic map (INIT => '0')
+               port map (a_sig_i => epp_en,    b_clk_i => epp_clk_i, b_sig_o => xclk_eppen);
+
+       e_xclk_astb: entity utility.xclk_sig
+               generic map (INIT => '1')
+               port map (a_sig_i => epp_astb,  b_clk_i => epp_clk_i, b_sig_o => xclk_astb);
+
+       e_xclk_dstb: entity utility.xclk_sig
+               generic map (INIT => '1')
+               port map (a_sig_i => epp_dstb,  b_clk_i => epp_clk_i, b_sig_o => xclk_dstb);
+
+       e_xclk_write: entity utility.xclk_sig
+               generic map (INIT => '1')
+               port map (a_sig_i => epp_write, b_clk_i => epp_clk_i, b_sig_o => xclk_write);
+
+       e_xclk_db_i: entity utility.xclk_vec
+               port map (a_sig_i => epp_db_i,  b_clk_i => epp_clk_i, b_sig_o => xclk_db_i);
+
+       e_xclk_db_o: entity utility.xclk_vec
+               port map (a_sig_i => xclk_db_o, b_clk_i => DstmIFCLK, b_sig_o => epp_db_o);
+
+       e_xclk_db_w: entity utility.xclk_sig
+               generic map (INIT => '0')
+               port map (a_sig_i => xclk_db_w, b_clk_i => DstmIFCLK, b_sig_o => epp_db_w);
+
+       e_xclk_wait: entity utility.xclk_sig
+               generic map (INIT => '0')  -- FIXME: is this the best initial value for WAIT?
+               port map (a_sig_i => xclk_wait, b_clk_i => DstmIFCLK, b_sig_o => epp_wait);
+
+       -- EPP interface logic
+       e_epp: entity work.eppex_wb
+               port map (
+                       EppEN   => xclk_eppen,
+                       EppAstb => xclk_astb,
+                       EppDstb => xclk_dstb,
+                       EppWr   => xclk_write,
+                       EppDB_i => xclk_db_i,
+                       EppDB_o => xclk_db_o,
+                       EppDB_w => xclk_db_w,
+                       EppWait => xclk_wait,
+
+                       rst_i   => epp_rst_i,
+                       clk_i   => epp_clk_i,
+                       cyc_o   => epp_cyc_o,
+                       stb_o   => epp_stb_o,
+                       we_o    => epp_we_o,
+                       ack_i   => epp_ack_i,
+                       adr_o   => epp_adr_o,
+                       dat_i   => epp_dat_i,
+                       dat_o   => epp_dat_o
+               );
+
+       ------------------------------------------------------------------------
+       -- STM Interface
+
+       -- STM interface logic
+       e_stm: entity work.stmex_wb
+               port map (
+                       ifclk    => dstm_ifclk,
+                       stmen    => dstm_slcs,
+                       db_i     => dstm_db_i,
+                       db_o     => dstm_db_o,
+                       flaga    => dstm_flaga,
+                       flagb    => dstm_flagb,
+                       fifoadr  => dstm_adr,
+                       slrd     => dstm_slrd,
+                       slwr     => dstm_slwr,
+                       sloe     => dstm_sloe,
+                       pktend   => dstm_pktend,
+
+                       dl_stb_o => dl_stb,
+                       dl_rdy_i => dl_rdy,
+                       dl_dat_o => dl_dat,
+                       dl_end_o => dl_end,
+
+                       ul_stb_i => ul_stb,
+                       ul_ack_o => ul_ack,
+                       ul_dat_i => ul_dat,
+                       ul_end_i => ul_end
+               );
+
+       -- STM clock domain crossing, download side
+       e_dl_fifo: entity utility.fifo_xclk
+               port map (
+                       head_clk_i => dstm_ifclk,
+                       head_stb_i => dl_stb,
+                       head_rdy_o => dl_rdy,
+                       head_dat_i => dl_dat,
+
+                       tail_clk_i => stm_clk_i,
+                       tail_stb_o => stm_dl_stb_o,
+                       tail_ack_i => stm_dl_ack_i,
+                       tail_dat_o => stm_dl_dat_o
+               );
+
+       -- STM clock domain crossing, upload side
+       e_ul_fifo: entity utility.fifo_xclk
+               port map (
+                       head_clk_i => stm_clk_i,
+                       head_stb_i => stm_ul_stb_i,
+                       head_rdy_o => stm_ul_ack_o,
+                       head_dat_i => stm_ul_dat_i,
+
+                       tail_clk_i => dstm_ifclk,
+                       tail_stb_o => ul_stb,
+                       tail_ack_i => ul_ack,
+                       tail_dat_o => ul_dat
+               );
+
+end behavioral;
diff --git a/libraries/nexys2/usb_mux.vhd b/libraries/nexys2/usb_mux.vhd
new file mode 100644 (file)
index 0000000..909a248
--- /dev/null
@@ -0,0 +1,80 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+
+entity usb_mux is
+       port (
+               -- Nexys2 pins
+               EppDB_DstmDB:      inout std_logic_vector(7 downto 0);
+               EppWRITE:          in    std_logic;
+               EppASTB_DstmFLAGA: in    std_logic;
+               EppDSTB_DstmFLAGB: in    std_logic;
+               EppWAIT_DstmSLRD:  out   std_logic;
+               DstmIFCLK:         in    std_logic;
+               DstmSLCS:          in    std_logic;
+               DstmADR:           out   std_logic_vector(1 downto 0);
+               DstmSLWR:          out   std_logic;
+               DstmSLOE:          out   std_logic;
+               DstmPKTEND:        out   std_logic;
+               UsbMode:           in    std_logic;
+               UsbRdy:            in    std_logic;
+
+               -- EPP interface (sel_i = '0')
+               s0_EppEN:          out   std_logic;
+               s0_EppASTB:        out   std_logic;
+               s0_EppDSTB:        out   std_logic;
+               s0_EppWRITE:       out   std_logic;
+               s0_EppDB_i:        out   std_logic_vector(7 downto 0);  -- Inbound: from host to device
+               s0_EppDB_o:        in    std_logic_vector(7 downto 0);  -- Outbound: from device to host
+               s0_EppDB_w:        in    std_logic;  -- '1' when EppDB_o should be on the 
+               s0_EppWAIT:        in    std_logic;
+
+               -- STM interface (sel_i = '1')
+               s1_DstmIFCLK:      out   std_logic;
+               s1_DstmSLCS:       out   std_logic;
+               s1_DstmFLAGA:      out   std_logic;
+               s1_DstmFLAGB:      out   std_logic;
+               s1_DstmADR:        in    std_logic_vector(1 downto 0);
+               s1_DstmSLRD:       in    std_logic;
+               s1_DstmSLWR:       in    std_logic;
+               s1_DstmSLOE:       in    std_logic;
+               s1_DstmPKTEND:     in    std_logic;
+               s1_DstmDB_i:       out   std_logic_vector(7 downto 0);
+               s1_DstmDB_o:       in    std_logic_vector(7 downto 0)
+       );
+end usb_mux;
+
+
+architecture behavioral of usb_mux is
+
+       signal DB_o: std_logic_vector(7 downto 0);
+       signal DB_w: std_logic;
+
+begin
+
+       -- Outputs to Nexys2 board
+       DstmADR          <= s1_DstmADR    when UsbRdy = '1' else (others => 'Z');
+       DstmSLWR         <= s1_DstmSLWR   when UsbRdy = '1' else 'Z';
+       DstmSLOE         <= s1_DstmSLOE   when UsbRdy = '1' else 'Z';
+       DstmPKTEND       <= s1_DstmPKTEND when UsbRdy = '1' else 'Z';
+       EppWAIT_DstmSLRD <= 'Z' when UsbRdy = '0' else s0_EppWAIT when DstmSLCS = '0' else s1_DstmSLRD;
+       DB_o             <= s0_EppDB_o when DstmSLCS = '0' else s1_DstmDB_o;
+       DB_w             <= s0_EppDB_w when DstmSLCS = '0' else s1_DstmSLOE;
+
+       EppDB_DstmDB <= (others => 'Z') when UsbRdy = '0' else DB_o when DB_w = '1' else (others => 'Z');
+
+       -- Outputs to EPP interface
+       s0_EppEN    <= UsbMode;
+       s0_EppASTB  <= EppASTB_DstmFLAGA;
+       s0_EppDSTB  <= EppDSTB_DstmFLAGB;
+       s0_EppWRITE <= EppWRITE;
+       s0_EppDB_i  <= EppDB_DstmDB;
+
+       -- Outputs to STM interface
+       s1_DstmIFCLK <= DstmIFCLK;
+       s1_DstmSLCS  <= DstmSLCS;
+       s1_DstmFLAGA <= EppASTB_DstmFLAGA;
+       s1_DstmFLAGB <= EppDSTB_DstmFLAGB;
+       s1_DstmDB_i  <= EppDB_DstmDB;
+
+end behavioral;