gigatron/rom/Contrib/fetchingcat/fpga/gigatron.vhd
2025-01-28 19:17:01 +03:00

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;