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;