library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Fourmi_VGA is
port(
clk : in std_logic;
rst : in std_logic;
H_sync : out std_logic;
V_sync : out std_logic;
sw : in std_logic_vector(7 downto 0);
pixel : out std_logic_vector(11 downto 0)
);
end Fourmi_VGA;
architecture behavioral of Fourmi_VGA is
component VGA_ctrl is
generic( freq_clk: integer :=50000000;
H_sync_polarity: std_logic := '1'; -- Sync polarity - 1 positive, 0 negative
V_sync_polarity: std_logic := '1'; -- Sync polarity - 1 positive, 0 negative
H_Visible: integer :=800; -- nombre de pixels visibles
H_Front_porch: integer :=56; -- nombre de cycles porch
H_Sync_pulse: integer :=120; -- nombre de cycles H_sync
H_Back_porch: integer :=64; -- nombre de cycles porch
V_Visible: integer :=600; -- nombre de lignes visibles
V_Front_porch: integer :=37; -- nombre de lignes porch
V_Sync_pulse: integer :=6; -- nombre de lignes V_sync
V_Back_porch: integer :=23 -- nombre de lignes porch
);
port(
clk : in std_logic; -- clk d'entrée
rst : in std_logic; -- reset
Hcount : out std_logic_vector(12 downto 0); -- Cordonnée du pixel horizontale à afficher
Vcount : out std_logic_vector(12 downto 0); -- Cordonnée du pixel horizontale à afficher
H_sync : out std_logic; -- Signal de synchronization
V_sync : out std_logic; -- Signal de synchronization
blank : out std_logic; -- 0 si pixel visible, 1 si non visible (porch ou sync)
frame : out std_logic
);
end component;
component counter is
generic (
SIZE : integer :=8);
port (
clk : in std_logic;
rst : in std_logic;
enable : in std_logic;
load : in std_logic;
load_value : in std_logic_vector(SIZE-1 downto 0);
max_value : in std_logic_vector(SIZE-1 downto 0);
counter_value : out std_logic_vector(SIZE-1 downto 0)
);
end component;
signal Hcount : std_logic_vector(12 downto 0);
signal Vcount : std_logic_vector(12 downto 0);
signal blank, frame: std_logic;
constant x_size:integer:=512;
constant y_size:integer:=480;
constant x_max:integer:=x_size-1;
constant y_max:integer:=y_size-1;
signal x,y : unsigned(8 downto 0):=to_unsigned(x_max/2,9);
signal next_x : unsigned(8 downto 0);
signal next_y : unsigned(8 downto 0);
type mem is array (0 to (x_size*y_size)-1) of std_logic;
signal grid : mem :=(others =>'1');
signal mem_add:integer;
signal mem_data_out,mem_data_in: std_logic;
signal mem_we : std_logic;
type state_type is (s1, s2, s3, s4);
signal state : state_type := s1;
signal next_state : state_type := state;
signal reset : std_logic;
signal switch : std_logic_vector(7 downto 0);
signal counter_value : std_logic_vector(7 downto 0);
-- Les attributs suivantes vous permettront de debogger vos signaux à l'aide du ILA
ATTRIBUTE MARK_DEBUG : STRING;
ATTRIBUTE MARK_DEBUG OF frame : SIGNAL IS "true";
ATTRIBUTE MARK_DEBUG OF mem_data_in : SIGNAL IS "true";
ATTRIBUTE MARK_DEBUG OF mem_data_out : SIGNAL IS "true";
ATTRIBUTE MARK_DEBUG OF x : SIGNAL IS "true";
ATTRIBUTE MARK_DEBUG OF y : SIGNAL IS "true";
begin
reset <= not rst;
VGA_inst : VGA_ctrl
generic map(25175000, '0', '0', 640, 16, 96, 48, 480, 10, 2, 33)
port map(clk, reset, Hcount, Vcount, H_sync, V_sync, blank, frame);
counter_inst : counter
generic map(8)
port map(clk, reset, '1', '0', (7 downto 0 => '0'), switch, counter_value);
------------- generation des pixels ------------------
process(clk)
begin
if rising_edge(clk) then
if blank = '0' then -- si on est sur la grille
pixel <= (others => mem_data_out); -- affice la mémoire
else
pixel <= (others =>'0');
end if;
end if;
end process;
-------------------- Definition de la mémoire ---------------
mem_add <= to_integer(unsigned(Vcount(8 downto 0))&unsigned(Hcount(8 downto 0))) when blank = '0' else to_integer(y&x);
-- l'adresse est donnée par les cordonées VGA si blank = '0',
-- sinon la position de la fourmis determina l'adresse
process(clk) -- process qui determine l'écriture et lecture de la mémoire
begin
if rising_edge(clk) then --
mem_data_out <= grid(mem_add);
if mem_we = '1' then
grid(mem_add) <= mem_data_in;
end if;
end if;
end process;
mem_we <= '1' when frame = '1' else '0'; -- mise à jour de la mémoire.
mem_data_in <= not mem_data_out; -- mise à jour de la mémoire, ceci devrait vous faire clignoter un pixel (à peine visible)
-- A partir d'ici vous pouvez inclure votre machine d'états et votre compteur.
fsm : process(state)
begin
-- valeurs par défaut pour éviter les latchs
next_state <= state;
next_x <= x;
next_y <= y;
--mem_data_in <= not mem_data_out; -- on inverse toujours la case courante
--if frame = '1' then
if unsigned(counter_value) = unsigned(switch)-1 then
case state is
when s1 =>
if mem_data_out = '1' then
next_state <= s2;
next_x <= x + 1;
else
next_state <= s4;
next_x <= x - 1;
end if;
when s2 =>
if mem_data_out = '1' then
next_state <= s3;
next_y <= y + 1;
else
next_state <= s1;
next_y <= y - 1;
end if;
when s3 =>
if mem_data_out = '1' then
next_state <= s4;
next_x <= x - 1;
else
next_state <= s2;
next_x <= x + 1;
end if;
when s4 =>
if mem_data_out = '1' then
next_state <= s1;
next_y <= y - 1;
else
next_state <= s3;
next_y <= y + 1;
end if;
end case;
end if;
end process;
ctrl : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
state <= s1;
x <= to_unsigned(x_max/2, 9);
y <= to_unsigned(y_max/2, 9);
else
state <= next_state;
x <= next_x;
y <= next_y;
end if;
end if;
end process;
end behavioral;