Question

Hello,

First of all, I'm a beginner. I'd like to use my zybo board to print a simple image on a screen using the VGA port. I looked for some tutorials, but either they are all working on older version of Vivado (mine is 2016.4), therefore the vhdl file have compatibility problems, or they are not so clear about how to actually configure the board to use the VGA. I really just want to do something simple, like printing a static ball on the screen...

Can somebody help me to understand how to do this?

Gianluca

Share this post


Link to post
Share on other sites

9 answers to this question

Recommended Posts

  • 0

@s224071

First, VHDL files should work the same regardless of the version of Vivado, usually version problems come from when you are using IP cores.

If you write your own controller, there are several things to take note of: The Zybo master XDC file, found in the sidebar of this page under "design resources", will have a number of pins to control the VGA connector, they are found at the very bottom of the file. The timings for these pins can be found in this project's description. I highly recommend reading that entire page. In order to display different images on the screen, you will need to modify the "At Display Area" comparator, as well as the color selection mux.

Hope this helps,

Arthur

Share this post


Link to post
Share on other sites
  • 0
10 hours ago, jpeyron said:

Hi @s224071,

Here is a good tutorial at the fpga4fun website. Also i have attached a zybo vga project in vhdl(more complex than static box) that is made in Vivado 2016.4.

cheers,

Jon

ZyBo_VGA.zip

Hi @jpeyron,

about the project you posted, I need to open it in the sdk launcher or I can directly add the bitstream to my zybo to make it work? Because opening it in vivado and trying to export the hardware, I got the following message (attachment 1).

I've also tried to open the project in ISE 14.7, but when generating the bitstream I had this result(attachment 2).

1.png

2.png

Share this post


Link to post
Share on other sites
  • 0

Hi @s224071,

This is a vhdl design that uses the clock wizard to generate the different clocks you can use based on the resolution. There is no microblaze/zynq processor in the design. This design does not use SDK. Once you generate a bitstream you open the hardware manager and program the zybo from there. You should look at the vhdl file to better understand what is going on. You can uncomment/comment out different lines of code to get different resolutions.

cheers,

Jon 

Share this post


Link to post
Share on other sites
  • 0

Hi @jpeyron @artvvb

I'm using zybo zynq -7000 board https://store.digilentinc.com/zybo-zynq-7000-arm-fpga-soc-trainer-board/

And design VGA controller (640*480@60Hz) on vivado 2018.2 using verilog.

I determine the clock divider value as

Clock_divider_value = (board_freq / 2*pixel_clock) - 1

I'm getting "out of range" error on monitor.

By the mention formula my clock_divider value came to be 2.5 so i use 2 instead as my board freq is 125MHz. And 25MHz is pixel clock with given resolution.

So I'm not able to calculate the pixel_clock/ clock_divider_value, hence getting out of range error

Please help me in this

 

Share this post


Link to post
Share on other sites
  • 0

Hi @Mukul,

Here is a VHDL VGA project that has pixel clock frequencies for multiple resolutions.

Spoiler

----------------------------------------------------------------------------------

-- Company: Digilent

-- Engineer: Arthur Brown

--

--

-- Create Date: 13:01:51 02/15/2013

-- Project Name: pmodvga

-- Target Devices: arty

-- Tool versions: 2016.4

-- Additional Comments:

--

-- Copyright Digilent 2017

----------------------------------------------------------------------------------

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.std_logic_unsigned.all;

-- Uncomment the following library declaration if using

-- arithmetic functions with Signed or Unsigned values

--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating

-- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity top is

Port ( CLK_I : in STD_LOGIC;

VGA_HS_O : out STD_LOGIC;

VGA_VS_O : out STD_LOGIC;

VGA_R : out STD_LOGIC_VECTOR (3 downto 0);

VGA_B : out STD_LOGIC_VECTOR (3 downto 0);

VGA_G : out STD_LOGIC_VECTOR (3 downto 0));

end top;

architecture Behavioral of top is

component clk_wiz_0

port

(-- Clock in ports

CLK_IN1 : in std_logic;

-- Clock out ports

CLK_OUT1 : out std_logic

);

end component;

--Sync Generation constants

----***640x480@60Hz***-- Requires 25 MHz clock

--constant FRAME_WIDTH : natural := 640;

--constant FRAME_HEIGHT : natural := 480;

--constant H_FP : natural := 16; --H front porch width (pixels)

--constant H_PW : natural := 96; --H sync pulse width (pixels)

--constant H_MAX : natural := 800; --H total period (pixels)

--constant V_FP : natural := 10; --V front porch width (lines)

--constant V_PW : natural := 2; --V sync pulse width (lines)

--constant V_MAX : natural := 525; --V total period (lines)

--constant H_POL : std_logic := '0';

--constant V_POL : std_logic := '0';

----***800x600@60Hz***-- Requires 40 MHz clock

--constant FRAME_WIDTH : natural := 800;

--constant FRAME_HEIGHT : natural := 600;

--

--constant H_FP : natural := 40; --H front porch width (pixels)

--constant H_PW : natural := 128; --H sync pulse width (pixels)

--constant H_MAX : natural := 1056; --H total period (pixels)

--

--constant V_FP : natural := 1; --V front porch width (lines)

--constant V_PW : natural := 4; --V sync pulse width (lines)

--constant V_MAX : natural := 628; --V total period (lines)

--

--constant H_POL : std_logic := '1';

--constant V_POL : std_logic := '1';

----***1280x720@60Hz***-- Requires 74.25 MHz clock

--constant FRAME_WIDTH : natural := 1280;

--constant FRAME_HEIGHT : natural := 720;

--

--constant H_FP : natural := 110; --H front porch width (pixels)

--constant H_PW : natural := 40; --H sync pulse width (pixels)

--constant H_MAX : natural := 1650; --H total period (pixels)

--

--constant V_FP : natural := 5; --V front porch width (lines)

--constant V_PW : natural := 5; --V sync pulse width (lines)

--constant V_MAX : natural := 750; --V total period (lines)

--

--constant H_POL : std_logic := '1';

--constant V_POL : std_logic := '1';

----***1280x1024@60Hz***-- Requires 108 MHz clock

--constant FRAME_WIDTH : natural := 1280;

--constant FRAME_HEIGHT : natural := 1024;

--constant H_FP : natural := 48; --H front porch width (pixels)

--constant H_PW : natural := 112; --H sync pulse width (pixels)

--constant H_MAX : natural := 1688; --H total period (pixels)

--constant V_FP : natural := 1; --V front porch width (lines)

--constant V_PW : natural := 3; --V sync pulse width (lines)

--constant V_MAX : natural := 1066; --V total period (lines)

--constant H_POL : std_logic := '1';

--constant V_POL : std_logic := '1';

--***1920x1080@60Hz***-- Requires 148.5 MHz pxl_clk

constant FRAME_WIDTH : natural := 1920;

constant FRAME_HEIGHT : natural := 1080;

constant H_FP : natural := 88; --H front porch width (pixels)

constant H_PW : natural := 44; --H sync pulse width (pixels)

constant H_MAX : natural := 2200; --H total period (pixels)

constant V_FP : natural := 4; --V front porch width (lines)

constant V_PW : natural := 5; --V sync pulse width (lines)

constant V_MAX : natural := 1125; --V total period (lines)

constant H_POL : std_logic := '1';

constant V_POL : std_logic := '1';

--Moving Box constants

constant BOX_WIDTH : natural := 8;

constant BOX_CLK_DIV : natural := 1000000; --MAX=(2^25 - 1)

constant BOX_X_MAX : natural := (512 - BOX_WIDTH);

constant BOX_Y_MAX : natural := (FRAME_HEIGHT - BOX_WIDTH);

constant BOX_X_MIN : natural := 0;

constant BOX_Y_MIN : natural := 256;

constant BOX_X_INIT : std_logic_vector(11 downto 0) := x"000";

constant BOX_Y_INIT : std_logic_vector(11 downto 0) := x"190"; --400

signal pxl_clk : std_logic;

signal active : std_logic;

signal h_cntr_reg : std_logic_vector(11 downto 0) := (others =>'0');

signal v_cntr_reg : std_logic_vector(11 downto 0) := (others =>'0');

signal h_sync_reg : std_logic := not(H_POL);

signal v_sync_reg : std_logic := not(V_POL);

signal h_sync_dly_reg : std_logic := not(H_POL);

signal v_sync_dly_reg : std_logic := not(V_POL);

signal vga_red_reg : std_logic_vector(3 downto 0) := (others =>'0');

signal vga_green_reg : std_logic_vector(3 downto 0) := (others =>'0');

signal vga_blue_reg : std_logic_vector(3 downto 0) := (others =>'0');

signal vga_red : std_logic_vector(3 downto 0);

signal vga_green : std_logic_vector(3 downto 0);

signal vga_blue : std_logic_vector(3 downto 0);

signal box_x_reg : std_logic_vector(11 downto 0) := BOX_X_INIT;

signal box_x_dir : std_logic := '1';

signal box_y_reg : std_logic_vector(11 downto 0) := BOX_Y_INIT;

signal box_y_dir : std_logic := '1';

signal box_cntr_reg : std_logic_vector(24 downto 0) := (others =>'0');

signal update_box : std_logic;

signal pixel_in_box : std_logic;

begin

clk_div_inst : clk_wiz_0

port map

(-- Clock in ports

CLK_IN1 => CLK_I,

-- Clock out ports

CLK_OUT1 => pxl_clk);

----------------------------------------------------

------- TEST PATTERN LOGIC -------

----------------------------------------------------

vga_red <= h_cntr_reg(5 downto 2) when (active = '1' and ((h_cntr_reg < 512 and v_cntr_reg < 256) and h_cntr_reg(8) = '1')) else

(others=>'1') when (active = '1' and ((h_cntr_reg < 512 and not(v_cntr_reg < 256)) and not(pixel_in_box = '1'))) else

(others=>'1') when (active = '1' and ((not(h_cntr_reg < 512) and (v_cntr_reg(8) = '1' and h_cntr_reg(3) = '1')) or

(not(h_cntr_reg < 512) and (v_cntr_reg(8) = '0' and v_cntr_reg(3) = '1')))) else

(others=>'0');

vga_blue <= h_cntr_reg(5 downto 2) when (active = '1' and ((h_cntr_reg < 512 and v_cntr_reg < 256) and h_cntr_reg(6) = '1')) else

(others=>'1') when (active = '1' and ((h_cntr_reg < 512 and not(v_cntr_reg < 256)) and not(pixel_in_box = '1'))) else

(others=>'1') when (active = '1' and ((not(h_cntr_reg < 512) and (v_cntr_reg(8) = '1' and h_cntr_reg(3) = '1')) or

(not(h_cntr_reg < 512) and (v_cntr_reg(8) = '0' and v_cntr_reg(3) = '1')))) else

(others=>'0');

vga_green <= h_cntr_reg(5 downto 2) when (active = '1' and ((h_cntr_reg < 512 and v_cntr_reg < 256) and h_cntr_reg(7) = '1')) else

(others=>'1') when (active = '1' and ((h_cntr_reg < 512 and not(v_cntr_reg < 256)) and not(pixel_in_box = '1'))) else

(others=>'1') when (active = '1' and ((not(h_cntr_reg < 512) and (v_cntr_reg(8) = '1' and h_cntr_reg(3) = '1')) or

(not(h_cntr_reg < 512) and (v_cntr_reg(8) = '0' and v_cntr_reg(3) = '1')))) else

(others=>'0');

------------------------------------------------------

------- MOVING BOX LOGIC ------

------------------------------------------------------

process (pxl_clk)

begin

if (rising_edge(pxl_clk)) then

if (update_box = '1') then

if (box_x_dir = '1') then

box_x_reg <= box_x_reg + 1;

else

box_x_reg <= box_x_reg - 1;

end if;

if (box_y_dir = '1') then

box_y_reg <= box_y_reg + 1;

else

box_y_reg <= box_y_reg - 1;

end if;

end if;

end if;

end process;

process (pxl_clk)

begin

if (rising_edge(pxl_clk)) then

if (update_box = '1') then

if ((box_x_dir = '1' and (box_x_reg = BOX_X_MAX - 1)) or (box_x_dir = '0' and (box_x_reg = BOX_X_MIN + 1))) then

box_x_dir <= not(box_x_dir);

end if;

if ((box_y_dir = '1' and (box_y_reg = BOX_Y_MAX - 1)) or (box_y_dir = '0' and (box_y_reg = BOX_Y_MIN + 1))) then

box_y_dir <= not(box_y_dir);

end if;

end if;

end if;

end process;

process (pxl_clk)

begin

if (rising_edge(pxl_clk)) then

if (box_cntr_reg = (BOX_CLK_DIV - 1)) then

box_cntr_reg <= (others=>'0');

else

box_cntr_reg <= box_cntr_reg + 1;

end if;

end if;

end process;

update_box <= '1' when box_cntr_reg = (BOX_CLK_DIV - 1) else

'0';

pixel_in_box <= '1' when (((h_cntr_reg >= box_x_reg) and (h_cntr_reg < (box_x_reg + BOX_WIDTH))) and

((v_cntr_reg >= box_y_reg) and (v_cntr_reg < (box_y_reg + BOX_WIDTH)))) else

'0';

------------------------------------------------------

------- SYNC GENERATION ------

------------------------------------------------------

process (pxl_clk)

begin

if (rising_edge(pxl_clk)) then

if (h_cntr_reg = (H_MAX - 1)) then

h_cntr_reg <= (others =>'0');

else

h_cntr_reg <= h_cntr_reg + 1;

end if;

end if;

end process;

process (pxl_clk)

begin

if (rising_edge(pxl_clk)) then

if ((h_cntr_reg = (H_MAX - 1)) and (v_cntr_reg = (V_MAX - 1))) then

v_cntr_reg <= (others =>'0');

elsif (h_cntr_reg = (H_MAX - 1)) then

v_cntr_reg <= v_cntr_reg + 1;

end if;

end if;

end process;

process (pxl_clk)

begin

if (rising_edge(pxl_clk)) then

if (h_cntr_reg >= (H_FP + FRAME_WIDTH - 1)) and (h_cntr_reg < (H_FP + FRAME_WIDTH + H_PW - 1)) then

h_sync_reg <= H_POL;

else

h_sync_reg <= not(H_POL);

end if;

end if;

end process;

process (pxl_clk)

begin

if (rising_edge(pxl_clk)) then

if (v_cntr_reg >= (V_FP + FRAME_HEIGHT - 1)) and (v_cntr_reg < (V_FP + FRAME_HEIGHT + V_PW - 1)) then

v_sync_reg <= V_POL;

else

v_sync_reg <= not(V_POL);

end if;

end if;

end process;

active <= '1' when ((h_cntr_reg < FRAME_WIDTH) and (v_cntr_reg < FRAME_HEIGHT))else

'0';

process (pxl_clk)

begin

if (rising_edge(pxl_clk)) then

v_sync_dly_reg <= v_sync_reg;

h_sync_dly_reg <= h_sync_reg;

vga_red_reg <= vga_red;

vga_green_reg <= vga_green;

vga_blue_reg <= vga_blue;

end if;

end process;

VGA_HS_O <= h_sync_dly_reg;

VGA_VS_O <= v_sync_dly_reg;

VGA_R <= vga_red_reg;

VGA_G <= vga_green_reg;

VGA_B <= vga_blue_reg;

end Behavioral;

 

Here and here are non-digilent VGA tutorials. Here is a listing for different pixel frequencies and resolutions. 

best regards,

Jon

Share this post


Link to post
Share on other sites
  • 0

Hi @Mukul,

Another think would be to use the zynq processor or clocking wizard to generate the frequency you would like to use.

In the VHDL code posted above this code uses the clocking wizard.

component clk_wiz_0

port

(-- Clock in ports

CLK_IN1 : in std_logic;

-- Clock out ports

CLK_OUT1 : out std_logic

);

best regards,

Jon

 

Share this post


Link to post
Share on other sites
  • 0

Hi @jpeyron

I replaced the counter based clock divider with fractional clock divider, now my verilog code for VGA controller work fine.

But i check for clicking wizard, zynq processor.

Thanks for support

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now