diff --git a/src/Pipeline_pb.vhd b/src/Pipeline_pb.vhd index f366525..8cd37f6 100644 --- a/src/Pipeline_pb.vhd +++ b/src/Pipeline_pb.vhd @@ -11,24 +11,36 @@ use ieee.math_real.all; entity Pipeline_pb is generic ( - --@ Number of pipeline stages - G_PipelineStages : integer := 10; + --@ Number of pipeline stages inside each module + G_PipelineStages : integer := 2; --@ Data width - G_Width : integer := 32; + G_Width : integer := 8; --@ Register balancing attribute
--@ - "no" : No register balancing
--@ - "yes": Register balancing in both directions
--@ - "forward": Moves a set of FFs at the inputs of a LUT to a single FF at its output.
--@ - "backward": Moves a single FF at the output of a LUT to a set of FFs at its inputs. - G_RegisterBalancing : string := "yes" + G_RegisterBalancing : string := "yes"; + --@ Enable pipeline buffer + --@ - true : Use pipeline buffer + --@ - false : Direct connection (bypass) + G_EnablePipelineBuffer : boolean := true; + --@ How many Pipeline modules shall be chained? + G_PipelineModules : integer := 250; + --@ Enable chip enable signal + G_Enable_CE : boolean := false; + --@ Enable reset signal + G_Enable_RST : boolean := false ); port ( I_CLK : in std_logic; I_RST : in std_logic; I_CE : in std_logic; + --- I_Data : in std_logic_vector(G_Width - 1 downto 0); I_Valid : in std_logic; O_Ready : out std_logic; + --- O_Data : out std_logic_vector(G_Width - 1 downto 0); O_Valid : out std_logic; I_Ready : in std_logic @@ -36,119 +48,116 @@ entity Pipeline_pb is end entity Pipeline_pb; architecture RTL of Pipeline_pb is - -- Keep attribute: Prevents the synthesis tool from removing the entity if is "true". + --------------------------------------------------------------------------- + -- Attribute helpers + --------------------------------------------------------------------------- attribute keep : string; - -- IOB attribute: Attaches the FF to the IOB if is "true". attribute IOB : string; - -- General Interace - signal R_RST : std_logic; - signal R_CE : std_logic; - -- Attribute + --------------------------------------------------------------------------- + -- Bench‐wrapper FFs (synchronous IO) + --------------------------------------------------------------------------- + signal R_RST : std_logic := '0'; + signal R_CE : std_logic := '1'; attribute keep of R_RST, R_CE : signal is "true"; attribute IOB of R_RST, R_CE : signal is "false"; - -- Input Interface - signal R_DataIn : std_logic_vector(G_Width - 1 downto 0); - signal R_ValidIn : std_logic; - signal R_ReadyOut : std_logic; - -- Attribute - attribute keep of R_DataIn, R_ValidIn, R_ReadyOut : signal is "true"; - attribute IOB of R_DataIn, R_ValidIn, R_ReadyOut : signal is "false"; + signal R_DataIn : std_logic_vector(G_Width-1 downto 0); + signal R_ValidIn : std_logic; + attribute keep of R_DataIn, R_ValidIn : signal is "true"; + attribute IOB of R_DataIn, R_ValidIn : signal is "false"; - -- Output Interface - signal R_DataOut : std_logic_vector(G_Width - 1 downto 0); + signal R_DataOut : std_logic_vector(G_Width-1 downto 0); signal R_ValidOut : std_logic; signal R_ReadyIn : std_logic; - -- Attribute attribute keep of R_DataOut, R_ValidOut, R_ReadyIn : signal is "true"; attribute IOB of R_DataOut, R_ValidOut, R_ReadyIn : signal is "false"; - signal C_Pipeline0Enable : std_logic; - signal C_Pipeline1Enable : std_logic; + --------------------------------------------------------------------------- + -- Chaining arrays (sentinel element @0 and @G_PipelineModules) + --------------------------------------------------------------------------- + type T_DataArray is array(0 to G_PipelineModules) of std_logic_vector(G_Width-1 downto 0); + + signal S_Data : T_DataArray; + signal S_Valid : std_logic_vector(0 to G_PipelineModules); + signal S_Ready : std_logic_vector(0 to G_PipelineModules); - signal R_Valid : std_logic; - signal R_Ready : std_logic; - signal R_Data : std_logic_vector(G_Width - 1 downto 0); begin + GEN_Enable_CE : if G_Enable_CE = true generate + process(I_CLK) + begin + if rising_edge(I_CLK) then + R_CE <= I_CE; + end if; + end process; + end generate GEN_Enable_CE; - BenchmarkEnvironmentFFs : process (I_CLK) + GEN_Enable_RST : if G_Enable_RST = true generate + process(I_CLK) + begin + if rising_edge(I_CLK) then + R_RST <= I_RST; + end if; + end process; + end generate GEN_Enable_RST; + + ----------------------------------------------------------------------- + -- Wrapper FFs: register all top‑level ports once for fair timing + ----------------------------------------------------------------------- + BenchFF : process(I_CLK) begin if rising_edge(I_CLK) then - -- General Interace - R_RST <= I_RST; - R_CE <= I_CE; - - -- Input Interface - R_DataIn <= I_Data; - R_ValidIn <= I_Valid; - O_Ready <= R_ReadyOut; - - -- Output Interface - O_Data <= R_DataOut; - O_Valid <= R_ValidOut; - R_ReadyIn <= I_Ready; + --- Register inputs + R_DataIn <= I_Data; + R_ValidIn <= I_Valid; + O_Ready <= S_Ready(0); + --- Register outputs + R_DataOut <= S_Data (G_PipelineModules); + R_ValidOut <= S_Valid(G_PipelineModules); + R_ReadyIn <= I_Ready; end if; end process; - PipelineControllerIn : entity work.PipelineController - generic map( - G_PipelineStages => G_PipelineStages, - G_ResetActiveAt => '1' - ) - port map( - I_CLK => I_CLK, - I_RST => R_RST, - I_CE => R_CE, - O_Enable => C_Pipeline0Enable, - I_Valid => R_ValidIn, - O_Ready => R_ReadyOut, - O_Valid => R_Valid, - I_Ready => R_Ready - ); + O_Data <= R_DataOut; + O_Valid <= R_ValidOut; - PipelineRegisterIn : entity work.PipelineRegister - generic map( - G_PipelineStages => G_PipelineStages, - G_Width => G_Width, - G_RegisterBalancing => G_RegisterBalancing - ) - port map( - I_CLK => I_CLK, - I_Enable => C_Pipeline0Enable, - I_Data => R_DataIn, - O_Data => R_Data - ); + ----------------------------------------------------------------------- + -- Bind sentinel 0 with registered inputs + ----------------------------------------------------------------------- + S_Data (0) <= R_DataIn; + S_Valid(0) <= R_ValidIn; - --------- + ----------------------------------------------------------------------- + -- Bind last sentinel with registered outputs + ----------------------------------------------------------------------- + S_Ready(G_PipelineModules) <= R_ReadyIn; - PipelineControllerOut : entity work.PipelineController - generic map( - G_PipelineStages => G_PipelineStages, - G_ResetActiveAt => '1' - ) - port map( - I_CLK => I_CLK, - I_RST => R_RST, - I_CE => R_CE, - O_Enable => C_Pipeline1Enable, - I_Valid => R_Valid, - O_Ready => R_Ready, - O_Valid => R_ValidOut, - I_Ready => R_ReadyIn - ); + ----------------------------------------------------------------------- + -- Generate N pipeline modules in series + ----------------------------------------------------------------------- + gen_modules : for i in 0 to G_PipelineModules-1 generate - PipelineRegisterOut : entity work.PipelineRegister - generic map( - G_PipelineStages => G_PipelineStages, - G_Width => G_Width, - G_RegisterBalancing => G_RegisterBalancing - ) - port map( - I_CLK => I_CLK, - I_Enable => C_Pipeline1Enable, - I_Data => R_Data, - O_Data => R_DataOut - ); + P_MOD : entity work.Pipeline_pb_Module + generic map( + G_PipelineStages => G_PipelineStages, + G_Width => G_Width, + G_RegisterBalancing => G_RegisterBalancing, + G_EnablePipelineBuffer => G_EnablePipelineBuffer + ) + port map( + I_CLK => I_CLK, + I_RST => R_RST, + I_CE => R_CE, + -- Up‑stream side + I_Data => S_Data (i), + I_Valid => S_Valid(i), + O_Ready => S_Ready(i), + -- Down‑stream side + O_Data => S_Data (i+1), + O_Valid => S_Valid(i+1), + I_Ready => S_Ready(i+1) + ); + + end generate gen_modules; end architecture RTL; diff --git a/src/Pipeline_pb_Module.vhd b/src/Pipeline_pb_Module.vhd new file mode 100644 index 0000000..bb59bb0 --- /dev/null +++ b/src/Pipeline_pb_Module.vhd @@ -0,0 +1,123 @@ +--@ Performance Benchmarking Environment +--@ This file is a wrapper for the module which is to be tested +--@ and capsulates the module with flip-flops to create a synchronous +--@ interface for the module. This is necessary to test the synthesis +--@ results of the module. + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +entity Pipeline_pb_Module is + generic ( + --@ Number of pipeline stages + G_PipelineStages : integer := 10; + --@ Data width + G_Width : integer := 32; + --@ Register balancing attribute
+ --@ - "no" : No register balancing
+ --@ - "yes": Register balancing in both directions
+ --@ - "forward": Moves a set of FFs at the inputs of a LUT to a single FF at its output.
+ --@ - "backward": Moves a single FF at the output of a LUT to a set of FFs at its inputs. + G_RegisterBalancing : string := "no"; + --@ Enable pipeline buffer + --@ - true : Use pipeline buffer + --@ - false : Direct connection (bypass) + G_EnablePipelineBuffer : boolean := false + ); + port ( + I_CLK : in std_logic; + I_RST : in std_logic; + I_CE : in std_logic; + I_Data : in std_logic_vector(G_Width - 1 downto 0); + I_Valid : in std_logic; + O_Ready : out std_logic; + O_Data : out std_logic_vector(G_Width - 1 downto 0); + O_Valid : out std_logic; + I_Ready : in std_logic + ); +end entity Pipeline_pb_Module; + +architecture RTL of Pipeline_pb_Module is + signal C_Pipeline0Enable : std_logic; + signal C_PipelineBufferEnable : std_logic_vector(1 downto 0) := (others => '0'); + + signal R_Valid : std_logic; + signal R_Ready : std_logic; + signal R_Data : std_logic_vector(G_Width - 1 downto 0); + signal C_Data : std_logic_vector(G_Width - 1 downto 0); +begin + PipelineControllerIn : entity work.PipelineController + generic map( + G_PipelineStages => G_PipelineStages, + G_ResetActiveAt => '1' + ) + port map( + I_CLK => I_CLK, + I_RST => I_RST, + I_CE => I_CE, + O_Enable => C_Pipeline0Enable, + I_Valid => I_Valid, + O_Ready => O_Ready, + O_Valid => R_Valid, + I_Ready => R_Ready + ); + + PipelineRegisterIn : entity work.PipelineRegister + generic map( + G_PipelineStages => G_PipelineStages, + G_Width => G_Width, + G_RegisterBalancing => G_RegisterBalancing + ) + port map( + I_CLK => I_CLK, + I_Enable => C_Pipeline0Enable, + I_Data => I_Data, + O_Data => R_Data + ); + + --------- + + C_Data <= std_logic_vector(unsigned(R_Data) + 3); -- Example operation, can be replaced with actual logic + + --------- + + -- Pipeline Buffer Generation based on G_EnablePipelineBuffer + gen_pipeline_buffer : if G_EnablePipelineBuffer generate + PipelineBufferController : entity work.PipelineBufferController + generic map( + G_ResetActiveAt => '1' + ) + port map( + I_CLK => I_CLK, + I_RST => I_RST, + I_CE => I_CE, + O_Enable => C_PipelineBufferEnable, + I_Valid => R_Valid, + O_Ready => R_Ready, + O_Valid => O_Valid, + I_Ready => I_Ready + ); + + PipelineBuffer : entity work.PipelineBuffer + generic map( + G_Width => G_Width + ) + port map( + I_CLK => I_CLK, + I_Enable => C_PipelineBufferEnable, + I_Data => C_Data, + O_Data => O_Data + ); + end generate gen_pipeline_buffer; + + -- Direct connection when pipeline buffer is disabled + gen_direct_connection : if not G_EnablePipelineBuffer generate + -- Direct signal connections (bypass pipeline buffer) + O_Valid <= R_Valid; + O_Data <= R_Data; + R_Ready <= I_Ready; + end generate gen_direct_connection; + +end architecture RTL;