Project

General

Profile

-- -----------------------------------------------------------------------
--
-- Turbo Chameleon
--
-- Multi purpose FPGA expansion for the Commodore 64 computer
--
-- -----------------------------------------------------------------------
-- Copyright 2005-2010 by Peter Wendrich (pwsoft@syntiac.com)
-- All Rights Reserved.
--
-- http://www.syntiac.com/chameleon.html
-- -----------------------------------------------------------------------
--
-- Chameleon USB micro communication
--
-- -----------------------------------------------------------------------
-- clk - system clock
-- req - toggles on a access request (read & write)
-- ack - toggled by system when the request is processed.
-- we - write enable, is high during write actions
-- a - 32 bits address bus
-- d - data input
-- q - data output
-- flashslot - Slot number (0-15) in flash where FPGA is started from.
-- Highest bit is valid-bit, is set when slot number is valid.
-- serial_clk - clock of synchronous serial communication
-- serial_rxd - serial receive data
-- serial_txd - serial send data
-- serial_cts_n - clear to send inverted. When low USB micro is ready to
-- receive bytes.
-- -----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

-- -----------------------------------------------------------------------

entity chameleon_usb is
port (
clk : in std_logic;
req : out std_logic;
ack : in std_logic := '0';
we : out std_logic;
a : out unsigned(31 downto 0);
d : in unsigned(7 downto 0) := (others => '0');
q : out unsigned(7 downto 0);
reconfig : in std_logic := '0';
reconfig_slot : in unsigned(3 downto 0) := (others => '0');
flashslot : out unsigned(4 downto 0);
serial_clk : in std_logic;
serial_rxd : in std_logic := '1';
serial_txd : out std_logic;
serial_cts_n : in std_logic := '0';
serial_debug_trigger : out std_logic;
serial_debug_data : out unsigned(8 downto 0)
);
end entity;

-- -----------------------------------------------------------------------

architecture rtl of chameleon_usb is
type state_t is (
STATE_RESET, STATE_IDLE,
STATE_READ, STATE_READ_ACK, STATE_WRITE, STATE_WRITE_ACK,
STATE_ADDR0, STATE_ADDR1, STATE_ADDR2, STATE_ADDR3,
STATE_LEN0, STATE_LEN1, STATE_LEN2);
type command_t is (
CMD_NONE, CMD_READ, CMD_WRITE);
signal req_reg : std_logic := '0';
signal state : state_t := STATE_RESET;
signal flashslot_reg : unsigned(4 downto 0) := (others => '0');

signal recv_trigger : std_logic;
signal recv_data : unsigned(8 downto 0) := (others => '0');
signal send_trigger : std_logic := '0';
signal send_empty : std_logic;
signal send_data : unsigned(8 downto 0) := (others => '0');
signal command : command_t := CMD_NONE;
signal cmd_length : unsigned(23 downto 0) := (others => '0');
signal cmd_address : unsigned(31 downto 0) := (others => '0');
begin
req <= req_reg;
we <= '1' when ((state = STATE_WRITE) or (state = STATE_WRITE_ACK)) else '0';
a <= cmd_address;
flashslot <= flashslot_reg;
serial_debug_trigger <= recv_trigger;
serial_debug_data <= recv_data;

-- -----------------------------------------------------------------------

myUsart : entity work.gen_usart
generic map (
bits => 9
)
port map (
clk => clk,
d => send_data,
d_trigger => send_trigger,
d_empty => send_empty,
q => recv_data,
q_trigger => recv_trigger,
serial_clk => serial_clk,
serial_rxd => serial_rxd,
serial_txd => serial_txd,
serial_cts_n => serial_cts_n
);

process(clk)
begin
if rising_edge(clk) then
send_trigger <= '0';
case state is
when STATE_RESET =>
if send_empty = '1' then
send_data <= "100101010"; -- 42, 0x12A
send_trigger <= '1';
end if;
when STATE_IDLE =>
if (send_empty = '1') and (reconfig = '1') then
send_data <= "11111" & reconfig_slot;
send_trigger <= '1';
end if;
when STATE_READ =>
if (req_reg = ack) and (send_empty = '1') then
req_reg <= not req_reg;
state <= STATE_READ_ACK;
end if;
when STATE_READ_ACK =>
if (req_reg = ack) then
send_data <= "0" & d;
send_trigger <= '1';
cmd_address <= cmd_address + 1;
if cmd_length = 0 then
state <= STATE_IDLE;
else
cmd_length <= cmd_length - 1;
state <= STATE_READ;
end if;
end if;
when STATE_WRITE_ACK =>
if req_reg = ack then
cmd_address <= cmd_address + 1;
state <= STATE_WRITE;
end if;
when others =>
null;
end case;
if recv_trigger = '1' then
if recv_data(8) = '1' then
case recv_data(7 downto 0) is
when X"00" =>
command <= CMD_NONE;
state <= STATE_IDLE;
when X"01" =>
command <= CMD_WRITE;
state <= STATE_ADDR3;
when X"02" =>
command <= CMD_READ;
state <= STATE_ADDR3;
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17"
| X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" =>
flashslot_reg <= recv_data(4 downto 0);
command <= CMD_NONE;
state <= STATE_IDLE;
when others =>
command <= CMD_NONE;
state <= STATE_IDLE;
end case;
else
case state is
when STATE_WRITE =>
q <= recv_data(7 downto 0);
req_reg <= not req_reg;
state <= STATE_WRITE_ACK;
when STATE_ADDR0 =>
cmd_address(7 downto 0) <= recv_data(7 downto 0);
case command is
when CMD_READ =>
state <= STATE_LEN2;
when CMD_WRITE =>
state <= STATE_WRITE;
when others =>
state <= STATE_IDLE;
end case;
when STATE_ADDR1 =>
cmd_address(15 downto 8) <= recv_data(7 downto 0);
state <= STATE_ADDR0;
when STATE_ADDR2 =>
cmd_address(23 downto 16) <= recv_data(7 downto 0);
state <= STATE_ADDR1;
when STATE_ADDR3 =>
cmd_address(31 downto 24) <= recv_data(7 downto 0);
state <= STATE_ADDR2;
when STATE_LEN0 =>
cmd_length(7 downto 0) <= recv_data(7 downto 0);
state <= STATE_READ;
when STATE_LEN1 =>
cmd_length(15 downto 8) <= recv_data(7 downto 0);
state <= STATE_LEN0;
when STATE_LEN2 =>
cmd_length(23 downto 16) <= recv_data(7 downto 0);
state <= STATE_LEN1;
when others =>
null;
end case;
end if;
end if;
end if;
end process;
end architecture;


(16-16/40)