Skip to content

Instantly share code, notes, and snippets.

@insom
Created December 15, 2016 02:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save insom/f837035a2034fe94c42bde58ae88ec99 to your computer and use it in GitHub Desktop.
Save insom/f837035a2034fe94c42bde58ae88ec99 to your computer and use it in GitHub Desktop.
VHDL file for my Microcomputer
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
--
-- This defines the actual physical inputs and outputs I'm going to use.
--
entity Microcomputer is
port(
n_reset : in std_logic;
clk : in std_logic;
rxd1 : in std_logic;
txd1 : out std_logic;
leds : out std_logic_vector(7 downto 0)
);
end Microcomputer;
--
-- This section defines signals, where are like the inputs and outputs of the module.
--
architecture struct of Microcomputer is
signal n_WR : std_logic;
signal n_RD : std_logic;
signal cpuAddress : std_logic_vector(15 downto 0);
signal cpuDataOut : std_logic_vector(7 downto 0);
signal cpuDataIn : std_logic_vector(7 downto 0);
signal basRomData : std_logic_vector(7 downto 0);
signal internalRam1DataOut : std_logic_vector(7 downto 0);
signal internalRam2DataOut : std_logic_vector(7 downto 0);
signal interface1DataOut : std_logic_vector(7 downto 0);
signal n_memWR : std_logic :='1';
signal n_memRD : std_logic :='1';
signal n_ioWR : std_logic :='1';
signal n_ioRD : std_logic :='1';
signal n_MREQ : std_logic :='1';
signal n_IORQ : std_logic :='1';
signal n_int1 : std_logic :='1';
signal n_int2 : std_logic :='1';
signal n_internalRam1CS : std_logic :='1';
signal n_internalRam2CS : std_logic :='1';
signal n_basRomCS : std_logic :='1';
signal n_interface1CS : std_logic :='1';
signal n_aaronCS : std_logic :='1';
signal serialClkCount : std_logic_vector(15 downto 0);
signal cpuClkCount : std_logic_vector(5 downto 0);
signal cpuClock : std_logic;
signal serialClock : std_logic;
begin
--
-- These entities are like importing other VHDL modules.
-- The map() section maps the signals listed on _those_ VHDL modules to our
-- own signals or to pins.
--
cpu1 : entity work.t80s
generic map(mode => 1, t2write => 1, iowait => 0)
port map(
reset_n => n_reset,
clk_n => cpuClock,
wait_n => '1',
int_n => '1',
nmi_n => '1',
busrq_n => '1',
mreq_n => n_MREQ,
iorq_n => n_IORQ,
rd_n => n_RD,
wr_n => n_WR,
a => cpuAddress,
di => cpuDataIn,
do => cpuDataOut
);
rom1 : entity work.Z80_BASIC_ROM -- 8KB BASIC
port map(
address => cpuAddress(12 downto 0),
clock => clk,
q => basRomData
);
ram1: entity work.InternalRam4K
port map(
address => cpuAddress(11 downto 0),
clock => clk,
data => cpuDataOut,
wren => not(n_memWR or n_internalRam1CS),
q => internalRam1DataOut
);
io1 : entity work.bufferedUART
port map(
clk => clk,
n_wr => n_interface1CS or n_ioWR,
n_rd => n_interface1CS or n_ioRD,
n_int => n_int1,
regSel => cpuAddress(0),
dataIn => cpuDataOut,
dataOut => interface1DataOut,
rxClock => serialClock,
txClock => serialClock,
rxd => rxd1,
txd => txd1,
n_cts => '0',
n_dcd => '0'
);
io2 : entity work.aaron
port map(
n_wr => n_aaronCS or n_ioWR,
dataIn => cpuDataOut,
dataOut => leds,
reset_n => n_reset
);
n_ioWR <= n_WR or n_IORQ;
n_memWR <= n_WR or n_MREQ;
n_ioRD <= n_RD or n_IORQ;
n_memRD <= n_RD or n_MREQ;
--
-- This section performs the actual address decoding - it will raise or lower
-- the chip select lines of the modules depending on the contents of the address
-- bus.
--
-- These are active low so '0' means "enable this CS line"
n_basRomCS <= '0' when cpuAddress(15 downto 13) = "000" else '1'; -- 8K at bottom of memory
n_internalRam1CS <= '0' when cpuAddress(15 downto 12) = "0010" else '1'; -- 4K above that
n_interface1CS <= '0' when cpuAddress(7 downto 1) = "1000000" and (n_ioWR='0' or n_ioRD = '0') else '1'; -- 2 Bytes $80-$81
n_aaronCS <= '0' when cpuAddress(7 downto 1) = "1001000" and (n_ioWR='0' or n_ioRD = '0') else '1'; -- 2 Bytes $90-$91
-- Connect the CPU and peripheral data lines when the respective CS line is low
cpuDataIn <=
interface1DataOut when n_interface1CS = '0' else
basRomData when n_basRomCS = '0' else
internalRam1DataOut when n_internalRam1CS= '0' else
x"FF";
--
-- This is all to create a secondary, slower, clock for the UART to use.
--
serialClock <= serialClkCount(15);
process (clk)
begin
if rising_edge(clk) then
if cpuClkCount < 4 then -- 4 = 10MHz, 3 = 12.5MHz, 2=16.6MHz, 1=25MHz
cpuClkCount <= cpuClkCount + 1;
else
cpuClkCount <= (others=>'0');
end if;
if cpuClkCount < 2 then -- 2 when 10MHz, 2 when 12.5MHz, 2 when 16.6MHz, 1 when 25MHz
cpuClock <= '0';
else
cpuClock <= '1';
end if;
-- Serial clock DDS
-- 50MHz master input clock:
-- Baud Increment
-- 115200 2416
-- 38400 805
-- 19200 403
-- 9600 201
-- 4800 101
-- 2400 50
serialClkCount <= serialClkCount + 2416;
end if;
end process;
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment