¿Generando video con ZYNQ, usando el diseño de bloqueo de IP?

2

Estoy tratando de implementar un transmisor de video en la placa ZYBO de Digilent que tiene Xilinx ZYNQ 7010. Por cierto, la razón de esto es probar la calidad de una placa codificadora. Lo que quiero es:

  • Genere un bloque RAM para almacenar datos de video predeterminados.
  • Transmita su contenido desde los conectores Pmod (probablemente utilizando el bloque AXI4-Stream Video Out ), utilizando DMA .

Las características de video son: 1024x768, 720p, 30fps por ahora. Puede que tenga que cambiarlos más tarde.

Encontré algunos diseños en la web ( compruebe la figura a continuación ). Pero como genera video aleatorio, tengo que modificar (quiero decir, reemplazarlo con algunos otros bloques) Bloque Generador de patrones de prueba, pero no tengo idea de cómo. ¿Qué tipo de proceso de diseño debo seguir? Tengo un tiempo y conocimiento limitados sobre el diseño de bloques y HDL, por lo que se agradece cualquier ayuda.

    
pregunta ddyn

1 respuesta

2

Escribí este TPG para un proyecto mío. Puede que esto te ayude. Crea un nuevo proyecto de vivado. Importa el código y genera una IP. Ahora puedes importarlo en nuestro proyecto.

La salida es Bayer sin formato, pero se puede adoptar fácilmente para generar RBG o 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;
    
respondido por el Botnic

Lea otras preguntas en las etiquetas