3
\$\begingroup\$

I am trying to implement a video streamer on Digilent ZYBO board that has Xilinx ZYNQ 7010. By the way, reason of this thing is to test the quality of an encoder board. What I want is to:

  • Generate a RAM Block to store pre-determined video data.
  • Stream out its contents from Pmod connectors (probably using AXI4-Stream Video Out block), using DMA.

Video features are: 1024x768, 720p, 30fps for now. I may have to change them later.

I have found some design on web (please check the figure below). But since it generates random video, I have to modify (I mean, replace it with some other blocks) Test Pattern Generator block, but I have no idea how. What kind of design process should I follow? I have limited time and knowledge about block designing and HDLs, so any help is appreciated.

enter image description here

asked Apr 7, 2016 at 16:16
\$\endgroup\$
5
  • \$\begingroup\$ The simple answer is to replace the video sample generator with your own module, generating a simple image, for that you need to know the format of the streaming video which is well documented. I am afraid there is no other way than finding another module that does the exact same thing you want to do. \$\endgroup\$ Commented Apr 8, 2016 at 6:43
  • \$\begingroup\$ Check out xilinx.com/products/intellectual-property/tpg.html it has exactly what you are looking for \$\endgroup\$ Commented Apr 8, 2016 at 6:46
  • \$\begingroup\$ @FarhadA I have just checked what you suggested. But I don't have a full license and it seems that it is obligatory to use Video Test Pattern Generator. \$\endgroup\$ Commented Apr 8, 2016 at 6:55
  • \$\begingroup\$ Are you using WebPack? because this is what it says in the license section of the IP: Licensing and Ordering Information This Xilinx® LogiCORETM IP module is provided at no cost under the terms of the Xilinx Core License Agreement. The module is shipped as part of the Vivado Design Suite. For full access to all core functionalities in simulation and in hardware, you must request a free license for the core. Contact your local Xilinx sales representative for information about pricing and availability. \$\endgroup\$ Commented Apr 8, 2016 at 9:48
  • \$\begingroup\$ Just checked my WEBPACK Vivado 2015.01 and it has the "Test Pattern Generator" module (that you have in your block) included in the license. If you double click on the IP, you will be able to modify the parameters of the IP and get what you are looking for. \$\endgroup\$ Commented Apr 8, 2016 at 11:31

1 Answer 1

2
\$\begingroup\$

I wrote this TPG for a project of mine. Maybe it can help you. Create a new Vivado Project. Import the code and generate a IP. Now you can import it into our project.

The output is raw Bayer, but it can easily be adopted to output RBG or YUV.

-------------------------------------------------------------------------------
-- Entity: testpattern_axi
-- Autor: Reto Meier [[email protected]]
-- Date: 2016年02月03日
-- Project: Gazelle
--
-- Description:
-- This test pattern generator makes a similar pattern as the camera would 
-- generate. It is allmost the same code as camera_testpattern, but as output
-- is not CIF but AXI
-------------------------------------------------------------------------------
library ieee;
 use ieee.std_logic_1164.all;
 use ieee.numeric_std.all; 
 use ieee.math_real.all;
package testpattern_axi_pkg is
 component testpattern_axi is
 generic(
 img_height: integer := 480;
 img_width: integer := 640;
 brake_line: integer := 100;
 brake_frame: integer := 500;
 brake_pre_frame: integer := 100;
 data_length: integer := 12
 );
 port( 
 clk: in std_logic;
 o_valid: out std_logic;
 o_user: out std_logic;
 o_last: out std_logic;
 o_ready: in std_logic;
 o_data: out std_logic_vector(data_length-1 downto 0)
 );
 end component testpattern_axi;
end package testpattern_axi_pkg;
-------------------------------------------------------------------------------
library ieee;
 use ieee.std_logic_1164.all;
 use ieee.numeric_std.all; 
 use ieee.math_real.all; 
entity testpattern_axi is
 generic(
 img_height: integer := 480;
 img_width: integer := 640;
 brake_line: integer := 100;
 brake_frame: integer := 500;
 brake_pre_frame: integer := 100;
 data_length: integer := 16
 );
 port( 
 clk: in std_logic;
 o_valid: out std_logic;
 o_user: out std_logic;
 o_last: out std_logic;
 o_ready: in std_logic;
 o_data: out std_logic_vector(data_length-1 downto 0)
 );
end entity testpattern_axi;
-------------------------------------------------------------------------------
architecture rtl of testpattern_axi is
 constant cnt_max: integer := 32000;
 type state_type is (s_frame_brake, s_pre_frame_brake, s_line_brake, s_line); --type of state machine. 
 type reg_type is record
 cnt: unsigned(integer(floor(log2(real(cnt_max)))) downto 0);
 cnt_lines: unsigned(integer(floor(log2(real(cnt_max)))) downto 0);
 r, g, b: std_logic;
 std_line: std_logic_vector(cnt_lines'range);
 std_cnt: std_logic_vector(cnt'range);
 state: state_type;
 end record reg_type;
 constant init_values: reg_type :=( 
 cnt => (others =>'0'),
 cnt_lines => (others=>'0'),
 r => '0', 
 g => '0',
 b => '0',
 std_line => (others =>'0'),
 std_cnt => (others =>'0'),
 state => s_frame_brake);
 signal r, rin: reg_type := init_values;
begin
 combinational: process(r, o_ready)
 variable v: reg_type;
 begin
 v := r; 
 if o_ready = '1' then
 v.cnt := v.cnt + 1;
 end if;
 -- make the brakes and lines
 case v.state is 
 when s_frame_brake =>
 if v.cnt = to_unsigned(brake_frame, v.cnt'length) then
 v.state := s_pre_frame_brake;
 v.cnt := to_unsigned(0, v.cnt'length);
 end if;
 when s_pre_frame_brake => 
 if v.cnt = to_unsigned(brake_pre_frame, v.cnt'length) then
 v.state := s_line;
 v.cnt := to_unsigned(0, v.cnt'length); 
 end if;
 when s_line => 
 if v.cnt = to_unsigned(img_width, v.cnt'length) then
 v.cnt := to_unsigned(0, v.cnt'length);
 if v.cnt_lines = to_unsigned(img_height-1, v.cnt_lines'length) then
 v.state := s_frame_brake;
 v.cnt_lines := to_unsigned(0, v.cnt_lines'length);
 else
 v.state := s_line_brake;
 v.cnt_lines := v.cnt_lines + 1;
 end if;
 end if;
 when s_line_brake => 
 if v.cnt = to_unsigned(brake_line, v.cnt'length) then
 v.state := s_line;
 v.cnt := to_unsigned(0, v.cnt'length);
 end if;
 end case;
 -- generate the color pattern according to the position in the line
 if v.cnt > to_unsigned(img_width/8*7-1,v.cnt'length) then
 v.r := '0';
 v.g := '0';
 v.b := '0';
 elsif v.cnt > to_unsigned(img_width/8*6-1,v.cnt'length) then
 v.r := '0';
 v.g := '0';
 v.b := '1';
 elsif v.cnt > to_unsigned(img_width/8*5-1,v.cnt'length) then
 v.r := '1';
 v.g := '0';
 v.b := '0';
 elsif v.cnt > to_unsigned(img_width/8*4-1,v.cnt'length) then
 v.r := '1';
 v.g := '0';
 v.b := '1';
 elsif v.cnt > to_unsigned(img_width/8*3-1,v.cnt'length) then
 v.r := '0';
 v.g := '1';
 v.b := '0';
 elsif v.cnt > to_unsigned(img_width/8*2-1,v.cnt'length) then
 v.r := '0';
 v.g := '1';
 v.b := '1';
 elsif v.cnt > to_unsigned(img_width/8*1-1,v.cnt'length) then
 v.r := '1';
 v.g := '1';
 v.b := '0';
 else
 v.r := '1';
 v.g := '1';
 v.b := '1';
 end if;
 -- generate the output
 case v.state is 
 when s_line => 
 o_valid <= '1';
 if v.cnt_lines = to_unsigned(0, v.cnt_lines'length) and 
 v.cnt = to_unsigned(0, v.cnt'length) then
 o_user <= '1';
 else
 o_user <= '0';
 end if;
 if v.cnt = to_unsigned(img_width-1, v.cnt'length) then
 o_last <= '1';
 else
 o_last <= '0';
 end if;
 v.std_line := std_logic_vector(v.cnt_lines);
 v.std_cnt := std_logic_vector(v.cnt);
 if v.std_line(0) = '0' then
 if v.std_cnt(0) = '0' then
 if v.b = '1' then
 o_data <= (others => '1');
 else
 o_data <= (others => '0');
 end if;
 else
 if v.g = '1' then
 o_data <= (others => '1');
 else
 o_data <= (others => '0');
 end if;
 end if;
 else
 if v.std_cnt(0) = '0' then
 if v.g = '1' then
 o_data <= (others => '1');
 else
 o_data <= (others => '0');
 end if;
 else
 if v.r = '1' then
 o_data <= (others => '1');
 else
 o_data <= (others => '0');
 end if;
 end if; 
 end if;
 when others => 
 o_valid <= '0';
 o_user <= '0';
 o_last <= '0';
 o_data <= (others => '0');
 end case;
 rin <= v;
 end process combinational;
 sequential: process(clk) -- sequential process (not need to edit)
 begin
 if rising_edge(clk) then
 r <= rin;
 end if;
 end process sequential;
end architecture rtl;
answered Apr 8, 2016 at 7:17
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.