260 lines
7.7 KiB
VHDL
Executable File
260 lines
7.7 KiB
VHDL
Executable File
----------------------------------------------------------------------------------
|
|
-- Company:
|
|
-- Engineer:
|
|
--
|
|
-- Create Date: 15:52:22 12/30/2008
|
|
-- Design Name:
|
|
-- Module Name: toplevel - Behavioral
|
|
-- Project Name:
|
|
-- Target Devices:
|
|
-- Tool versions:
|
|
-- Description:
|
|
--
|
|
-- Dependencies:
|
|
--
|
|
-- Revision:
|
|
-- Revision 0.01 - File Created
|
|
-- Additional Comments:
|
|
--
|
|
----------------------------------------------------------------------------------
|
|
library IEEE;
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
|
use IEEE.NUMERIC_STD.ALL;
|
|
|
|
---- Uncomment the following library declaration if instantiating
|
|
---- any Xilinx primitives in this code.
|
|
library UNISIM;
|
|
use UNISIM.VComponents.all;
|
|
|
|
entity uart is
|
|
|
|
port (
|
|
CLK_16M : in std_logic;
|
|
DATA_I : in std_logic_vector(7 downto 0);
|
|
ADDR_I : in std_logic_vector(1 downto 0);
|
|
IORQ_n, RD_n, WR_n : in std_logic;
|
|
DATA_O : out std_logic_vector(7 downto 0);
|
|
-- SPI for Atmel Dataflash
|
|
SPI_MISO : in std_logic;
|
|
SPI_MOSI : out std_logic;
|
|
SPI_SCK : out std_logic;
|
|
SPI_SS_B : out std_logic := '1';
|
|
DATAFLASH_WP : out std_logic;
|
|
DATAFLASH_RST : out std_logic;
|
|
-- LCD interface
|
|
LCD_DB : inout std_logic_vector(7 downto 0);
|
|
LCD_E, LCD_RS, LCD_RW : out std_logic;
|
|
-- Buttons
|
|
BTN_NORTH : in STD_LOGIC;
|
|
BTN_SOUTH : in STD_LOGIC;
|
|
BTN_EAST : in STD_LOGIC;
|
|
BTN_WEST : in STD_LOGIC;
|
|
ROT_CENTER : in STD_LOGIC);
|
|
|
|
end uart;
|
|
|
|
architecture Behavioral of uart is
|
|
|
|
component kcpsm3
|
|
port (
|
|
address : out std_logic_vector(9 downto 0);
|
|
instruction : in std_logic_vector(17 downto 0);
|
|
port_id : out std_logic_vector(7 downto 0);
|
|
write_strobe : out std_logic;
|
|
out_port : out std_logic_vector(7 downto 0);
|
|
read_strobe : out std_logic;
|
|
in_port : in std_logic_vector(7 downto 0);
|
|
interrupt : in std_logic;
|
|
interrupt_ack : out std_logic;
|
|
reset : in std_logic;
|
|
clk : in std_logic);
|
|
end component;
|
|
|
|
component uartprog
|
|
port (
|
|
address : in std_logic_vector(9 downto 0);
|
|
instruction : out std_logic_vector(17 downto 0);
|
|
clk : in std_logic);
|
|
end component;
|
|
|
|
component fifo16x8
|
|
port (
|
|
DATAIN : in STD_LOGIC_VECTOR (7 downto 0);
|
|
WRITESTB : in STD_LOGIC;
|
|
DATAOUT : out STD_LOGIC_VECTOR (7 downto 0);
|
|
READSTB : in STD_LOGIC;
|
|
CLK : in STD_LOGIC;
|
|
FULL : out STD_LOGIC;
|
|
EMPTY : out STD_LOGIC);
|
|
end component;
|
|
|
|
component spi
|
|
port (
|
|
MISO : in std_logic;
|
|
MOSI, SCK : out std_logic;
|
|
DATA_I : in std_logic_vector(7 downto 0);
|
|
DATA_O : out std_logic_vector(7 downto 0);
|
|
START : in std_logic;
|
|
BUSY : out std_logic;
|
|
CLK : in std_logic);
|
|
end component;
|
|
|
|
signal receive_r, transmit_r : std_logic_vector(7 downto 0);
|
|
signal drt_r, drr_r : std_logic := '0';
|
|
|
|
signal kcpsm3_addr : std_logic_vector(9 downto 0);
|
|
signal kcpsm3_instr : std_logic_vector(17 downto 0);
|
|
signal kcpsm3_portid, kcpsm3_outport, kcpsm3_inport : std_logic_vector(7 downto 0);
|
|
signal kcpsm3_wrstb, kcpsm3_rdstb : std_logic;
|
|
|
|
attribute iob : string;
|
|
signal lcdctrl_r : std_logic_vector(2 downto 0) := "000";
|
|
signal lcdout_r : std_logic_vector(7 downto 0) := X"00";
|
|
attribute iob of lcdout_r : signal is "true";
|
|
attribute iob of lcdctrl_r : signal is "true";
|
|
|
|
signal spi_datao : std_logic_vector(7 downto 0);
|
|
signal spi_start, spi_busy : std_logic;
|
|
|
|
signal iorq_old : std_logic := '0';
|
|
|
|
signal fifo_t_wrstb, fifo_t_rdstb, fifo_t_full, fifo_t_empty, fifo_r_wrstb, fifo_r_rdstb, fifo_r_full, fifo_r_empty : std_logic;
|
|
signal fifo_r_din, fifo_r_dout, fifo_t_din, fifo_t_dout : std_logic_vector(7 downto 0);
|
|
begin -- Behavioral
|
|
|
|
kcpsm3_inst : kcpsm3 port map (
|
|
address => kcpsm3_addr,
|
|
instruction => kcpsm3_instr,
|
|
port_id => kcpsm3_portid,
|
|
write_strobe => kcpsm3_wrstb,
|
|
out_port => kcpsm3_outport,
|
|
read_strobe => kcpsm3_rdstb,
|
|
in_port => kcpsm3_inport,
|
|
interrupt => '0',
|
|
interrupt_ack => open,
|
|
reset => '0',
|
|
clk => CLK_16M);
|
|
|
|
prog_inst : uartprog port map (
|
|
address => kcpsm3_addr,
|
|
instruction => kcpsm3_instr,
|
|
clk => CLK_16M);
|
|
|
|
spi_inst : spi port map (
|
|
MISO => SPI_MISO,
|
|
MOSI => SPI_MOSI,
|
|
SCK => SPI_SCK,
|
|
DATA_I => kcpsm3_outport,
|
|
DATA_O => spi_datao,
|
|
START => spi_start,
|
|
BUSY => spi_busy,
|
|
CLK => CLK_16M);
|
|
|
|
spi_start <= '1' when (kcpsm3_wrstb = '1') and (kcpsm3_portid = X"02") else
|
|
'0';
|
|
|
|
spi_iface: process (CLK_16M)
|
|
begin -- process spi_iface
|
|
if rising_edge(CLK_16M) then
|
|
if (kcpsm3_wrstb = '1') then
|
|
if (kcpsm3_portid = X"03") then
|
|
SPI_SS_B <= kcpsm3_outport(0);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
lcd_iface: process (CLK_16M)
|
|
begin -- process lcd_iface
|
|
if rising_edge(CLK_16M) then
|
|
if (kcpsm3_wrstb = '1') then
|
|
if (kcpsm3_portid = X"04") then
|
|
lcdctrl_r <= kcpsm3_outport(2 downto 0);
|
|
elsif kcpsm3_portid = X"05" then
|
|
lcdout_r <= kcpsm3_outport;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process lcd_iface;
|
|
|
|
kcpsm3_inport <= fifo_t_dout when kcpsm3_portid = X"00" else
|
|
"000000" & fifo_t_empty & fifo_r_full when kcpsm3_portid = X"01" else
|
|
spi_datao when kcpsm3_portid = X"02" else
|
|
"0000000" & spi_busy when kcpsm3_portid = X"03" else
|
|
LCD_DB when kcpsm3_portid = X"05" else
|
|
"00000" & lcdctrl_r when kcpsm3_portid = X"04" else
|
|
"000" & ROT_CENTER & BTN_NORTH & BTN_EAST & BTN_SOUTH & BTN_WEST when kcpsm3_portid = X"06" else
|
|
"XXXXXXXX";
|
|
|
|
process (CLK_16M)
|
|
begin
|
|
if rising_edge(CLK_16M) then
|
|
fifo_r_wrstb <= '0';
|
|
fifo_t_rdstb <= '0';
|
|
if (kcpsm3_wrstb = '1') then
|
|
if (kcpsm3_portid = X"00") then
|
|
fifo_r_din <= kcpsm3_outport;
|
|
fifo_r_wrstb <= '1';
|
|
end if;
|
|
elsif (kcpsm3_rdstb = '1') then
|
|
if (kcpsm3_portid = X"00") then
|
|
fifo_t_rdstb <= '1';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
fifo16x8_inst_transmit : fifo16x8 port map (
|
|
DATAIN => fifo_t_din,
|
|
WRITESTB => fifo_t_wrstb,
|
|
DATAOUT => fifo_t_dout,
|
|
READSTB => fifo_t_rdstb,
|
|
CLK => CLK_16M,
|
|
FULL => fifo_t_full,
|
|
EMPTY => fifo_t_empty);
|
|
|
|
fifo16x8_inst_receive : fifo16x8 port map (
|
|
DATAIN => fifo_r_din,
|
|
WRITESTB => fifo_r_wrstb,
|
|
DATAOUT => fifo_r_dout,
|
|
READSTB => fifo_r_rdstb,
|
|
CLK => CLK_16M,
|
|
FULL => fifo_r_full,
|
|
EMPTY => fifo_r_empty);
|
|
|
|
z80bus: process (CLK_16M)
|
|
begin
|
|
if rising_edge(CLK_16M) then
|
|
fifo_r_rdstb <= '0';
|
|
fifo_t_wrstb <= '0';
|
|
if (iorq_old = '1') and (IORQ_n = '0') then
|
|
if ADDR_I = "01" then
|
|
if RD_n = '0' then -- read receiver register
|
|
DATA_O <= fifo_r_dout;
|
|
fifo_r_rdstb <= '1';
|
|
elsif WR_n = '0' then -- transmitter buffer load
|
|
fifo_t_din <= DATA_I;
|
|
fifo_t_wrstb <= '1';
|
|
end if;
|
|
elsif ADDR_I = "10" then
|
|
if RD_n = '0' then -- read status flags
|
|
DATA_O <= not fifo_r_empty & not fifo_t_full & "XX000X"; -- DR, TBRE, x, x, FE, PE, OE, x
|
|
end if;
|
|
end if;
|
|
end if;
|
|
iorq_old <= IORQ_n;
|
|
end if;
|
|
end process;
|
|
|
|
LCD_DB <= lcdout_r when lcdctrl_r(2) = '0' else
|
|
"ZZZZZZZZ";
|
|
LCD_E <= lcdctrl_r(0);
|
|
LCD_RS <= lcdctrl_r(1);
|
|
LCD_RW <= lcdctrl_r(2);
|
|
|
|
DATAFLASH_RST <= '1';
|
|
DATAFLASH_WP <= '1';
|
|
|
|
end Behavioral;
|