09-27-2017 05:34 AM
Hello!
Application description
I can briefly explain my application so that you get an idea of what I am doing.
I am trying to show a picture on a VGA screen where I have to firstly write pixel values to BRAM ,read it back and then present it on a screen through a VGA connector.
Currently ,"FFF"s are written into memory, representing a 12-bit RGB colour that is suppose to be on the computer screeen.
As for now ,Zedboard is used to code this VGA application.
I personally suspect that the clocks generated are not working correctly. I am using the clocking wizard IP to generate two different clock sources with different frequencies.
Current settings in clocking wizard block:
clk_100 = 100 Mhz
clk_out1 = 20 Mhz (writes are faster than reads)
clk_out2 = 10 Mhz
Simulation Results
I have so far generated simulation results that indicate that my application work. However I have to manually force the first clock signal( CLK_100 OR clk_in1). What I think might be the problem is that the clock is working on simulation but not on the hardware itself thus generating incorrect VGA signals. I have tried different clock settings by following the datasheet ... but can't really see why this application fails.
RED = VGA block
YELLOW = RAND block
BLUE = clocking wizard block
(Please check the block design below for more info)
Figure 1. Writes "FFF" to memory ,retrieves the value back from it and generates VGA signals-
figure 2. Sets the H-sync signal to zero when the ROW has been processed as a VGA signal.
Figure 3. Showing a normal operation when both H-sync and V-sync is high.
XDC code with pin settings
set_property DIRECTION OUT [get_ports {vga_blue[3]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_blue[3]}] set_property DRIVE 12 [get_ports {vga_blue[3]}] set_property SLEW SLOW [get_ports {vga_blue[3]}] set_property DIRECTION OUT [get_ports {vga_blue[2]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_blue[2]}] set_property DRIVE 12 [get_ports {vga_blue[2]}] set_property SLEW SLOW [get_ports {vga_blue[2]}] set_property DIRECTION OUT [get_ports {vga_blue[1]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_blue[1]}] set_property DRIVE 12 [get_ports {vga_blue[1]}] set_property SLEW SLOW [get_ports {vga_blue[1]}] set_property DIRECTION OUT [get_ports {vga_blue[0]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_blue[0]}] set_property DRIVE 12 [get_ports {vga_blue[0]}] set_property SLEW SLOW [get_ports {vga_blue[0]}] set_property DIRECTION OUT [get_ports {vga_green[3]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_green[3]}] set_property DRIVE 12 [get_ports {vga_green[3]}] set_property SLEW SLOW [get_ports {vga_green[3]}] set_property DIRECTION OUT [get_ports {vga_green[2]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_green[2]}] set_property DRIVE 12 [get_ports {vga_green[2]}] set_property SLEW SLOW [get_ports {vga_green[2]}] set_property DIRECTION OUT [get_ports {vga_green[1]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_green[1]}] set_property DRIVE 12 [get_ports {vga_green[1]}] set_property SLEW SLOW [get_ports {vga_green[1]}] set_property DIRECTION OUT [get_ports {vga_green[0]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_green[0]}] set_property DRIVE 12 [get_ports {vga_green[0]}] set_property SLEW SLOW [get_ports {vga_green[0]}] set_property DIRECTION OUT [get_ports {vga_red[3]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_red[3]}] set_property DRIVE 12 [get_ports {vga_red[3]}] set_property SLEW SLOW [get_ports {vga_red[3]}] set_property DIRECTION OUT [get_ports {vga_red[2]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_red[2]}] set_property DRIVE 12 [get_ports {vga_red[2]}] set_property SLEW SLOW [get_ports {vga_red[2]}] set_property DIRECTION OUT [get_ports {vga_red[1]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_red[1]}] set_property DRIVE 12 [get_ports {vga_red[1]}] set_property SLEW SLOW [get_ports {vga_red[1]}] set_property DIRECTION OUT [get_ports {vga_red[0]}] set_property IOSTANDARD LVCMOS18 [get_ports {vga_red[0]}] set_property DRIVE 12 [get_ports {vga_red[0]}] set_property SLEW SLOW [get_ports {vga_red[0]}] set_property DIRECTION IN [get_ports clk_100] set_property IOSTANDARD LVCMOS18 [get_ports clk_100] set_property DIRECTION IN [get_ports resetn] set_property IOSTANDARD LVCMOS18 [get_ports resetn] set_property DIRECTION OUT [get_ports vga_hsync] set_property IOSTANDARD LVCMOS18 [get_ports vga_hsync] set_property DRIVE 12 [get_ports vga_hsync] set_property SLEW SLOW [get_ports vga_hsync] set_property DIRECTION OUT [get_ports vga_vsync] set_property IOSTANDARD LVCMOS18 [get_ports vga_vsync] set_property DRIVE 12 [get_ports vga_vsync] set_property SLEW SLOW [get_ports vga_vsync] set_property PACKAGE_PIN Y9 [get_ports clk_100] set_property PACKAGE_PIN Y21 [get_ports {vga_blue[3]}] set_property PACKAGE_PIN Y20 [get_ports {vga_blue[2]}] set_property PACKAGE_PIN AB20 [get_ports {vga_blue[1]}] set_property PACKAGE_PIN AB19 [get_ports {vga_blue[0]}] set_property PACKAGE_PIN AB22 [get_ports {vga_green[3]}] set_property PACKAGE_PIN AA22 [get_ports {vga_green[2]}] set_property PACKAGE_PIN AB21 [get_ports {vga_green[1]}] set_property PACKAGE_PIN AA21 [get_ports {vga_green[0]}] set_property PACKAGE_PIN V20 [get_ports {vga_red[3]}] set_property PACKAGE_PIN U20 [get_ports {vga_red[2]}] set_property PACKAGE_PIN V19 [get_ports {vga_red[1]}] set_property PACKAGE_PIN V18 [get_ports {vga_red[0]}] set_property PACKAGE_PIN T18 [get_ports resetn] set_property PACKAGE_PIN AA19 [get_ports vga_hsync] set_property PACKAGE_PIN Y19 [get_ports vga_vsync] #revert back to original instance current_instance -quiet
VGA code
---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 26.07.2017 16:49:54 -- Design Name: -- Module Name: VGA_generator - Behavioral -- Project Name: -- Target Devices: -- Tool Versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.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 leaf cells in this code. --library UNISIM; --use UNISIM.VComponents.all; entity VGA_generator is Port ( clk : in STD_LOGIC; vga_red : out STD_LOGIC_VECTOR(3 downto 0); vga_green : out STD_LOGIC_VECTOR(3 downto 0); vga_blue : out STD_LOGIC_VECTOR(3 downto 0); vga_hsync : out STD_LOGIC; vga_vsync : out STD_LOGIC; en : out STD_LOGIC; frame_addr : out STD_LOGIC_VECTOR(18 downto 0); frame_pixel : in STD_LOGIC_VECTOR(11 downto 0) ); end VGA_generator; architecture Behavioral of VGA_generator is -- Timing constants constant hRez : natural := 640; constant hStartSync : natural := 640+16; constant hEndSync : natural := 640+16+96; constant hMaxCount : natural := 800; constant vRez : natural := 480; constant vStartSync : natural := 480+10; constant vEndSync : natural := 480+10+2; constant vMaxCount : natural := 480+10+2+33; constant hsync_active : std_logic := '0'; constant vsync_active : std_logic := '0'; signal hCounter : unsigned( 9 downto 0) := (others => '0'); signal vCounter : unsigned( 9 downto 0) := (others => '0'); signal address : unsigned(18 downto 0) := (others => '0'); signal blank : std_logic := '1'; begin frame_addr <= std_logic_vector(address(18 downto 0)); en <= '1'; --ALWAYS ONE HAS TO CHECK WHY IT WORKS TIMING ERROR WHEN CHANGING THIS HAS TO BE CHANGED TOGETHER WITH THE WEA PIN process(clk) begin if rising_edge(clk) then -- Count the lines and rows -- Count the lines and rows if hCounter = hMaxCount-1 then hCounter <= (others => '0'); if vCounter = vMaxCount-1 then vCounter <= (others => '0'); else vCounter <= vCounter+1; end if; else hCounter <= hCounter+1; end if; if blank = '0' then vga_red <= frame_pixel(11 downto 8); vga_green <= frame_pixel( 7 downto 4); vga_blue <= frame_pixel( 3 downto 0); else vga_red <= (others => '0'); vga_green <= (others => '0'); vga_blue <= (others => '0'); end if; if vCounter >= vRez then address <= (others => '0'); blank <= '1'; else if hCounter < 640 then blank <= '0'; address <= address + 1; else blank <= '1'; end if; end if; -- Are we in the hSync pulse? (one has been added to include frame_buffer_latency) if hCounter > hStartSync and hCounter <= hEndSync then vga_hSync <= hsync_active; else vga_hSync <= not hsync_active; end if; -- Are we in the vSync pulse? if vCounter >= vStartSync and vCounter < vEndSync then vga_vSync <= vsync_active; else vga_vSync <= not vsync_active; end if; end if; end process; end Behavioral;
rand_generator code
---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 16.08.2017 14:23:22 -- Design Name: -- Module Name: vga_rand_gen - Behavioral -- Project Name: -- Target Devices: -- Tool Versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values -- -- Uncomment the following library declaration if instantiating -- any Xilinx leaf cells in this code. --library UNISIM; --use UNISIM.VComponents.all; entity vga_rand_generator is Port ( clk : IN std_logic; frame_addr : OUT std_logic_vector(18 downto 0); frame_pixel : OUT std_logic_vector(11 downto 0); we : OUT std_logic ); end vga_rand_generator; architecture Behavioral of vga_rand_generator is signal address : std_logic_vector(18 downto 0) := (others => '0'); signal new_wre : std_logic:= '0'; signal pixel : std_logic_vector(11 downto 0) := (others => '0'); signal first : std_logic:= '0'; begin frame_addr <= address; frame_pixel <= pixel; we <= '1'; --ALWAYS ONE HAS TO CHECK WHY IT WORKS TIMING ERROR WHEN CHANGING THIS HAS TO BE CHANGED TOGETHER WITH THE ENABLE PIN process(clk) begin if rising_edge(clk) then pixel <= b"111111111111"; address <= std_logic_vector(unsigned(address) + 1); if address = b"1001011000000000000" then address <= (others => '0'); end if; end if; end process; end Behavioral;
regards,
Azurath
09-27-2017 05:48 AM
Hi @azurath,
Could you explain what you mean by it is not working on HW? Did you use an ILA to check the signals or is it just that you monitor does not display anything?
I think I have already see issue with monitor if you send data during hsync, vsync or the blanking period. It seems to be your case.
You might want to see this tutorial as a reference for VGA on zedboard. It is really simple so it might help to get started.
Regards,
Florent
09-27-2017 05:44 AM
Correct title shall be:
"VGA works well in simulation but not on real hardware"
09-27-2017 05:48 AM
Hi @azurath,
Could you explain what you mean by it is not working on HW? Did you use an ILA to check the signals or is it just that you monitor does not display anything?
I think I have already see issue with monitor if you send data during hsync, vsync or the blanking period. It seems to be your case.
You might want to see this tutorial as a reference for VGA on zedboard. It is really simple so it might help to get started.
Regards,
Florent
09-27-2017 05:55 AM
Hi,
have glanced over your post and here are my few generic comments.
However I have to manually force the first clock signal( CLK_100 OR clk_in1).
Not a good way to generate clock. From the TB use a signal which toggles that will drive clk_in1.
In such designs monitoring the FIFO input/output data is useful. Try that and ensure you read the data out which has been written into and it is in sequence.
Use an ILA core to debug the internal signals and connections. Use it wherever you have a doubt.
------------FPGA enthusiast------------
Consider giving "Kudos" if you like my answer. Please mark my post "Accept as solution" if my answer has solved your problem
09-27-2017 06:07 AM
Hello @florentw,
I have not considered to use ILA Since I am new to this forum but will from now on use it.
My monitor does not display anything.It just goes to sleep mode.. however I have attached a button to the reset_n signal .. the screen goes active again whenever I press that button but Its still black all the time.
I will recheck and see if that's the problem.
I will check the tutorial.
10-03-2017 07:31 AM
The VGA timing specifications were not correct thus not working properly.. Thx for recommending ILA .. It was a great IP that I used to debug. Checking the timings and controlling the back porch,front porch and sync pulse signal for both V-sync and H-sync did solve the problem..
10-03-2017 07:33 AM