Revision 1429
Added by markw 11 months ago
atari_chips/pokeyv2/pokeymaxv1.vhd | ||
---|---|---|
enable_audout2: integer := 1;
|
||
enable_spdif: integer := 0;
|
||
enable_ps2: integer := 0;
|
||
enable_adc: integer := 0;
|
||
paddle_lvds: integer := 0;
|
||
paddle_comp: integer := 1;
|
||
enable_iox: integer := 1;
|
||
|
||
sid_wave_base : integer := 42496; --to_integer(unsigned(x"a600"));
|
||
|
||
... | ... | |
|
||
EXT : INOUT STD_LOGIC_VECTOR(EXT_BITS DOWNTO 1);
|
||
|
||
PADDLE : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||
-- V4
|
||
PADDLE_P : INOUT STD_LOGIC_VECTOR((7*paddle_lvds) DOWNTO (1-paddle_lvds));
|
||
PADDLE_N : INOUT STD_LOGIC_VECTOR((7*paddle_lvds) DOWNTO (1-paddle_lvds));
|
||
K : OUT STD_LOGIC_VECTOR((5-(5*enable_iox)) DOWNTO enable_iox);
|
||
KR1 : IN STD_LOGIC;
|
||
KR2 : IN STD_LOGIC;
|
||
ADC_TX_P : OUT STD_LOGIC;
|
||
--ADC_TX_N : OUT STD_LOGIC;
|
||
ADC_RX_P : IN STD_LOGIC;
|
||
--ADC_RX_N : IN STD_LOGIC
|
||
|
||
-- V2-V3
|
||
PADDLE : IN STD_LOGIC_VECTOR((7*paddle_comp) DOWNTO (1-paddle_comp));
|
||
|
||
IOX_RST : OUT STD_LOGIC;
|
||
IOX_INT : IN STD_LOGIC;
|
||
IOX_SDA : INOUT STD_LOGIC;
|
||
... | ... | |
);
|
||
end component;
|
||
|
||
component lvds_tx is
|
||
port (
|
||
tx_in : in std_logic_vector(0 downto 0) := (others => 'X'); -- tx_in
|
||
tx_out : out std_logic_vector(0 downto 0) -- tx_out
|
||
);
|
||
end component lvds_tx;
|
||
|
||
component lvds_rx is
|
||
port (
|
||
data : in std_logic_vector(0 downto 0) := (others => 'X'); -- data
|
||
clock : in std_logic := 'X'; -- clock
|
||
q : out std_logic_vector(0 downto 0) -- q
|
||
);
|
||
end component lvds_rx;
|
||
|
||
component paddle_gpio is
|
||
port (
|
||
dout : out std_logic_vector(7 downto 0); -- dout.export
|
||
din : in std_logic_vector(7 downto 0) := (others => '0'); -- din.export
|
||
pad_io : inout std_logic_vector(7 downto 0) := (others => '0'); -- pad_io.export
|
||
pad_io_b : inout std_logic_vector(7 downto 0) := (others => '0'); -- pad_io_b.export
|
||
oe : in std_logic_vector(7 downto 0) := (others => '0') -- oe.export
|
||
);
|
||
end component paddle_gpio;
|
||
|
||
signal OSC_CLK : std_logic; -- about 82MHz! Always?? Massive range on data sheet
|
||
|
||
signal CLK : std_logic;
|
||
... | ... | |
-- capability restriction
|
||
signal RESTRICT_CAPABILITY_REG : std_logic_vector(4 downto 0);
|
||
signal RESTRICT_CAPABILITY_NEXT : std_logic_vector(4 downto 0);
|
||
signal readreq_s : std_logic;
|
||
signal writereq_s : std_logic;
|
||
-- 0=stereo off
|
||
-- 1=quad off
|
||
-- 2=sid off
|
||
-- 3=psg off
|
||
-- 4=sample off
|
||
|
||
-- output channel on/off
|
||
signal CHANNEL_EN_REG : std_logic_vector(4 downto 0);
|
||
signal CHANNEL_EN_NEXT : std_logic_vector(4 downto 0);
|
||
-- 0=0 (37)
|
||
-- 1=1
|
||
-- 2=2 L ext
|
||
-- 3=3 R ext
|
||
-- 4=spdif
|
||
|
||
-- ext clk enable
|
||
signal SID_ENABLE_NEXT : std_logic;
|
||
signal SID_ENABLE_REG : std_logic;
|
||
... | ... | |
signal PS2CLK : std_logic;
|
||
signal PS2DAT : std_logic;
|
||
|
||
-- adc
|
||
signal sum_reg : unsigned(7 downto 0);
|
||
signal sum_next : unsigned(7 downto 0);
|
||
|
||
signal sample_reg : unsigned(7 downto 0);
|
||
signal sample_next : unsigned(7 downto 0);
|
||
|
||
signal toggle_reg : std_logic_vector(255 downto 0);
|
||
signal toggle_next : std_logic_vector(255 downto 0);
|
||
|
||
signal ADC_FILTERED1 : unsigned(15 downto 0);
|
||
signal ADC_FILTERED2 : unsigned(15 downto 0);
|
||
|
||
-- paddles
|
||
signal PADDLE_ADJ : std_logic_vector(7 downto 0);
|
||
|
||
function getByte(a : string; x : integer) return std_logic_vector is
|
||
variable ret : std_logic_vector(7 downto 0);
|
||
begin
|
||
... | ... | |
end function min;
|
||
|
||
BEGIN
|
||
IOX_RST <= 'Z'; -- TODO weak pull up in pins (see TODO file)
|
||
EXT <= (others=>'Z');
|
||
|
||
CS_COMB <= CS1MOD and not(CS0NMOD);
|
||
... | ... | |
pokey1 : entity work.pokey
|
||
GENERIC MAP
|
||
(
|
||
custom_keyboard_scan => 1
|
||
custom_keyboard_scan => enable_iox
|
||
)
|
||
PORT MAP(CLK => CLK,
|
||
ENABLE_179 => ENABLE_CYCLE,
|
||
... | ... | |
ADDR => ADDR_IN(3 DOWNTO 0),
|
||
DATA_IN => WRITE_DATA(7 DOWNTO 0),
|
||
keyboard_response => KEYBOARD_RESPONSE,
|
||
POT_IN => PADDLE,
|
||
POT_IN => PADDLE_ADJ,
|
||
IRQ_N_OUT => POKEY_IRQ(0),
|
||
SIO_OUT1 => SIO_TXD,
|
||
SIO_OUT2 => open,
|
||
... | ... | |
process(
|
||
DEVICE_ADDR,
|
||
POKEY_DO,
|
||
SID_DO,
|
||
SID_DO,SID_DRIVE_DO,
|
||
PSG_DO,
|
||
SAMPLE_DO,
|
||
CONFIG_DO,
|
||
write_n,
|
||
request,
|
||
RESTRICT_CAPABILITY_REG
|
||
RESTRICT_CAPABILITY_REG, readreq_s, writereq_s
|
||
)
|
||
variable writereq : std_logic;
|
||
variable readreq : std_logic;
|
||
... | ... | |
when "0001" =>
|
||
enable_region := RESTRICT_CAPABILITY_REG(0) or RESTRICT_CAPABILITY_REG(1);
|
||
DO_MUX <= POKEY_DO(1);
|
||
POKEY_WRITE_ENABLE(1) <= writereq;
|
||
POKEY_WRITE_ENABLE(1) <= writereq_s;
|
||
when "0010" =>
|
||
enable_region := RESTRICT_CAPABILITY_REG(1);
|
||
DO_MUX <= POKEY_DO(2);
|
||
POKEY_WRITE_ENABLE(2) <= writereq;
|
||
POKEY_WRITE_ENABLE(2) <= writereq_s;
|
||
when "0011" =>
|
||
enable_region := RESTRICT_CAPABILITY_REG(1);
|
||
DO_MUX <= POKEY_DO(3);
|
||
POKEY_WRITE_ENABLE(3) <= writereq;
|
||
POKEY_WRITE_ENABLE(3) <= writereq_s;
|
||
when "0100"|"0101" =>
|
||
enable_region := RESTRICT_CAPABILITY_REG(2);
|
||
DO_MUX <= SID_DO(0);
|
||
DRIVE_DO_MUX <= SID_DRIVE_DO(0);
|
||
SID_WRITE_ENABLE(0) <= writereq;
|
||
SID_READ_ENABLE(0) <= readreq;
|
||
SID_WRITE_ENABLE(0) <= writereq_s;
|
||
SID_READ_ENABLE(0) <= readreq_s;
|
||
when "0110"|"0111" =>
|
||
enable_region := RESTRICT_CAPABILITY_REG(2);
|
||
DO_MUX <= SID_DO(1);
|
||
DRIVE_DO_MUX <= SID_DRIVE_DO(1);
|
||
SID_WRITE_ENABLE(1) <= writereq;
|
||
SID_READ_ENABLE(0) <= readreq;
|
||
SID_WRITE_ENABLE(1) <= writereq_s;
|
||
SID_READ_ENABLE(0) <= readreq_s;
|
||
when "1000"|"1001" =>
|
||
enable_region := RESTRICT_CAPABILITY_REG(4);
|
||
DO_MUX <= SAMPLE_DO;
|
||
SAMPLE_WRITE_ENABLE <= writereq;
|
||
SAMPLE_WRITE_ENABLE <= writereq_s;
|
||
when "1010" =>
|
||
enable_region := RESTRICT_CAPABILITY_REG(3);
|
||
DO_MUX <= PSG_DO(0);
|
||
PSG_WRITE_ENABLE(0) <= writereq;
|
||
PSG_WRITE_ENABLE(0) <= writereq_s;
|
||
when "1011" =>
|
||
enable_region := RESTRICT_CAPABILITY_REG(3);
|
||
DO_MUX <= PSG_DO(1);
|
||
PSG_WRITE_ENABLE(1) <= writereq;
|
||
PSG_WRITE_ENABLE(1) <= writereq_s;
|
||
when "1111" =>
|
||
enable_region := '1';
|
||
DO_MUX <= CONFIG_DO;
|
||
CONFIG_WRITE_ENABLE <= writereq;
|
||
CONFIG_WRITE_ENABLE <= writereq_s;
|
||
when others =>
|
||
end case;
|
||
|
||
readreq_s <= readreq and enable_region;
|
||
writereq_s <= writereq and enable_region;
|
||
|
||
if enable_region='0' then
|
||
DO_MUX <= POKEY_DO(0);
|
||
POKEY_WRITE_ENABLE(0) <= writereq;
|
||
... | ... | |
SID_FILTER1_REG <= "10"; -- 0=8580,1=6581,2=digifix
|
||
SID_FILTER2_REG <= "10"; -- 0=8580,1=6581,2=digifix
|
||
RESTRICT_CAPABILITY_REG <= (others=>'1');
|
||
CHANNEL_EN_REG <= (others=>'1');
|
||
elsif (clk'event and clk='1') then
|
||
DETECT_RIGHT_REG <= DETECT_RIGHT_NEXT;
|
||
IRQ_EN_REG <= IRQ_EN_NEXT;
|
||
... | ... | |
SID_FILTER1_REG <= SID_FILTER1_NEXT;
|
||
SID_FILTER2_REG <= SID_FILTER2_NEXT;
|
||
RESTRICT_CAPABILITY_REG <= RESTRICT_CAPABILITY_NEXT;
|
||
CHANNEL_EN_REG <= CHANNEL_EN_NEXT;
|
||
end if;
|
||
end process;
|
||
|
||
... | ... | |
CPU_FLASH_REQUEST_REG,CPU_FLASH_WRITE_N_REG,CPU_FLASH_CFG_REG,CPU_FLASH_ADDR_REG,CPU_FLASH_DATA_REG,
|
||
CPU_FLASH_COMPLETE,CONFIG_FLASH_COMPLETE,CONFIG_FLASH_ADDR,flash_do_slow,
|
||
RESTRICT_CAPABILITY_REG,
|
||
CHANNEL_EN_REG,
|
||
PAL_REG
|
||
)
|
||
begin
|
||
... | ... | |
CPU_FLASH_DATA_NEXT <= CPU_FLASH_DATA_REG;
|
||
|
||
RESTRICT_CAPABILITY_NEXT <= RESTRICT_CAPABILITY_REG;
|
||
CHANNEL_EN_NEXT <= CHANNEL_EN_REG;
|
||
|
||
PAL_NEXT <= PAL_REG;
|
||
|
||
... | ... | |
-- 6-7 reserved
|
||
RESTRICT_CAPABILITY_NEXT <= flash_do_slow(12 downto 8);
|
||
-- 13-15 reserved
|
||
-- 16-23 reserved (used in sidmax)
|
||
CHANNEL_EN_NEXT <= flash_do_slow(28 downto 24);
|
||
-- 29-31 reserved
|
||
when others =>
|
||
end case;
|
||
elsif (CONFIG_WRITE_ENABLE='1') then
|
||
... | ... | |
RESTRICT_CAPABILITY_NEXT(4 downto 0) <= WRITE_DATA(4 downto 0);
|
||
end if;
|
||
|
||
if (addr_decoded4(9)='1') then
|
||
CHANNEL_EN_NEXT(4 downto 0) <= WRITE_DATA(4 downto 0);
|
||
end if;
|
||
|
||
if (addr_decoded4(12)='1') then
|
||
if (WRITE_DATA=x"3F") then
|
||
CONFIG_ENABLE_NEXT <= '1';
|
||
... | ... | |
CPU_FLASH_CFG_REG,CPU_FLASH_ADDR_REG,CPU_FLASH_DATA_REG,
|
||
CPU_FLASH_REQUEST_REG, CPU_FLASH_WRITE_N_REG,
|
||
RESTRICT_CAPABILITY_REG,
|
||
CHANNEL_EN_REG,
|
||
PAL_REG
|
||
)
|
||
variable ACTUAL_CAPABILITY : std_logic_vector(7 downto 0);
|
||
... | ... | |
CONFIG_DO(4 downto 0) <= RESTRICT_CAPABILITY_REG(4 downto 0);
|
||
end if;
|
||
|
||
if (addr_decoded4(9)='1') then
|
||
CONFIG_DO(4 downto 0) <= CHANNEL_EN_REG(4 downto 0);
|
||
end if;
|
||
|
||
if (addr_decoded4(12)='1') then
|
||
CONFIG_DO <= x"01";
|
||
end if;
|
||
... | ... | |
DETECT_RIGHT => DETECT_RIGHT_REG,
|
||
FANCY_ENABLE => FANCY_ENABLE,
|
||
GTIA_EN => GTIA_ENABLE_REG,
|
||
ADC_EN => "1100",
|
||
|
||
CH0 => POKEY_AUDIO_0,
|
||
CH1 => POKEY_AUDIO_1,
|
||
... | ... | |
CH7 => unsigned(SID_AUDIO(1)),
|
||
CH8 => unsigned(PSG_AUDIO(0)),
|
||
CH9 => unsigned(PSG_AUDIO(1)),
|
||
CHA(14 downto 12) => (others=>'0'),
|
||
CHA(11) => SIO_RXD_SYNC,
|
||
CHA(10 downto 0) => (others=>'0'),
|
||
CHA(14 downto 0) => (others=>'0'),
|
||
CHA(15) => GTIA_AUDIO,
|
||
CHB => ADC_FILTERED2,
|
||
|
||
AUDIO_0_UNSIGNED => AUDIO_0_UNSIGNED,
|
||
AUDIO_1_UNSIGNED => AUDIO_1_UNSIGNED,
|
||
... | ... | |
spdif_out => spdif_out
|
||
);
|
||
|
||
EXT(SPDIF_BIT) <= spdif_out;
|
||
EXT(SPDIF_BIT) <= spdif_out when CHANNEL_EN_REG(4)='1' else 'Z';
|
||
end generate spdif_on;
|
||
|
||
-- io extension
|
||
-- drive to 0 for pot reset (otherwise high imp)
|
||
-- drive keyboard lines
|
||
iox_on : if enable_iox=1 generate
|
||
i2c_master0 : entity work.i2c_master
|
||
generic map(input_clk=>58_000_000, bus_clk=>2_800_000)
|
||
port map(
|
||
... | ... | |
keyboard_response=>iox_keyboard_response,
|
||
keyboard_scan_enable=>keyboard_scan_enable
|
||
);
|
||
IOX_RST <= 'Z'; -- TODO weak pull up in pins (see TODO file)
|
||
end generate iox_on;
|
||
|
||
iox_off : if enable_iox=0 generate
|
||
iox_keyboard_response <= KR2&KR1;
|
||
k <= keyboard_scan;
|
||
end generate iox_off;
|
||
|
||
-- PS2 keyboard
|
||
ps2_on : if enable_ps2=1 generate
|
||
PS2CLK <= EXT(PS2CLK_BIT);
|
||
... | ... | |
KEYBOARD_RESPONSE <= IOX_KEYBOARD_RESPONSE;
|
||
end generate ps2_off;
|
||
|
||
adc_on : if enable_adc=1 generate
|
||
-- Simple ADC for SIO/PBI audio in
|
||
process(clk,reset_n)
|
||
begin
|
||
if (reset_n='0') then
|
||
toggle_reg <= (others=>'0');
|
||
sum_reg <= (others=>'0');
|
||
sample_reg <= (others=>'0');
|
||
elsif (clk'event and clk='1') then
|
||
toggle_reg <= toggle_next;
|
||
sum_reg <= sum_next;
|
||
sample_reg <= sample_next;
|
||
end if;
|
||
end process;
|
||
|
||
lvds_tx0: lvds_tx
|
||
port map(
|
||
tx_in(0) => toggle_reg(0),
|
||
tx_out(0) => ADC_TX_P
|
||
);
|
||
|
||
lvds_rx0: lvds_rx
|
||
port map(
|
||
data(0) => ADC_RX_P,
|
||
clock => CLK,
|
||
q(0) => toggle_next(0)
|
||
);
|
||
toggle_next(255 downto 1) <= toggle_reg(254 downto 0);
|
||
|
||
adcfilter : entity work.simple_low_pass_filter
|
||
PORT MAP
|
||
(
|
||
CLK => CLK,
|
||
AUDIO_IN => not(sample_reg(7)&sample_reg(6 downto 0))&"00000000",
|
||
SAMPLE_IN => ENABLE_CYCLE,
|
||
AUDIO_OUT => ADC_FILTERED1
|
||
);
|
||
|
||
adcfilter2 : entity work.simple_low_pass_filter
|
||
PORT MAP
|
||
(
|
||
CLK => CLK,
|
||
AUDIO_IN => ADC_FILTERED1,
|
||
SAMPLE_IN => ENABLE_CYCLE,
|
||
AUDIO_OUT => ADC_FILTERED2
|
||
);
|
||
|
||
process(sum_reg,sample_reg,toggle_reg)
|
||
begin
|
||
sum_next <= sum_reg;
|
||
sample_next <= sample_reg;
|
||
|
||
if (toggle_reg(255)='1' and toggle_reg(0)='0') then
|
||
sum_next <= sum_reg -1;
|
||
elsif (toggle_reg(255)='0' and toggle_reg(0)='1') then
|
||
sum_next <= sum_reg +1;
|
||
end if;
|
||
|
||
sample_next <= sum_reg;
|
||
end process;
|
||
end generate adc_on;
|
||
|
||
adc_off : if enable_adc=0 generate
|
||
ADC_FILTERED2(15 downto 12) <= (others=>'0');
|
||
ADC_FILTERED2(11) <= SIO_RXD_SYNC;
|
||
ADC_FILTERED2(10 downto 0) <= (others=>'0');
|
||
end generate adc_off;
|
||
|
||
paddle_lvds_on : if paddle_lvds=1 generate
|
||
paddle_lvds_rx0: paddle_gpio
|
||
port map(
|
||
dout => PADDLE_ADJ,
|
||
din => (others=>'0'),
|
||
pad_io => PADDLE_P,
|
||
pad_io_b => PADDLE_N,
|
||
oe =>(others=>POTRESET)
|
||
);
|
||
|
||
end generate paddle_lvds_on;
|
||
|
||
paddle_comp_on : if paddle_comp=1 generate
|
||
PADDLE_ADJ <= PADDLE;
|
||
end generate paddle_comp_on;
|
||
|
||
-- Wire up pins
|
||
ACLK <= SIO_CLOCKOUT;
|
||
BCLK <= '0' when (SIO_CLOCKIN_OE='1' and SIO_CLOCKIN_OUT='0') else 'Z';
|
||
... | ... | |
|
||
|
||
--1->pin37
|
||
AUD(1) <= AUDIO_0_SIGMADELTA;
|
||
AUD(1) <= AUDIO_0_SIGMADELTA when CHANNEL_EN_REG(0)='1' else '0';
|
||
|
||
-- ext AUD pins:
|
||
AUD(2) <= AUDIO_1_SIGMADELTA;
|
||
AUD(3) <= AUDIO_2_SIGMADELTA;
|
||
AUD(4) <= AUDIO_3_SIGMADELTA;
|
||
AUD(2) <= AUDIO_1_SIGMADELTA when CHANNEL_EN_REG(1)='1' else '0';
|
||
AUD(3) <= AUDIO_2_SIGMADELTA when CHANNEL_EN_REG(2)='1' else '0';
|
||
AUD(4) <= AUDIO_3_SIGMADELTA when CHANNEL_EN_REG(3)='1' else '0';
|
||
|
||
IRQ <= '0' when (IRQ_EN_REG='1' and (and_reduce(POKEY_IRQ)='0')) or (IRQ_EN_REG='0' and POKEY_IRQ(0)='0') or (SAMPLE_IRQ='1') else 'Z';
|
||
|
Also available in: Unified diff
Refreshed