VHDL: canalización con un bucle for

1

La pregunta se trasladó a: enlace

Estoy implementando un módulo AXI4-Stream. El módulo utiliza tres bloques DSP (DSP49E1, UG479 - Xilinx). Para ejecutar el módulo a una frecuencia de 150 MHz, el diseño es una tubería que pasa sucesivamente a través de cada DSP.

En el código a continuación, elegí un bucle for en un solo proceso para implementar la canalización. Debo decir que he simulado y probado este diseño en un FPGA (serie 7) y funciona perfectamente bien hasta ahora.

Mis preguntas son: ¿Sería mejor crear procesos independientes en lugar de un bucle for dentro de un solo proceso? Me gusta la forma en que codifiqué la tubería porque me ahorró tiempo (para el registro de cambios) gracias al bucle for y las matrices de std_logic_vector. Sin embargo, ¿es una buena forma de codificarlo (frecuencia, potencia, utilización de FPGA, ...)? Más generalmente, es una buena práctica de diseño o es limitante para ciertos propósitos. Me gustaría entender los por qué y los de mi elección.

Gracias.

Mi código:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library ieee_proposed;
use ieee_proposed.fixed_pkg.all;

entity slave_AXIStream_RGBtoGray is
port (
    -- Main signals
    CLK                 : in std_logic;
    RESETN              : in std_logic;

    -- Ready signal for upstream block
    S_AXIS_TREADY       : out std_logic;
    -- Data in
    S_AXIS_TDATA        : in std_logic_vector(23 downto 0);
    -- Flag for first pixel of a frame
    S_AXIS_TUSER        : in std_logic;
    -- Flag for last pixel of a line
    S_AXIS_TLAST        : in std_logic;
   -- Valid data
   S_AXIS_TVALID       : in std_logic;

    -- Downstream blocks are ready
    M_AXIS_TREADY       : in std_logic;    
    -- Data out
    M_AXIS_TDATA        : out std_logic_vector(7 downto 0);
    -- Flag for first pixel of a frame
    M_AXIS_TUSER        : out std_logic;
    -- Flag for last pixel of a line
    M_AXIS_TLAST        : out std_logic;
    -- Valid data
    M_AXIS_TVALID       : out std_logic    
);
end slave_AXIStream_RGBtoGray;

architecture Behavioral of slave_AXIStream_RGBtoGray is

-- DSP to perform A*B+C 
COMPONENT dsp48E1_macro
    PORT (
        CLK : IN STD_LOGIC;
        CE : IN STD_LOGIC;
        SCLR : IN STD_LOGIC;
        A : IN STD_LOGIC_VECTOR(14 DOWNTO 0); -- signed, two's complement
        B : IN STD_LOGIC_VECTOR(14 DOWNTO 0); -- signed, two's complement
        C : IN STD_LOGIC_VECTOR(29 DOWNTO 0); -- signed, two's complement
        P : OUT STD_LOGIC_VECTOR(30 DOWNTO 0) -- signed, two's complement
    );
END COMPONENT;

-- main signals
signal main_ready               : std_logic;

-- DSP48E1 signals
signal dsp_A_out                : std_logic_vector(30 downto 0);    
signal dsp_B_out                : std_logic_vector(30 downto 0);
signal dsp_C_out                : std_logic_vector(30 downto 0);

-- Out = coef_red * component_red + coef_green * component_green + coef_blue * component_blue
-- sum of the factors <= 1
constant coef_red               : std_logic_vector(14 downto 0) := to_slv(to_ufixed (0.29, 8, -6));
constant coef_green             : std_logic_vector(14 downto 0) := to_slv(to_ufixed (0.59, 8, -6));
constant coef_blue              : std_logic_vector(14 downto 0) := to_slv(to_ufixed (0.11, 8, -6));

-- Pipeline
signal pipeline_step            : integer range 0 to 13;       
type array_component_2DSP is array(0 to 8) of std_logic_vector(7 downto 0);
type array_component_1DSP is array(0 to 4) of std_logic_vector(7 downto 0);
signal component_red_dsp        : std_logic_vector(7 downto 0);
signal component_green_dsp      : array_component_1DSP;
signal component_blue_dsp       : array_component_2DSP;
signal DV_step_dsp              : std_logic_vector(0 to 12); -- data valid
signal SOF_step_dsp             : std_logic_vector(0 to 12); -- start of frame
signal EOL_step_dsp             : std_logic_vector(0 to 12); -- end of line

-- Last step
signal component_mono_step_out  : std_logic_vector(7 downto 0);    
signal DV_step_out              : std_logic; -- data valid
signal SOF_step_out             : std_logic; -- start of frame
signal EOL_step_out             : std_logic; -- end of line

signal data_stored              : std_logic_vector(7 downto 0);
signal DV_stored                : std_logic; -- data valid
signal SOF_stored               : std_logic; -- start of frame
signal EOL_stored               : std_logic; -- end of line

begin

S_AXIS_TREADY <= main_ready;

M_AXIS_TDATA <= component_mono_step_out;
M_AXIS_TVALID <= DV_step_out;
M_AXIS_TUSER <= SOF_step_out;
M_AXIS_TLAST <= EOL_step_out;

DSP_A: dsp48E1_macro
PORT MAP (
    CLK => CLK,
    CE => main_ready,
    SCLR => not RESETN,
    A => '0' & component_red_dsp & "000000",
    B => coef_red,
    C => (others => '0'),
    P => dsp_A_out
);

DSP_B: dsp48E1_macro
PORT MAP (
    CLK => CLK,
    CE => main_ready,
    SCLR => not RESETN,
    A => '0' & component_green_dsp(4) & "000000",
    B => coef_green,
    C => dsp_A_out(29 downto 0),
    P => dsp_B_out
);

DSP_C: dsp48E1_macro
PORT MAP (
    CLK => CLK,
    CE => main_ready,
    SCLR => not RESETN,
    A => '0' & component_blue_dsp(8) & "000000",
    B => coef_blue,
    C => dsp_B_out(29 downto 0),
    P => dsp_C_out
);        

main_process: process(CLK)
begin
if (rising_edge (CLK)) then
if(RESETN = '0') then
    pipeline_step <= 0;
    main_ready <= '0';

    component_red_dsp <= (others => '0');
    component_green_dsp <= (others => (others => '0'));
    component_blue_dsp <= (others => (others => '0'));

    DV_step_dsp <= (others => '0');
    SOF_step_dsp <= (others => '0');
    EOL_step_dsp <= (others => '0');

    component_mono_step_out <= (others => '0');
    DV_step_out <= '0';
    SOF_step_out <= '0';
    EOL_step_out <= '0';

    DV_stored <= '0';
    SOF_stored <= '0';
    EOL_stored <= '0';
else

    FOR pipeline_step IN 0 TO 13 LOOP
        CASE pipeline_step IS
            WHEN 0 => 
                if main_ready = '1' then
                    component_red_dsp <= S_AXIS_TDATA(23 downto 16);
                    component_green_dsp(pipeline_step) <= S_AXIS_TDATA(15 downto 8);
                    component_blue_dsp(pipeline_step) <= S_AXIS_TDATA(7 downto 0);
                    DV_step_dsp(pipeline_step) <= S_AXIS_TVALID;
                    SOF_step_dsp(pipeline_step) <= S_AXIS_TUSER;
                    EOL_step_dsp(pipeline_step) <= S_AXIS_TLAST;
                end if;

            WHEN 1 to 4 => 
                if main_ready = '1' then
                    component_green_dsp(pipeline_step) <= component_green_dsp(pipeline_step-1);
                    component_blue_dsp(pipeline_step) <= component_blue_dsp(pipeline_step-1);
                    DV_step_dsp(pipeline_step) <= DV_step_dsp(pipeline_step-1); 
                    SOF_step_dsp(pipeline_step) <= SOF_step_dsp(pipeline_step-1);
                    EOL_step_dsp(pipeline_step) <= EOL_step_dsp(pipeline_step-1);
                end if;            

            WHEN 5 to 8 => 
                if main_ready = '1' then
                    component_blue_dsp(pipeline_step) <= component_blue_dsp(pipeline_step-1);
                    DV_step_dsp(pipeline_step) <= DV_step_dsp(pipeline_step-1); 
                    SOF_step_dsp(pipeline_step) <= SOF_step_dsp(pipeline_step-1);
                    EOL_step_dsp(pipeline_step) <= EOL_step_dsp(pipeline_step-1);
                end if;

            WHEN 9 to 12 => 
                if main_ready = '1' then
                    DV_step_dsp(pipeline_step) <= DV_step_dsp(pipeline_step-1); 
                    SOF_step_dsp(pipeline_step) <= SOF_step_dsp(pipeline_step-1);
                    EOL_step_dsp(pipeline_step) <= EOL_step_dsp(pipeline_step-1); 
                end if;                     

            WHEN 13 =>
                if M_AXIS_TREADY = '1' or DV_step_out = '0' then
                    main_ready <= '1';
                    DV_step_out <= '0';

                    if main_ready = '1' then
                        component_mono_step_out <= dsp_C_out(19 downto 12); 
                        DV_step_out <= DV_step_dsp(pipeline_step-1);
                        SOF_step_out <= SOF_step_dsp(pipeline_step-1);
                        EOL_step_out <= EOL_step_dsp(pipeline_step-1); 
                    else
                        component_mono_step_out <= data_stored; 
                        DV_step_out <= DV_stored;
                        SOF_step_out <= SOF_stored;
                        EOL_step_out <= EOL_stored;  
                        DV_stored <= '0';
                    end if;
                else
                    main_ready <= '0';

                    if main_ready = '1' then
                        data_stored <= dsp_C_out(19 downto 12);
                        DV_stored <= DV_step_dsp(pipeline_step-1);
                        SOF_stored <= SOF_step_dsp(pipeline_step-1);
                        EOL_stored <= EOL_step_dsp(pipeline_step-1); 
                    end if;
                end if;

            WHEN others => NULL;
        END CASE;
    END LOOP;
end if;
end if;
end process;

end Behavioral;
    
pregunta Marmoz

0 respuestas

Lea otras preguntas en las etiquetas