297 lines
8.9 KiB
VHDL
297 lines
8.9 KiB
VHDL
|
|
-- written by Robert Sanchez
|
|
|
|
library IEEE;
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
use IEEE.NUMERIC_STD.ALL;
|
|
|
|
|
|
entity gigatron is
|
|
Port (
|
|
sysclk : in std_logic;
|
|
VGA_R : out std_logic_vector(3 downto 0);
|
|
VGA_G : out std_logic_vector(3 downto 0);
|
|
VGA_B : out std_logic_vector(3 downto 0);
|
|
VGA_HS : out std_logic;
|
|
VGA_VS : out std_logic;
|
|
|
|
LED : out std_logic_vector(15 downto 0));
|
|
end gigatron;
|
|
|
|
|
|
-- TRUTH TABLE for A and B ALU operands (BA bit order for input)
|
|
-- LD AR 0011
|
|
-- XOR AR 0110
|
|
-- OR AR 0111
|
|
-- AND AR 0001
|
|
-- SUB AR 1100 (using AL too, NOTE AR0 here also carry-in)
|
|
-- 0101 <-second side of mux
|
|
-- ADD AR 0011 (using AL too)
|
|
-- 0101 <-second side of mux
|
|
|
|
|
|
architecture Behavioral of gigatron is
|
|
|
|
component blk_mem_gen_0
|
|
PORT (
|
|
clka : IN STD_LOGIC;
|
|
ena : IN STD_LOGIC;
|
|
wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
|
|
addra : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
|
|
dina : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
|
|
douta : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
|
|
);
|
|
END component;
|
|
|
|
component blk_mem_gen_1
|
|
PORT (
|
|
clka : IN STD_LOGIC;
|
|
ena : IN STD_LOGIC;
|
|
wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
|
|
addra : IN STD_LOGIC_VECTOR(14 DOWNTO 0);
|
|
dina : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
douta : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
|
|
);
|
|
END component;
|
|
|
|
component clk_wiz_0
|
|
port(
|
|
clk_out1 : out std_logic;
|
|
clk_out2 : out std_logic;
|
|
clk_in1 : in std_logic
|
|
);
|
|
end component;
|
|
|
|
|
|
signal PC : unsigned(15 downto 0) := X"0000";
|
|
signal DR : std_logic_vector(7 downto 0) := X"00";
|
|
signal IR : std_logic_vector(7 downto 0) := X"00";
|
|
|
|
signal AC : std_logic_vector(7 downto 0) := X"00";
|
|
signal Y : std_logic_vector(7 downto 0) := X"00";
|
|
signal X : std_logic_vector(7 downto 0) := X"00";
|
|
signal OUTR : std_logic_vector(7 downto 0) := X"00";
|
|
signal INR : std_logic_vector(7 downto 0) := X"FF";
|
|
signal XOUTR : std_logic_vector(7 downto 0) := X"00";
|
|
|
|
signal DIN : std_logic_vector(15 downto 0);
|
|
signal DOUT : std_logic_vector(15 downto 0);
|
|
|
|
signal RAMDIN : std_logic_vector(7 downto 0);
|
|
signal RAMDOUT : std_logic_vector(7 downto 0);
|
|
|
|
|
|
signal DBUS : std_logic_vector(7 downto 0) := X"00";
|
|
|
|
signal TMP : std_logic_vector(7 downto 0) := X"00";
|
|
signal MAR : std_logic_vector(15 downto 0) := "0000000000000000";
|
|
|
|
signal RAMWE : std_logic_vector(0 downto 0) := "0";
|
|
|
|
signal PCWE : std_logic := '0';
|
|
signal PCNEW : unsigned(15 downto 0) := X"0000";
|
|
|
|
signal fastclk : std_logic;
|
|
signal clk : std_logic;
|
|
|
|
|
|
begin
|
|
|
|
ROM : blk_mem_gen_0 port map(clk, '1', "0", std_logic_vector(PC), DIN, DOUT);
|
|
RAM : blk_mem_gen_1 port map(fastclk, '1', RAMWE, MAR(14 downto 0), RAMDIN, RAMDOUT);
|
|
CLOCK : clk_wiz_0 port map(clk, fastclk, sysclk);
|
|
-- memory address process
|
|
process(DOUT, DR, X, Y)
|
|
begin
|
|
if IR(7 downto 5) = "111" then
|
|
MAR <= "00000000" & DR;
|
|
else
|
|
case (DOUT(4 downto 2)) is
|
|
when "000" =>
|
|
MAR <= "00000000" & DR;
|
|
when "001" =>
|
|
MAR <= "00000000" & X;
|
|
when "010" =>
|
|
MAR <= Y & DR;
|
|
when "011" =>
|
|
MAR <= Y & X;
|
|
when "100" =>
|
|
MAR <= "00000000" & DR;
|
|
when "101" =>
|
|
MAR <= "00000000" & DR;
|
|
when "110" =>
|
|
MAR <= "00000000" & DR;
|
|
when "111" =>
|
|
MAR <= Y & X;
|
|
when others =>
|
|
end case;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
-- data bus value process
|
|
process(DOUT, RAMDOUT, AC, INR)
|
|
begin
|
|
case (DOUT(1 downto 0)) is
|
|
when "00" =>
|
|
DBUS <= DOUT(15 downto 8);
|
|
when "01" =>
|
|
DBUS <= RAMDOUT;
|
|
when "10" =>
|
|
DBUS <= AC;
|
|
when "11" =>
|
|
DBUS <= INR;
|
|
when others =>
|
|
end case;
|
|
end process;
|
|
|
|
|
|
|
|
-- real assignment process (write databus tmp value to destination)
|
|
process(clk)
|
|
begin
|
|
RAMDIN <= TMP;
|
|
|
|
if rising_edge(clk) then
|
|
if (IR(7 downto 5) /= "111") then
|
|
case (IR(4 downto 2)) is
|
|
when "000" =>
|
|
if IR(7 downto 5) /= "110" then
|
|
AC <= TMP;
|
|
end if;
|
|
when "001" =>
|
|
if IR(7 downto 5) /= "110" then
|
|
AC <= TMP;
|
|
end if;
|
|
when "010" =>
|
|
if IR(7 downto 5) /= "110" then
|
|
AC <= TMP;
|
|
end if;
|
|
when "011" =>
|
|
if IR(7 downto 5) /= "110" then
|
|
AC <= TMP;
|
|
end if;
|
|
when "100" => --x
|
|
X <= TMP;
|
|
when "101" => --y
|
|
Y <= TMP;
|
|
when "110" => --out
|
|
if IR(7 downto 5) /= "110" then
|
|
OUTR <= TMP;
|
|
end if;
|
|
when "111" => --out
|
|
if IR(7 downto 5) /= "110" then
|
|
OUTR <= TMP;
|
|
end if;
|
|
X <= std_logic_vector(unsigned(X) + 1);
|
|
when others =>
|
|
if IR(7 downto 5) /= "110" then
|
|
AC <= TMP;
|
|
end if;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-- program counter
|
|
process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
if (PCWE = '1') then
|
|
PC <= PCNEW;
|
|
else
|
|
PC <= PC + 1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process(DOUT)
|
|
begin
|
|
RAMWE <= "0";
|
|
if (DOUT(7 downto 5) = "110") then -- STORE
|
|
RAMWE <= "1";
|
|
end if;
|
|
end process;
|
|
|
|
-- select which value to write to data bus
|
|
process(DBUS,IR)
|
|
begin
|
|
PCWE <= '0';
|
|
|
|
case (IR(7 downto 5)) is
|
|
when "000" => -- LD
|
|
TMP <= DBUS;
|
|
when "001" => -- AND
|
|
TMP <= AC and DBUS;
|
|
when "010" => -- OR
|
|
TMP <= AC or DBUS;
|
|
when "011" => -- XOR
|
|
TMP <= AC xor DBUS;
|
|
when "100" => -- ADD
|
|
TMP <= std_logic_vector(unsigned(AC) + unsigned(DBUS));
|
|
when "101" => -- SUB
|
|
TMP <= std_logic_vector(unsigned(AC) - unsigned(DBUS));
|
|
when "110" => -- STORE
|
|
TMP <= DBUS; --AC;
|
|
when "111" => -- JMP
|
|
case (IR(4 downto 2)) is
|
|
when "000" => -- far jump y, bus
|
|
PCNEW <= unsigned(Y & DBUS);
|
|
PCWE <= '1';
|
|
when "001" =>
|
|
if (signed(AC) > 0) then
|
|
PCNEW <= PC(15 downto 8) & unsigned(DBUS);
|
|
PCWE <= '1';
|
|
end if;
|
|
when "010" =>
|
|
if (signed(AC) < 0) then
|
|
PCNEW <= PC(15 downto 8) & unsigned(DBUS);
|
|
PCWE <= '1';
|
|
end if;
|
|
when "011" =>
|
|
if (signed(AC) /= 0) then
|
|
PCNEW <= PC(15 downto 8) & unsigned(DBUS);
|
|
PCWE <= '1';
|
|
end if;
|
|
when "100" =>
|
|
if (signed(AC) = 0) then
|
|
PCNEW <= PC(15 downto 8) & unsigned(DBUS);
|
|
PCWE <= '1';
|
|
end if;
|
|
when "101" =>
|
|
if (signed(AC) >= 0) then
|
|
PCNEW <= PC(15 downto 8) & unsigned(DBUS);
|
|
PCWE <= '1';
|
|
end if;
|
|
when "110" =>
|
|
if (signed(AC) <= 0) then
|
|
PCNEW <= PC(15 downto 8) & unsigned(DBUS);
|
|
PCWE <= '1';
|
|
end if;
|
|
when "111" =>
|
|
PCNEW <= PC(15 downto 8) & unsigned(DBUS);
|
|
PCWE <= '1';
|
|
when others =>
|
|
end case;
|
|
when others =>
|
|
end case;
|
|
end process;
|
|
|
|
process(OUTR(6))
|
|
begin
|
|
if rising_edge(OUTR(6)) then
|
|
XOUTR <= AC;
|
|
end if;
|
|
end process;
|
|
|
|
DR <= DOUT(15 downto 8);
|
|
IR <= DOUT(7 downto 0);
|
|
VGA_R <= OUTR(1 downto 0) & "00";
|
|
VGA_G <= OUTR(3 downto 2) & "00";
|
|
VGA_B <= OUTR(5 downto 4) & "00";
|
|
VGA_HS <= OUTR(6);
|
|
VGA_VS <= OUTR(7);
|
|
LED(7 downto 0) <= XOUTR(7 downto 0);
|
|
|
|
end Behavioral;
|