Files
nascom2_t80/uart.vhd
2009-01-15 19:17:56 +00:00

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;