OpenCores
URL https://opencores.org/ocsvn/am9080_cpu_based_on_microcoded_am29xx_bit-slices/am9080_cpu_based_on_microcoded_am29xx_bit-slices/trunk

Subversion Repositories am9080_cpu_based_on_microcoded_am29xx_bit-slices

[/] [am9080_cpu_based_on_microcoded_am29xx_bit-slices/] [trunk/] [sys9080.vhd] - Rev 8

Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company: @Home
-- Engineer: zpekic@hotmail.com
-- 
-- Create Date: 08/24/2017 11:13:02 PM
-- Design Name: 
-- Module Name: sys9080 - Behavioral
-- Project Name: Simple 8-bit system around microcode implemented Am9080 CPU
-- Target Devices: https://www.micro-nova.com/mercury/ + Baseboard
-- Tool Versions: ISE 14.7 (nt)
-- Description: 
-- 
-- Dependencies: 
-- 
-- Revision:
-- Revision 0.99 - Kinda works...
-- Additional Comments:
-- https://en.wikichip.org/w/images/7/76/An_Emulation_of_the_Am9080A.pdf
----------------------------------------------------------------------------------
 
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
 
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity sys9080 is
    Port ( 
				-- 50MHz on the Mercury board
				CLK: in std_logic;
				-- Master reset button on Mercury board
				USR_BTN: in std_logic; 
				-- Switches on baseboard
				-- SW(1 downto 0) -- LED display selection
				--   0	0  Sys9080 - A(7:0) & D(7:0) & io and memory r/w on dots
				--   0   1  Sys9080 - OUT port 1 & port 0
				--   1   0  Am9080 - microinstruction counter & instruction register
				--   1   1  Am9080 - content of register as defined by SW5:2
				-- SW(5 downto 2) -- 4 bit Am9080 register selector when inspecting register states in SS mode
				-- SW(6 downto 5) -- system clock speed 
				--   0   0	1Hz	(can be used with SS mode)
				--   0   1	1024Hz (can be used with SS mode)
				--   1   0  6.125MHz
				--   1   1  25MHz
				-- SW7
				--   0   single step mode off (BTN3 should be pressed once to start the system)
				--   1   single step mode on (use with BTN3)
				SW: in std_logic_vector(7 downto 0); 
				-- Push buttons on baseboard
				-- BTN0 - generate RST 7 interrupt which will dump processor regs and memory they are pointing to over ACIA0
				-- BTN1 - bypass ACIA Rx char input processing and dump received bytes and status to ACIA0
				-- BTN2 - put processor into HOLD mode
				-- BTN3 - single step clock cycle forward if in SS mode (NOTE: single press on this button is needed after reset to unlock SS circuit)
				BTN: in std_logic_vector(3 downto 0); 
				-- Stereo audio output on baseboard
				--AUDIO_OUT_L, AUDIO_OUT_R: out std_logic;
				-- 7seg LED on baseboard 
				A_TO_G: out std_logic_vector(6 downto 0); 
				AN: out std_logic_vector(3 downto 0); 
				DOT: out std_logic; 
				-- 4 LEDs on Mercury board
				LED: out std_logic_vector(3 downto 0);
				-- ADC interface
				--ADC_MISO: in std_logic;
				--ADC_MOSI: out std_logic;
				--ADC_SCK: out std_logic;
				--ADC_CSN: out std_logic;
				--PMOD interface (for hex keypad)
				PMOD: inout std_logic_vector(7 downto 0)
 
          );
end sys9080;
 
architecture Structural of sys9080 is
 
component clock_divider is
    Port ( reset : in  STD_LOGIC;
           clock : in  STD_LOGIC;
           slow : out  STD_LOGIC_VECTOR (11 downto 0);
           fast : out  STD_LOGIC_VECTOR (3 downto 0)
			 );
end component;
 
component clocksinglestepper is
    Port ( reset : in STD_LOGIC;
           clock0_in : in STD_LOGIC;
           clock1_in : in STD_LOGIC;
           clock2_in : in STD_LOGIC;
           clock3_in : in STD_LOGIC;
           clocksel : in STD_LOGIC_VECTOR(1 downto 0);
           modesel : in STD_LOGIC;
           singlestep : in STD_LOGIC;
           clock_out : out STD_LOGIC);
end component;
 
component counter16bit is
    Port ( reset : in STD_LOGIC;
           clk : in STD_LOGIC;
           mode : in STD_LOGIC_VECTOR (1 downto 0);
           d : in STD_LOGIC_VECTOR (31 downto 0);
           q : out STD_LOGIC_VECTOR (31 downto 0));
end component;
 
component debouncer8channel is
    Port ( clock : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           signal_raw : in  STD_LOGIC_VECTOR(7 downto 0);
           signal_debounced : out  STD_LOGIC_VECTOR(7 downto 0));
end component;
 
component fourdigitsevensegled is
    Port ( -- inputs
			  data : in  STD_LOGIC_VECTOR (15 downto 0);
           digsel : in  STD_LOGIC_VECTOR (1 downto 0);
           showdigit : in  STD_LOGIC_VECTOR (3 downto 0);
           showdot : in  STD_LOGIC_VECTOR (3 downto 0);
           showsegments : in  STD_LOGIC;
			  -- outputs
           anode : out  STD_LOGIC_VECTOR (3 downto 0);
           segment : out  STD_LOGIC_VECTOR (7 downto 0)
			 );
end component;
 
component simpledevice is 
		Port(
           clk : in STD_LOGIC;
           reset: in STD_LOGIC;
			  D: inout STD_LOGIC_VECTOR(7 downto 0);
			  A: in STD_LOGIC_VECTOR(3 downto 0);
           nRead: in STD_LOGIC;
           nWrite: in STD_LOGIC;
			  IntReq: out STD_LOGIC;
			  IntAck: in STD_LOGIC;			  
			  nSelect: in STD_LOGIC;
			  direct_in: in STD_LOGIC_VECTOR(15 downto 0);
			  direct_out: out STD_LOGIC_VECTOR(15 downto 0)
			);
end component;
 
component ACIA is 
		Port(
           clk : in STD_LOGIC;
           reset: in STD_LOGIC;
			  D: inout STD_LOGIC_VECTOR(7 downto 0);
			  A: in STD_LOGIC;
           nRead: in STD_LOGIC;
           nWrite: in STD_LOGIC;
			  nSelect: in STD_LOGIC;
			  IntReq: out STD_LOGIC;
			  IntAck: in STD_LOGIC;
			  txd: out STD_LOGIC;
			  rxd: in STD_LOGIC		  
			);
end component;
 
component simpleram is
	 generic (
		address_size: integer;
		default_value: STD_LOGIC_VECTOR(7 downto 0)
	  );
    Port (       
			  clk: in STD_LOGIC;
			  D : inout  STD_LOGIC_VECTOR (7 downto 0);
           A : in  STD_LOGIC_VECTOR ((address_size - 1) downto 0);
           nRead : in  STD_LOGIC;
           nWrite : in  STD_LOGIC;
           nSelect : in  STD_LOGIC);
end component;
 
component hexfilerom is
	 Generic (
			filename: string;
			address_size: integer;
			default_value: STD_LOGIC_VECTOR(7 downto 0)
		);
    Port (           
			  D : out  STD_LOGIC_VECTOR (7 downto 0);
           A : in  STD_LOGIC_VECTOR ((address_size - 1) downto 0);
           nRead : in  STD_LOGIC;
           nSelect : in  STD_LOGIC
			 );
end component;
 
component interrupt_controller is
    Port ( CLK : in  STD_LOGIC;
           nRESET : in  STD_LOGIC;
           INT : out  STD_LOGIC;
           nINTA : in  STD_LOGIC;
           INTE : in  STD_LOGIC;
           D : out  STD_LOGIC_VECTOR (7 downto 0);
           DEVICEREQ : in  STD_LOGIC_VECTOR (7 downto 0);
           DEVICEACK : out  STD_LOGIC_VECTOR (7 downto 0));
end component;
 
component Am9080a is
    Port ( DBUS : inout  STD_LOGIC_VECTOR (7 downto 0);
			  ABUS : out STD_LOGIC_VECTOR (15 downto 0);
           WAITOUT : out  STD_LOGIC;
           nINTA : out  STD_LOGIC;
           nIOR : out  STD_LOGIC;
           nIOW : out  STD_LOGIC;
           nMEMR : out  STD_LOGIC;
           nMEMW : out  STD_LOGIC;
           HLDA : out  STD_LOGIC;
			  INTE : out STD_LOGIC;
           CLK : in  STD_LOGIC;
           nRESET : in  STD_LOGIC;
			  INT: in STD_LOGIC;
			  READY: in STD_LOGIC;
			  HOLD: in STD_LOGIC;
			  -- debug port, not part of actual processor
           debug_ena : in  STD_LOGIC;
           debug_sel : in  STD_LOGIC;
           debug_out : out  STD_LOGIC_VECTOR (19 downto 0);
			  debug_reg : in STD_LOGIC_VECTOR(3 downto 0)
			);
end component;
 
--component ila_0 IS
--    PORT (
--        clk : IN STD_LOGIC;
--        probe0 : IN STD_LOGIC_VECTOR(5 DOWNTO 0);
--        probe1 : IN STD_LOGIC_VECTOR(0 DOWNTO 0));
--end component;
 
component vio_0 IS
PORT (
clk : IN STD_LOGIC;
probe_in0 : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
probe_in1 : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
probe_in2 : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
probe_in3 : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
probe_out0 : OUT STD_LOGIC_VECTOR(23 DOWNTO 0);
probe_out1 : OUT STD_LOGIC_VECTOR(23 DOWNTO 0);
probe_out2 : OUT STD_LOGIC_VECTOR(23 DOWNTO 0);
probe_out3 : OUT STD_LOGIC_VECTOR(23 DOWNTO 0)
);
END component;
 
-- CPU buses
signal data_bus: std_logic_vector(7 downto 0);
signal address_bus: std_logic_vector(15 downto 0);
signal Reset, nReset: std_logic;
signal clock_main: std_logic;
signal nIORead, nIOWrite, nMemRead, nMemWrite: std_logic;
signal IntReq, nIntAck, Hold, HoldAck, IntE: std_logic;
 
-- other signals
signal reset_delay: std_logic_vector(3 downto 0);
signal DeviceReq: std_logic_vector(7 downto 0);
signal DeviceAck: std_logic_vector(7 downto 0);
signal switch: std_logic_vector(7 downto 0);
signal button: std_logic_vector(7 downto 0);
--signal cnt: std_logic_vector(31 downto 0);
signal io_output: std_logic_vector(15 downto 0);
signal led_bus: std_logic_vector(19 downto 0);
signal cpu_debug_bus, sys_debug_bus: std_logic_vector(19 downto 0);
signal nIoEnable, nACIA0Enable, nACIA1Enable, nBootRomEnable, nMonRomEnable, nRamEnable: std_logic;
signal readwritesignals: std_logic_vector(4 downto 0);
signal showsegments: std_logic;
signal flash: std_logic;
signal freq2k, freq1k, freq512, freq256, freq128, freq64, freq32, freq16, freq8, freq4, freq2, freq1: std_logic;
signal freq25M, freq12M5, freq6M25, freq3M125: std_logic;
 
begin
 
	 Reset <= USR_BTN;
	 nReset <= '0' when (Reset = '1') or (reset_delay /= "0000") else '1'; 
 
	 led_bus <= cpu_debug_bus when (switch(1) = '1') else sys_debug_bus;
	 sys_debug_bus <= readwritesignals(4 downto 1) & address_bus(7 downto 0) & data_bus when (switch(0) = '0') else "0000" & io_output;
 
	 readwritesignals <= (not nIORead) & (not nIOWrite) & (not nMemRead) & (not nMemWrite) & (not nIntAck);
	 showsegments <= '0' when (switch(1 downto 0) = "00" and readwritesignals = "00000") else '1';
 
	 Hold <= button(2);
	 flash <= HoldAck or freq2; -- blink in hold bus mode!
	 -- DISPLAY
	 LED(3) <= nIntAck;  
	 LED(2) <= IntReq;  
	 LED(1) <= HoldAck; 
	 LED(0) <= clock_main;  
    led4x7: fourdigitsevensegled port map ( 
			  -- inputs
			  data => led_bus(15 downto 0),
           digsel(1) => freq1k,
			  digsel(0) => freq2k,
           showdigit(3) => flash,
           showdigit(2) => flash,
           showdigit(1) => flash,
           showdigit(0) => flash,
           showdot => led_bus(19 downto 16),
           showsegments => showsegments,
			  -- outputs
           anode => AN,
           segment(6 downto 0) => A_TO_G(6 downto 0),
			  segment(7) => DOT
			 );
 
    -- FREQUENCY GENERATOR
    one_sec: clock_divider port map 
    (
        clock => CLK,
        reset => Reset,
        slow(11) => freq1, -- 1Hz
        slow(10) => freq2, -- 2Hz
        slow(9) => freq4, -- 4Hz
        slow(8) => freq8, -- 8Hz
        slow(7) => freq16,  -- 16Hz
        slow(6) => freq32,  -- 32Hz
        slow(5) => freq64,  -- 64Hz
        slow(4) => freq128,  -- 128Hz
        slow(3) => freq256,  -- 256Hz
        slow(2) => freq512,  -- 512Hz
        slow(1) => freq1k,  -- 1024Hz
        slow(0) => freq2k,  -- 2048Hz
		  fast(3) => freq3M125,
		  fast(2) => freq6M25,
		  fast(1) => freq12M5,
		  fast(0) => freq25M
    );
 
	-- DEBOUNCE the 8 switches and 4 buttons
    debouncer_sw: debouncer8channel port map (
        clock => freq128,
        reset => Reset,
        signal_raw => SW,
        signal_debounced => switch
    );
 
    debouncer_btn: debouncer8channel port map (
        clock => freq128,
        reset => Reset,
        signal_raw(7 downto 4) => "1111",
        signal_raw(3 downto 0) => BTN(3 downto 0),
        signal_debounced => button
    );
 
	-- Hook up buttons to generate interrupts
	irq7: process(nReset, button(0), deviceack(7))
	begin
		if (nReset = '0' or deviceack(7) = '1') then
			devicereq(7) <= '0';
		else
			if (rising_edge(button(0))) then
				devicereq(7) <= '1';
			end if;
		end if;
	end process;
 
	irq6: process(nReset, button(1), deviceack(6))
	begin
		if (nReset = '0' or deviceack(6) = '1') then
			devicereq(6) <= '0';
		else
			if (rising_edge(button(1))) then
				devicereq(6) <= '1';
			end if;
		end if;
	end process;	
 
	-- delay to generate nReset 4 cycles after reset
	generate_nReset: process (clock_main, Reset)
	begin
		if (Reset = '1') then
			reset_delay <= "1111";
		else
			if (rising_edge(clock_main)) then
				reset_delay <= reset_delay(2 downto 0) & Reset;
			end if;
		end if;
	end process;
 
	-- Single step by each clock cycle, slow or fast
	ss: clocksinglestepper port map (
        reset => Reset,
        clock0_in => freq2,
        clock1_in => freq2k,
        clock2_in => freq3M125,
        clock3_in => freq25M,
        clocksel => switch(6 downto 5),
        modesel => switch(7),
        singlestep => button(3),
        clock_out => clock_main
    );
 
--	ila_ss: ila_0 port map (
--            clk => CLK,
--            probe0(5) => RESET,
--            probe0(4) => button(3),
--            probe0(3) => switch(3),
--            probe0(2) => switch(2),
--            probe0(1) => freq2k,
--            probe0(0) => freq1,
--            probe1(0) => clock_main
--    );
 
	nIoEnable <= (nIoRead and nIoWrite) when address_bus(7 downto 4) = "0000" else '1'; 		-- 0x00 - 0x0F
	nACIA0Enable <= (nIoRead and nIoWrite) when address_bus(7 downto 1) = "0001000" else '1'; -- 0x10 - 0x11
	nACIA1Enable <= (nIoRead and nIoWrite) when address_bus(7 downto 1) = "0001001" else '1'; -- 0x12 - 0x13
	nBootRomEnable <= nMemRead when address_bus(15 downto 10) = "000000" else '1'; -- 1k ROM (0000 - 03FF)
	nMonRomEnable <= nMemRead when address_bus(15 downto 10)  = "000001" else '1'; -- 1k ROM (0400 - 07FF)
	nRamEnable <= (nMemRead and nMemWrite) when address_bus(15 downto 8) = "11111111" else '1'; -- 256b RAM (FF00 - FFFF)
 
	iodevice: simpledevice port map(
			  clk => CLK, -- this is the full 50MHz clock!
			  reset => Reset,
			  D => data_bus,
			  A => address_bus(3 downto 0),
           nRead => nIORead,
           nWrite => nIOWrite,
			  nSelect => nIoEnable,
			  IntReq => open,
			  IntAck => '1',
			  direct_in(7 downto 0) => switch,
			  direct_in(15 downto 8) => button,
			  direct_out => io_output
	);
 
	acia0: ACIA port map(
			  clk => CLK, -- this is the full 50MHz clock!
			  reset => Reset,
			  D => data_bus,
			  A => address_bus(0),
           nRead => nIORead,
           nWrite => nIOWrite,
			  nSelect => nAcia0Enable,
			  IntReq => DeviceReq(5),
			  IntAck => DeviceAck(5),
			  txd => PMOD(0),
			  rxd => PMOD(1)				  
	);
 
	acia1: ACIA port map(
			  clk => CLK, -- this is the full 50MHz clock!
			  reset => Reset,
			  D => data_bus,
			  A => address_bus(0),
           nRead => nIORead,
           nWrite => nIOWrite,
			  nSelect => nAcia1Enable,
			  IntReq => DeviceReq(4),
			  IntAck => DeviceAck(4),
			  txd => PMOD(2),
			  rxd => PMOD(3)				  
	);
 
	bootrom: hexfilerom 
		generic map(
			filename => "./prog/zout/boot.hex",
			address_size => 10,
			default_value => X"FF" -- if executed, will be RST 7
			)	
		port map(
			  D => data_bus,
			  A => address_bus(9 downto 0),
           nRead => nMemRead,
			  nSelect => nBootRomEnable
		);
 
	monrom: hexfilerom 
		generic map(
			filename => "./prog/zout/altmon.hex",
			address_size => 10,
			default_value => X"FF" -- if executed, will be RST 7
			)	
		port map(
			  D => data_bus,
			  A => address_bus(9 downto 0),
           nRead => nMemRead,
			  nSelect => nMonRomEnable
		);
 
	ram: simpleram 
		generic map(
			address_size => 8,
			default_value => X"FF" -- if executed, will be RST 7
			)	
		port map(
			  clk => clock_main,
			  D => data_bus,
			  A => address_bus(7 downto 0),
           nRead => nMemRead,
			  nWrite => nMemWrite,
			  nSelect => nRamEnable
		);
 
	ic: interrupt_controller Port map ( 
			CLK => CLK, -- this is the full 50MHz clock!
			nRESET => nReset,
			INT => IntReq,
		   nINTA => nIntAck,
		   INTE => IntE,
			D => data_bus,
		   DEVICEREQ(7) => devicereq(7), -- button 0
		   DEVICEREQ(6) => devicereq(6), -- button 1
		   DEVICEREQ(5) => devicereq(5), -- ACIA 0
		   DEVICEREQ(4) => '0', --devicereq(4), -- ACIA 1 $BUGBUG - interrupt req stuck for ACIA1?
		   DEVICEREQ(3) => '0',
		   DEVICEREQ(2) => '0',
		   DEVICEREQ(1) => '0',
		   DEVICEREQ(0) => '0',
			DEVICEACK => DeviceAck
		);
 
	cpu: Am9080a port map (
			  DBUS => data_bus,
			  ABUS => address_bus,
           WAITOUT => open,
           nINTA => nIntAck,
           nIOR => nIORead,
           nIOW => nIOWrite,
           nMEMR => nMemRead,
           nMEMW => nMemWrite,
           HLDA => HoldAck,
			  INTE => IntE,
           CLK => clock_main,
           nRESET => nReset,
			  INT => IntReq,
			  READY => '1', -- TODO - use to implement single stepping per instruction, not cycle
			  HOLD => Hold, 
			  -- debug port, not part of actual processor
			  debug_ena => switch(1),
           debug_sel => switch(0),
           debug_out => cpu_debug_bus,
			  debug_reg => switch(5 downto 2)
			);
 
end;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.