You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

341 lines
11 KiB

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library WORK;
use WORK.fontROM.ALL;
entity toplevel is
Port ( port_id : out std_logic_vector(7 downto 0); --solo para depurar
write_strobe : out std_logic; --solo para depurar
read_strobe : out std_logic; --solo para depurar
out_port : out std_logic_vector(7 downto 0); --solo para depurar
in_port : out std_logic_vector(7 downto 0); --solo para depurar
reset : in std_logic;
clk : in std_logic;
-- Eliminamos. Interrupt en RX interrupt : in std_logic;
rx : in std_logic;
tx : out std_logic;
LED : out std_logic; --led de comprobacion y reset
-- Cosas del VGA
R,G,B : out std_logic;
H,V : out std_logic);
end toplevel ;
architecture behavioral of toplevel is
----------------------------------------------------------------
-- declaracion del picoblaze
----------------------------------------------------------------
component picoblaze
Port ( address : out std_logic_vector(7 downto 0);
instruction : in std_logic_vector(15 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;
reset : in std_logic;
clk : in std_logic);
end component;
-----------------------------------------------------------------
-- declaracin de la ROM de programa
-----------------------------------------------------------------
component programa_helloworld_int
Port ( address : in std_logic_vector(7 downto 0);
dout : out std_logic_vector(15 downto 0);
clk : in std_logic);
end component;
-----------------------------------------------------------------
-- Signals usadas para conectar el picoblaze y la ROM de programa
-----------------------------------------------------------------
signal address : std_logic_vector(7 downto 0);
signal instruction : std_logic_vector(15 downto 0);
-----------------------------------------------------------------
-- Signals para debugging
-----------------------------------------------------------------
signal readstrobe: std_logic;
signal writestrobe: std_logic;
signal portid: std_logic_vector(7 downto 0);
signal inport: std_logic_vector(7 downto 0);
signal outport: std_logic_vector(7 downto 0);
signal picoint: std_logic;
-- Declaramos la RAM. Van a ser 64 vectores de 8 bits
-- FF -> UART
-- 0 a 63 -> RAM
type ram_type is array (0 to 63) of std_logic_vector (7 downto 0);
signal RAM : ram_type := (
x"0A", x"0D", x"2A", x"20", x"48", x"45", x"4C", x"4C",
x"4F", x"20", x"49", x"27", x"4D", x"20", x"41", x"4C",
x"49", x"56", x"45", x"21", x"20", x"3A", x"2D", x"44",
x"20", x"2A", x"0A", x"0D", x"2A", x"20", x"50", x"52",
x"45", x"53", x"53", x"20", x"41", x"4E", x"59", x"20",
x"4B", x"45", x"59", x"20", x"54", x"4F", x"20", x"43",
x"4F", x"4E", x"54", x"49", x"4E", x"55", x"45", x"20",
x"2A", x"0A", x"0D", x"00", x"00", x"00", x"00", x"00" );
-- Declaramos las salidas de RAM y de RX
signal rxbuff_out,RAM_out: std_logic_vector(7 downto 0);
-- VGA signals
signal x, y : std_logic_vector(9 downto 0);
signal ready : std_logic;
signal xCount, yCount : integer;
-- ROM COLOR
constant BLACK : std_logic_vector(2 downto 0) := "000";
constant BLUE : std_logic_vector(2 downto 0) := "001";
constant GREEN : std_logic_vector(2 downto 0) := "010";
constant CYAN : std_logic_vector(2 downto 0) := "011";
constant RED : std_logic_vector(2 downto 0) := "100";
constant MAGENTA: std_logic_vector(2 downto 0) := "101";
constant YELLOW: std_logic_vector(2 downto 0) := "110";
constant WHITE: std_logic_vector(2 downto 0) := "111";
-- ROM WORDS
type words_rom_type is array (0 to 22) of integer;
constant WORDS_ROM : words_rom_type :=
(80, 114, 111, 102, 101, 115, 111, 114, 32, 113, 117, 101, 114, 101, 109, 111, 115, 32, 117, 110, 32, 49, 48);
-- cubo que se mueve por teclado
signal cube_x_min : integer := 300;
signal cube_x_max : integer := 340;
signal cube_y_min : integer := 220;
signal cube_y_max : integer := 260;
-- fontROM signals
constant font_ROM : font_rom_type := ROM;
-- Signal vga register
signal vga_reg :std_logic_vector(7 downto 0) := "00000000";
-- Aadimos el controlador de VGA
component controllerVGA
port (
clk : in std_logic;
hsync, vsync : out std_logic;
ready : out std_logic;
x : out std_logic_vector(9 downto 0);
y : out std_logic_vector(9 downto 0)
);
end component;
begin
LED <= reset; -- para comprobar la programacion encendemos
-- un led cada vez que reseteamos
read_strobe <= readstrobe;
write_strobe <= writestrobe;
port_id <= portid;
in_port <= inport;
out_port <= outport;
picoint <= NOT rx; -- La seal de inicio de RX es un 0.
-- Metemos un 1 al pico cuando recibimos.
processor: picoblaze
port map( address => address,
instruction => instruction,
port_id => portid,
write_strobe => writestrobe,
out_port => outport,
read_strobe => readstrobe,
in_port => inport,
interrupt => picoint,
reset => reset,
clk => clk);
program: programa_helloworld_int
port map( address => address,
dout => instruction,
clk => clk);
vga:controllerVGA
port map( clk => clk,
hsync => H,
vsync => V,
ready => ready,
x => x, -- X es la cuenta de la posicion
y => y); -- Y es la cuenta de la posicion
-- Cambiamos a unsigned para poder hacer comparaciones dentro de los procesos
xCount <= to_integer(unsigned(x));
yCount <= to_integer(unsigned(y));
process(clk,reset)
-- Variable para los colores. CARGA INSTANTANEA DEL VALOR, SOLO PARA USO TEMPORAL!!
variable RGB : std_logic_vector(2 downto 0);
variable clock_25 : std_logic := '0';
variable x : integer;
variable y : integer;
variable rowData : std_logic_vector(0 to 7) := (others => '0');
variable terminal_column : integer := 0;
variable terminal_row : integer := 0;
variable char_start_x : integer := 0;
variable char_end_x : integer := 0;
variable char_start_y : integer := 0;
variable char_end_y : integer := 0;
variable border_width : integer := 2;
begin
if rising_edge(clk) then
if reset = '1' then
RGB := BLACK;
clock_25 := '0';
else
if clock_25 = '1' then
-- Si estamos dentro del rango de display y la pantalla esta lista para sacar cosas
if (ready = '1' AND xCount >= 0 AND xCount < 640 AND yCount >= 0 AND yCount < 480) then
-- ## LO QUE EJECUTAMOS EN CADA FRAME ## --
-- Default color como black
--RGB := BLACK;
if xCount < border_width * 8 OR xCount > 639 - (border_width * 8) OR
yCount < (border_width * 8) OR yCount > 479 - (border_width * 8) then
RGB := BLUE;
elsif(xCount>=cube_x_min AND xCount<cube_x_max AND
yCount>=cube_y_min AND yCount<cube_y_max) then
RGB := GREEN;
else
RGB := RED;
end if;
-- Get nearest valid char position using magic division/multiplication decimal crush
terminal_column := xCount / 8 ;
char_start_x := terminal_column * 8;
char_end_x := char_start_x + 8;
terminal_row := yCount / 16;
char_start_y := terminal_row * 16;
char_end_y := char_start_y + 16;
if xCount >= char_start_x AND xCount < char_end_x AND yCount >= char_start_y AND yCount < char_end_y
AND terminal_column < (WORDS_ROM'LENGTH + border_width)
AND terminal_column > border_width - 1 AND terminal_column < 80 - border_width
AND terminal_row > border_width - 2 AND terminal_row <= 30 - border_width then
x := (xCount - char_start_x) mod 8;
y := (yCount - char_start_y) mod 16;
--addrA <= y+16*1;
--rowData := dataOutA;
rowData := font_ROM(y + 16 * WORDS_ROM(terminal_column - border_width));
if rowData(x) = '1' then
RGB := WHITE;
end if;
end if;
-- Sacamos los colores por los puertos de la FPGA
R <= RGB(2);
G <= RGB(1);
B <= RGB(0);
end if;
end if;
clock_25 := NOT clock_25;
end if;
end if;
end process;
--registra el bit tx del puerto de salida, por si ste cambia
-- Usamos el puerto FF para el UART.
txbuff:process(reset, clk)
begin
if (reset='1') then
tx <= '1';
elsif rising_edge(clk) then
if (writestrobe = '1' and portid=x"FF") then
tx <= outport(0);
end if;
end if;
end process;
--aade 7ceros a rx para meterlos al puerto de entrada cuando se lea
-- Usamos el puerto FF para el UART.
rxbuff:process(reset, clk)
begin
if (reset='1') then
rxbuff_out <= (others=>'1');
elsif rising_edge(clk) then
if (readstrobe = '1' and portid=x"FF") then
rxbuff_out <= rx & "0000000";
end if;
end if;
end process;
-- Proceso mover cubo
vgabuff:process(reset, clk)
begin
if (reset='1') then
vga_reg <= "00000000";
elsif rising_edge(clk) then
if (writestrobe = '1' and portid=x"FE") then
vga_reg <= outport;
case outport is
when x"64" =>
-- Recibimos ascii d
-- Movemos derecha
cube_x_min <= cube_x_min+10;
cube_x_max <= cube_x_max+10;
cube_y_min <= cube_y_min;
cube_y_max <= cube_y_max;
when x"61" =>
-- Recibimos ascii a
-- Movemos izquierda
cube_x_min <= cube_x_min-10;
cube_x_max <= cube_x_max-10;
cube_y_min <= cube_y_min;
cube_y_max <= cube_y_max;
when x"77" =>
-- Recibimos ascii w
-- Movemos arriba
cube_x_min <= cube_x_min;
cube_x_max <= cube_x_max;
cube_y_min <= cube_y_min-10;
cube_y_max <= cube_y_max-10;
when x"73" =>
-- Recibimos ascii s
-- Movemos abajo
cube_x_min <= cube_x_min;
cube_x_max <= cube_x_max;
cube_y_min <= cube_y_min+10;
cube_y_max <= cube_y_max+10;
when others =>
cube_x_min <= cube_x_min;
cube_x_max <= cube_x_max;
cube_y_min <= cube_y_min;
cube_y_max <= cube_y_max;
end case;
end if;
end if;
end process;
-- Memoria RAM. Tipo => Escritura sincrona/Lectura asincrona
process(clk)
begin
if(clk'event and clk = '1') then
if(writestrobe = '1' and portid<x"40") then
RAM(to_integer(unsigned(portid))) <= outport;
end if;
end if;
end process;
-- Lectura asincrona, limitada solo por el valor de portid
process(portid)
begin
if(portid<x"40") then
RAM_out <= RAM(to_integer(unsigned(portid)));
end if;
end process;
-- Multiplexor inport
inport <= RAM_out when (readstrobe = '1' and portid<x"40") else
rxbuff_out when (readstrobe = '1' and portid=x"FF") else
x"00";
end behavioral;