-- --------------------------------------------------------------------- -- ES5701 SuperGLU -- based on ES5701 datasheet and compared against ES5506 (OTTO) and ES5510 (ESP) datasheets -- --------------------------------------------------------------------- -- -- V1.0 2019-11-23 by Rainer Buchty, rainer@buchty.net -- syntax test only (ghdl -a) -- -- --------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity es5571 is port( -- general control rw, -- CPU read/write udben, -- upper data bus enable (cooked, must have CS# worked in) ldben, -- lower data bus enable (cooked, must have CS# worked in) clk20, -- 20MHz input clock clk16: in std_logic; -- 16MHz input clock clk10, -- 10MHz output clock clk8: out std_logic; -- 8MHz output clock -- CPU signals cpu_a: in std_logic_vector(7 downto 0); -- CPU address bus cpu_d: inout std_logic_vector(15 downto 0); -- CPU data bus -- ESP signals esp_cs: in std_logic; -- ESP chip select esp_dtack: out std_logic; -- ESP DTACK# esp_ad: inout std_logic_vector(7 downto 0); -- ESP multiplexed A/D bus -- OTIS/OTTO control (bus level) nyb: in std_logic; -- 12-bit nibble mode enable mode: in std_logic_vector(1 downto 0); -- sample resolution mode (8/12/13/16 bit) otis_dah, -- OTIS/OTTO upper data nibble (for nyb=0) otis_dal: in std_logic_vector(3 downto 0); -- OTIS/OTTO lower data nibble (for nyb=0) -- OTIS/OTTO signals otis_ras, -- OTIS/OTTO RAS# otis_cas, -- OTIS/OTTO CAS# otis_dbus: in std_logic; -- OTIS/OTTO data bus enable (E) otis_la: out std_logic_vector(19 downto 4); -- OTIS/OTTO latched address bus otis_da: inout std_logic_vector(19 downto 0) -- OTIS/OTTO multiplexed A/D bus ); end entity; architecture rtl of es5571 is signal lo_r, hi_r, -- lsb/msb read lo_w, hi_w: std_logic; -- lsb/msb write signal c20, c16: std_logic; -- clock divider signal otis_mask: std_logic_vector(7 downto 0); -- OTIS/OTTO data bus masking (8/12/13/16 bit mode) signal n_otis_la: std_logic_vector(19 downto 4); -- OTIS/OTTO address bus latch signal otis_nibble: std_logic_vector(3 downto 0); -- OTIS/OTTO upper/lower nibble mux (DAH/DAL) signal esp_q, esp_nq, -- RS latch for ESP bus control esp_en_a, esp_en_d: std_logic; -- ESP A/D bus enable begin -- --------------------------------------------------------------------- -- misc -- --------------------------------------------------------------------- -- bus access helpers (lo/hi read/write) lo_r <= '0' when ldben='0' and rw='1' else '1'; hi_r <= '0' when udben='0' and rw='1' else '1'; lo_w <= '0' when ldben='0' and rw='1' else '1'; hi_w <= '0' when udben='0' and rw='1' else '1'; -- clock divider 10MHz process(clk20) begin if falling_edge(clk20) then c20 <= not(c20); end if; end process; clk10 <= c20; -- clock divider 8MHz process(clk16) begin if falling_edge(clk16) then c16 <= not(c16); end if; end process; clk8 <= c16; -- --------------------------------------------------------------------- -- OTIS mode control -- --------------------------------------------------------------------- -- "tie M1 to GND, connect M0 to CS# for 8-bit sounds" (cf. page 4) -- --------------------------------------------------------------------- otis_mask <= "00000000" when mode="00" -- 8-bit mode else "11110000" when mode="01" -- 12-bit mode else "11111000" when mode="10" -- 13-bit mode else "11111111"; -- 16-bit mode -- --------------------------------------------------------------------- -- CPU data bus -- --------------------------------------------------------------------- cpu_d( 7 downto 0) <= esp_ad when lo_r='0' and esp_cs='0' -- ESP lower read else otis_da(11 downto 4) and otis_mask when lo_r='0' and otis_dbus='1' -- OTIS/OTTO lower read else (others => 'Z'); cpu_d(15 downto 8) <= esp_ad when hi_r='0' and esp_cs='0' -- ESP upper read else otis_da(19 downto 12) when hi_r='0' and otis_dbus='1' -- OTIS/OTTO upper read else (others => 'Z'); -- --------------------------------------------------------------------- -- OTIS/OTTO interface -- --------------------------------------------------------------------- -- LA: latched address to static memory -- cf. ES5506 datasheet, page 40 (74373) process(otis_ras) begin if falling_edge(otis_ras) then n_otis_la(19 downto 4) <= otis_da(19 downto 4); end if; end process; otis_la(19 downto 4) <= n_otis_la(19 downto 4) when otis_dbus='0' else (others => 'Z'); -- nibble mode otis_nibble <= otis_dah when n_otis_la(19)='1' else otis_dal; -- DA: multiplexed OTIS address/data bus otis_da( 3 downto 0) <= cpu_a( 3 downto 0) when otis_dbus='1' and (udben='0' or ldben='0') -- CPU read/write else (others => 'Z'); otis_da( 7 downto 4) <= cpu_d( 3 downto 0) when otis_dbus='1' and lo_w='0' -- CPU write else (others => 'Z'); otis_da(11 downto 8) <= cpu_d( 7 downto 4) when otis_dbus='1' and lo_w='0' -- CPU write else otis_nibble when otis_dbus='0' and nyb='0' and otis_cas='0' -- nibble-mode sound access else (others => 'Z'); otis_da(19 downto 12) <= cpu_d(15 downto 8) when otis_dbus='1' and hi_w='0' -- CPU write else (others => 'Z'); -- --------------------------------------------------------------------- -- ESP interface -- --------------------------------------------------------------------- -- ESP has a multiplexed 8-bit A/D bus -- cf. ES5510 datasheet, page 46 (unclocked D-FF on CS# signal) esp_q <= esp_cs nand esp_nq; esp_nq <= not(esp_cs) nand esp_q; esp_en_a <= esp_q; esp_en_d <= esp_nq; esp_ad <= cpu_a when esp_en_a='0' -- address else cpu_d( 7 downto 0) when esp_en_d='0' and lo_w='0' -- lower data write else cpu_d(15 downto 8) when esp_en_d='0' and hi_w='0' -- upper data write else (others => 'Z'); -- ES5701 datasheet states, citing: -- "/ESP is reflected back to the process by an open-collector buffer in order to provide a /DTACK signal." -- (might need pulse stretcher to meet proper timing) esp_dtack <= '0' when esp_cs='0' else 'Z'; end architecture;