---------------------------------------------------------------------------------- --@ - Name: **Pipeline Register** --@ - Version: 0.0.1 --@ - Author: _Maximilian Passarello ([Blog](mpassarello.de))_ --@ - License: [MIT](LICENSE) --@ --@ The pipeline register provides a simple way to pipeline combinatorial logic using the **register rebalancing** of the synthesis. --@ --@ ### Core functions --@ --@ - **Register rebalancing**: The generic `G_RegisterBalancing` can be used --@ to precisely configure how register rebalancing works. --@ - **Number of registers**: The pipeline register instantiates a number of FFs corresponding --@ to the generic `G_PipelineStages`. --@ - **Data width**: The data width of the registers --@ and the input/output vectors (std_logic_vector) is configured via the generic `G_Width`. --@ --@ ### Register rebalancing --@ --@ The generic `G_RegisterBalancing` can be used to set the **Register Rebalancing** of the Xilinx ISE. --@ The possible variants are --@ - `no`: Deactivates the rebalancing register. --@ - `yes`: Activates the rebalancing register in both directions (forwards and backwards). --@ - `forward`: Activates the rebalancing register in the forward direction. --@ This causes the synthesis to shift and reduce a **multiple** of FFs at the inputs of a LUT --@ to a **single** FF forward at the output of a LUT. --@ - `backward`: Activates the rebalancing register in the backward direction. --@ This causes the synthesis to shift and duplicate a **single** FF at the output of a LUT --@ backwards to a **multiple** of FFs at the input of a LUT. --@ --@ ## History --@ - 0.0.1 (2024-03-24) Initial version ---------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; entity PipelineRegister is generic ( --@ Number of pipeline stages (Correspondent to the number of registers in the pipeline) G_PipelineStages : integer := 3; --@ Data width G_Width : integer := 32; --@ Register balancing attribute
--@ - `no` : **Disable** register balancing,
--@ - `yes`: **Enable** register balancing in both directions,
--@ - `forward`: **Enable** register balancing --@ and moves a set of FFs at the inputs of a LUT to a single FF at its output,
--@ - `backward`: **Enable** register balancing --@ and moves a single FF at the output of a LUT to a set of FFs at its inputs. G_RegisterBalancing : string := "yes" ); port ( --@ Clock; (**Rising edge** triggered) I_CLK : in std_logic := '0'; --@ Enable input from **Pipeline Controller** I_Enable : in std_logic := '0'; --@ Data input I_Data : in std_logic_vector(G_Width - 1 downto 0) := (others => '0'); --@ Data output O_Data : out std_logic_vector(G_Width - 1 downto 0) := (others => '0') ); end entity PipelineRegister; architecture RTL of PipelineRegister is attribute register_balancing : string; --@ Pipeline register data type; organized as an array (Stages) of std_logic_vector (Data). type T_Data is array(0 to G_PipelineStages - 1) of std_logic_vector(G_Width - 1 downto 0); --@ Pipeline register data signal; `G_PipelineStages` stages of `G_Width` bits. signal R_Data : T_Data := (others => (others => '0')); --@ Pipeline register balancing attribute from generic attribute register_balancing of R_Data : signal is G_RegisterBalancing; begin --@ Generate the pipeline registers if `G_PipelineStages` is greater than 0. GEN_PipelineRegister : if G_PipelineStages > 0 generate --@ Pipeline register and connection of the data from the input port to the first stage of the pipeline register.
--@ **I_Data -> R_Data(0) -> R_Data(1) -> ... -> R_Data(G_PipelineStages - 1)** -> O_Data P_PipelineRegister : process (I_CLK) begin if rising_edge(I_CLK) then if I_Enable = '1' then for i in 0 to G_PipelineStages - 1 loop if i = 0 then --@ Input data from the input port to the first stage of the pipeline register R_Data(i) <= I_Data; else --@ Data from the previous stage of the pipeline register to the current stage R_Data(i) <= R_Data(i - 1); end if; end loop; end if; end if; end process; end generate; --@ Generate the connection last register to the output port if `G_PipelineStages` is greater than 0. GEN_ForwardRegister : if G_PipelineStages > 0 generate --@ Connect (combinatoric) data from the last stage of the pipeline register to the output port.
--@ I_Data -> R_Data(0) -> R_Data(1) -> ... -> **R_Data(G_PipelineStages - 1) -> O_Data** P_ForwardData : process (R_Data) begin O_Data <= R_Data(G_PipelineStages - 1); end process; end generate; --@ Generate the connection of the input port to the output port if `G_PipelineStages` is 0. GEN_ForwardData : if G_PipelineStages = 0 generate --@ If `G_PipelineStages` is 0, the data from the input port is directly connected to the output port. P_ForwardData : process (I_Data) begin O_Data <= I_Data; end process; end generate; end architecture RTL;