--- In cone_cores@yahoogroups.com, Blair <blairc64@...> wrote:
>
> I'd love to see the Chameleon multiplexer. :) (see email address if
> you are feeling pity on me)
First the purpose I have given the lines:
-- toExtender vid(13 downto 11) & vid(3 downto 0)
-- frExtender vid(10 downto 4)
-- clkExtender vid(15)
Ok following is the code used on the extender side. As you can see I use a
specific byte to sync. The system starts in SYNC state and waits for a "5" to
appear. When the 1k30 is not configured its lines are high so the extender will
see "111111" (number of ones depending on the bits used for the interface). Once
the 1k30 is started it will send "0000101" as SYNC byte and the FPGAs are in
sync.
For data from the extender to the 1k30 it goes exactly the same, but this time
the extender starts with a sync. However while sending the sync I also sneak in
some clock information in the upper bits, so the 1k30 should only really watch
the lower 4 bits to determine sync.
The SYNC bytes are repeated, though not really necessary (they use the same
clock so can never get out of sync), it makes debugging easier as I can reload
only one the FPGAs by JTAG and things will continue to work.
After sync is complete both FPGAs will send multiple bytes after each other in
time. 1k30 will send IEC bus info followed by PS/2 and then the joysticks.
The extender send address and data lines for the SID access followed by PS/2 in
the host to device direction to configure the mouse.
-----------------------------------------------------------------------
type State1k30 is (SYNC, IEC, DATA1, CTRL1, ADDR1, ADDR2, PS2, JOY1, JOY2);
signal recvState : State1k30 := SYNC;
signal sendState : State1k30 := SYNC;
-- -----------------------------------------------------------------------
-- Communication with 1k30 bridge
-- -----------------------------------------------------------------------
process(sysclk)
begin
if rising_edge(sysclk) then
-- Capture external data (from SID or cartridge port)
externalData <= mdb;
end if;
end process;
process(sysclk)
begin
if rising_edge(sysclk) then
case recvState is
when SYNC =>
if toExtender(3 downto 0) = X"5" then
recvState <= IEC;
end if;
when IEC =>
cia2_pai(6) <= toExtender(2);
cia2_pai(7) <= toExtender(3);
recvState <= PS2;
when PS2 =>
ps2_kbd_clk <= toExtender(0);
ps2_kbd_dat <= toExtender(1);
ps2_mse_clk <= toExtender(2);
ps2_mse_dat <= toExtender(3);
recvState <= JOY1;
recvTest <= recvTest(11 downto 0) & toExtender(3 downto 0);
when JOY1 =>
joystick1 <= toExtender(4 downto 0);
recvState <= JOY2;
when JOY2 =>
joystick2 <= toExtender(4 downto 0);
recvState <= SYNC;
when others =>
recvState <= SYNC;
end case;
end if;
end process;
process(sysclk)
begin
if rising_edge(sysclk) then
frExtender <= "0000000";
case sendState is
when SYNC =>
frExtender(6) <= phi;
frExtender(5) <= systemWe;
if (phi = '0') then
frExtender(3 downto 0) <= X"5";
sendState <= IEC;
end if;
if (csSid1 = '1') and (systemCnt = 56) then
frExtender(3 downto 0) <= X"4";
sendState <= IEC;
end if;
when IEC =>
frExtender <= systemData(7) & "00" & cia2_pao(5) & cia2_pao(4) & cia2_pao(3)
& "0";
sendState <= DATA1;
when DATA1 =>
frExtender <= systemData(6 downto 0);
sendState <= ADDR1;
when ADDR1 =>
frExtender <= systemAddr(6 downto 0);
sendState <= ADDR2;
when ADDR2 =>
sendState <= PS2;
when PS2 =>
frExtender <= "111" & ps2_mse_dat_out & ps2_mse_clk_out & "11";
sendState <= SYNC;
when others =>
sendState <= SYNC;
end case;
end if;
end process;
-----------------------------------------------------------------------
And this is the 1k30 side
-- -----------------------------------------------------------------------
--
-- Turbo Chameleon
--
-- Multi purpose FPGA expansion for the commodore 64 computer
--
-- -----------------------------------------------------------------------
-- Copyright 2005-2009 by Peter Wendrich (pwsoft@...)
-- All Rights Reserved.
--
-- http://www.syntiac.com/chameleon.html
--
-- -----------------------------------------------------------------------
--
-- Port of the Turbo Chameleon core to the C-One.
-- 1k30 signal router
--
-- -----------------------------------------------------------------------
--
-- toExtender vid(13 downto 11) & vid(3 downto 0)
-- frExtender vid(10 downto 4)
-- clkExtender vid(15)
--
--
-- clk gb(7)
--
-- -----------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
-- -----------------------------------------------------------------------
entity cone_chameleon_1k30 is
port (
-- Clocks
sysclk : in std_logic;
clk1Mhz : out std_logic;
-- Extender
clkExtender : in std_logic;
toExtender : out unsigned(6 downto 0);
frExtender : in unsigned(6 downto 0);
-- 1K100
gb : inout unsigned(7 downto 0);
addrBus : out unsigned(4 downto 0);
dataBus : inout unsigned(7 downto 0);
wr : out std_logic;
cselect : out unsigned(3 downto 0);
ps2_kbd_clk : inout std_logic;
ps2_kbd_dat : inout std_logic;
ps2_mse_clk : inout std_logic;
ps2_mse_dat : inout std_logic
);
end entity;
-- -----------------------------------------------------------------------
architecture rtl of cone_chameleon_1k30 is
type State is (SYNC, IEC, DATA1, CTRL1, ADDR1, ADDR2, PS2, JOY1, JOY2);
signal toExtenderState : State := SYNC;
signal recvState : State := SYNC;
type IoStateDef is (IDLE, IECR, IECW, SIDR, SIDW, SIDWHOLD);
signal ioState : IoStateDef := IDLE;
signal ioTimer : unsigned(1 downto 0) := (others => '0');
signal clk : std_logic;
signal systemWe : std_logic;
signal toExtenderLoc : unsigned(6 downto 0) := (others => '0');
signal frExtenderLoc : unsigned(6 downto 0) := (others => '0');
signal csSid : std_logic := '0';
signal csSidPending : std_logic := '0';
signal curData : unsigned(7 downto 0);
signal curAddr : unsigned(15 downto 0);
signal IECreg : unsigned(7 downto 3);
signal joystick : unsigned(15 downto 0);
signal joyshift : unsigned(15 downto 0);
signal kbdClkReg : std_logic;
signal kbdDatReg : std_logic;
signal ps2_mse_clk_out : std_logic := '1';
signal ps2_mse_dat_out : std_logic := '1';
begin
-- Extender clock to 1k100
gb(7) <= clkExtender;
clk <= not clkExtender;
ps2_kbd_clk <= 'Z';
ps2_kbd_dat <= 'Z';
ps2_mse_clk <= 'Z';
ps2_mse_dat <= 'Z';
process(clk)
begin
if rising_edge(clk) then
toExtender <= toExtenderLoc;
frExtenderLoc <= frExtender;
end if;
end process;
-- -----------------------------------------------------------------------
-- PS/2 Mouse Interface
process(ps2_mse_clk_out, ps2_mse_dat_out)
begin
ps2_mse_clk <= 'Z';
ps2_mse_dat <= 'Z';
if ps2_mse_clk_out = '0' then
ps2_mse_clk <= '0';
end if;
if ps2_mse_dat_out = '0' then
ps2_mse_dat <= '0';
end if;
end process;
-- -----------------------------------------------------------------------
-- Joystick data
process(clk)
begin
if rising_edge(clk) then
joyshift <= gb(0) & joyshift(15 downto 1);
if joyshift(0) = '0' then
joyshift(14 downto 0) <= (others => '1');
joystick <= joyshift;
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
kbdClkReg <= ps2_kbd_clk;
kbdDatReg <= ps2_kbd_dat;
end if;
end process;
-- Data from 1k30 to extender
process(clk)
begin
if rising_edge(clk) then
case toExtenderState is
when SYNC =>
toExtenderLoc <= "0000101";
toExtenderState <= IEC;
when IEC =>
toExtenderLoc <= "000" & IECreg(7) & IECreg(6) & "00";
toExtenderState <= PS2;
when PS2 =>
toExtenderLoc <= "000" & ps2_mse_dat & ps2_mse_clk & kbdDatReg & kbdClkReg;
toExtenderState <= JOY1;
when JOY1 =>
toExtenderLoc <= "00" & joystick(7) & joystick(4) & joystick(5) &
joystick(6) & joystick(8);
toExtenderState <= JOY2;
when JOY2 =>
toExtenderLoc <= "00" & joystick(10) & joystick(13) & joystick(12) &
joystick(11) & joystick(9);
toExtenderState <= SYNC;
when others =>
toExtenderState <= SYNC;
end case;
end if;
end process;
-- I/O access
process(clk)
begin
if rising_edge(clk) then
ioTimer <= ioTimer + 1;
if ioTimer = 0 then
addrBus <= "ZZZZZ";
dataBus <= "ZZZZZZZZ";
cselect <= "1111";
wr <= '1';
case ioState is
when IDLE =>
if csSid = '1' and systemWe = '1' then
dataBus <= curData;
addrBus <= curAddr(4 downto 0);
ioState <= SIDW;
elsif csSid = '1' and systemWe = '0' then
addrBus <= curAddr(4 downto 0);
ioState <= SIDR;
else
cselect <= "1011";
ioState <= IECR;
end if;
when SIDR =>
cselect <= "0011";
addrBus <= curAddr(4 downto 0);
if csSid = '0' then
cselect <= "1111";
ioState <= IDLE;
end if;
when SIDW =>
cselect <= "0011";
wr <= '0';
dataBus <= curData;
addrBus <= curAddr(4 downto 0);
if csSid = '0' then
cselect <= "1111";
-- ioState <= IDLE;
ioState <= SIDWHOLD;
end if;
when SIDWHOLD =>
-- cselect <= "0011";
-- wr <= '0';
dataBus <= curData;
addrBus <= curAddr(4 downto 0);
ioState <= IDLE;
when IECR =>
IECreg(7) <= dataBus(7);
IECreg(6) <= dataBus(6);
dataBus(5) <= IECreg(5);
dataBus(4) <= IECreg(4);
dataBus(3) <= IECreg(3);
dataBus(2) <= '0'; -- lptstrobe
cselect <= "1011";
wr <= '0';
ioState <= IECW;
when IECW =>
dataBus(5) <= IECreg(5);
dataBus(4) <= IECreg(4);
dataBus(3) <= IECreg(3);
dataBus(2) <= '0'; -- lptstrobe
ioState <= IDLE;
when others =>
ioState <= IDLE;
end case;
end if;
end if;
end process;
-- Data from extender to 1k30 and beyond
process(clk)
begin
if rising_edge(clk) then
case recvState is
when SYNC =>
clk1mhz <= frExtenderLoc(6);
systemWe <= frExtenderLoc(5);
csSidPending <= '0';
if frExtenderLoc(3 downto 0) = X"4" then
csSidPending <= '1';
recvState <= IEC;
end if;
if frExtenderLoc(6) = '0' then
csSid <= '0';
end if;
if frExtenderLoc(3 downto 0) = X"5" then
recvState <= IEC;
end if;
when IEC =>
curData(7) <= frExtenderLoc(6);
IECreg(5) <= frExtenderLoc(3);
IECreg(4) <= frExtenderLoc(2);
IECreg(3) <= frExtenderLoc(1);
recvState <= DATA1;
when DATA1 =>
curData(6 downto 0) <= frExtenderLoc;
recvState <= ADDR1;
when ADDR1 =>
curAddr(6 downto 0) <= frExtenderLoc;
if csSidPending = '1' then
csSid <= '1';
end if;
recvState <= ADDR2;
when ADDR2 =>
recvState <= PS2;
when PS2 =>
ps2_mse_clk_out <= frExtenderLoc(2);
ps2_mse_dat_out <= frExtenderLoc(3);
recvState <= SYNC;
when others =>
recvState <= SYNC;
end case;
end if;
end process;
end architecture;