Question

I'm trying to make a grid on the screen using this VHDL. I can make two lines now, but when I refresh the screen, the lines move. I'm not sure where the error is, can someone help or offer any pointers?

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_unsigned.all;
--use IEEE.std_logic_arith.all; --VVVVVVV
use IEEE.NUMERIC_STD.all;       --^^^^^^^ 

entity SCRN is
port(
    clk     : in STD_LOGIC;
    vga     : OUT STD_LOGIC_VECTOR (7 downto 0);
    Hsync : OUT STD_LOGIC;
    Vsync : OUT STD_LOGIC
    );
end SCRN;

architecture Behavioral of SCRN is

type PLC_HOLD is array (1 to 800, 1 to 525) of STD_LOGIC_VECTOR(7 downto 0);
signal scrn : PLC_HOLD;

signal s_clk    : std_logic_vector (1 downto 0) := (others => '0');
signal xx_vga   : std_logic_vector (7 downto 0);

signal xx_h : std_logic;
signal xx_v : std_logic;

signal X : std_logic_vector (9 downto 0) := (others => '1');
signal Y : std_logic_vector (9 downto 0) := (others => '1');

-- signal test : ieee.numeric_std.unsigned 
-- test now works with mod
begin

NW_CLK: process (clk) is
    begin
    if rising_edge (clk) then 
        s_clk <= (s_clk + "01");
    end if;
end process NW_CLK;
--###############################--
scrn_loc : 
process (s_clk(1)) is

begin
    if RISING_EDGE (s_clk(1)) then
    X <= X + "0000000001";
        if (X = "1100100000") then --if x = 800
            X <= "0000000001"; 
            Y <= (Y + "0000000001");
        elsif (Y = 525) then -- if y = 525
            X <= "0000000001"; 
            Y <= "0000000001";
        end if;
    end if;
end process;

--###############################--
draw : 
process (X,Y) is 

    -- h and v sync process
    begin
    if (X > 640) then -- and (X <= 752) then -- low for sync pulse at 656 to 752 -- 96 pixel
        xx_h <= '0';
    else 
        xx_h <= '1';
    end if;

    if (Y> 490) and (Y <= 492) then -- low for sync puls at 490 to 492
        xx_v <= '0';
    else
        xx_v <= '1';
    end if;
--  (CONV_INTEGER((X)) mod 10)
-- CONV_INTEGER(Y) mod 10
--  if  X = 1 then
--      xx_vga <= "00111000";
----    elsif Y = 1 or Y = 480 then
----        xx_vga <= "11101011";
--  else 
--      xx_vga <= "11100000";
--  end if;

end process;
--###############################--


scrn(CONV_INTEGER(X),CONV_INTEGER(Y)) <=    "00111000" when X = 1 else
                                                "11100101" when Y = 2 else
                                                "00000111" when X = 640 else
                                                "11001101";

Hsync <= xx_h;
Vsync <= xx_v;

vga <= scrn(CONV_INTEGER(X),CONV_INTEGER(Y));

end Behavioral;
Was it helpful?

Solution 2

You are creating a clock from a clock, which is a bad idea. It seems you are trying to divide by 4? Instead create an enable pulse:

NW_CLK: process (clk) is
  variable divider : integer range 0 to 3;
    begin
    if rising_edge (clk) then 
        if divider = 3 then
           divider := 0;
           screen_process_enable <= '1';
        else
           divider := divider + 1;
           screen_process_enable <= '0';
        end if
    end if;
end process NW_CLK;

Then in the screen process:

scrn_loc : process (clk) is

begin
    if RISING_EDGE (clk) and screen_process_enable = '1' then
       etc...

Not related to your question, but I'll comment on it here anyway: You seem to be trying to hold the entire screen in memory - that's quite a lot of storage you are asking for in a real chip (it'll be fine in simulation).

For producing a grid you can just do it on the fly, by assigning to the VGA output depending on the values of your x and y counters. Because you have both the assignment to scrn and vga outside of a process, the synthesiser is probably clever enough to figure out that you never make use of the memory storage you've asked for and has optimised it away. If at some future point you come to use scrn as a true framebuffer, you may run up against performance or resource limitations, depending on your device.

OTHER TIPS

Hmmm... What happens if you move the line where you assign to scrn(CONV_INTEGER(X),CONV_INTEGER(Y)) <= "00111000" when X = 1 else ... to somewhere inside your process?

Also there is no need to use binary literals in your code (e.g., if (X = "1100100000")). Just use integer literals, or decimal bit-string literals. Better yet, define all your numeric values as integers or naturals. As a bonus, your code will be cleaner because you won't need all those conversion functions.

Check chapter 15 (VHDL Design of VGA Video Interfaces) of "Circuit Design and Simulation with VHDL", which shows detailed VGA theory followed by a number of experiments using VHDL and VGA monitors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top