diff --git a/.gitignore b/.gitignore index fd6e778..acabbfd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -build/working \ No newline at end of file +build/working +.locale/ +vhdl_ls.toml diff --git a/src/PipelineController.vhd b/src/PipelineController.vhd index 23c880e..3d2ade3 100644 --- a/src/PipelineController.vhd +++ b/src/PipelineController.vhd @@ -48,7 +48,6 @@ --@ - 0.0.1 (2024-03-24) Initial version --@ - 0.0.2 (2024-04-13) Enhanced the validity update logic to correctly handle configurations with a single pipeline stage ---------------------------------------------------------------------------------- - library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; @@ -57,31 +56,34 @@ use ieee.math_real.all; entity PipelineController is generic ( --@ Number of pipeline stages (FFs in the pipeline including I/O FFs) - G_PipelineStages : integer := 3; + G_PipelineStages : integer := 3; --@ Reset active at this level - G_ResetActiveAt : std_logic := '1' + G_ResetActiveAt : std_logic := '1' ); port ( --@ Clock signal; **Rising edge** triggered - I_CLK : in std_logic; + I_CLK : in std_logic := '0'; --@ Reset signal; Active at `G_ResetActiveAt` - I_RST : in std_logic; + I_RST : in std_logic := '0'; --@ Chip enable; Active high - I_CE : in std_logic; + I_CE : in std_logic := '1'; + --@ Pipeline enable; Active high when pipeline can accept data and `I_CE` is high.
--@ **Note:** Connect `CE` of the registers to be controlled by this controller to `O_Enable`. - O_Enable : out std_logic; + O_Enable : out std_logic := '0'; + --@ @virtualbus Input-AXI-Handshake @dir in Input AXI like Handshake --@ Valid data flag; indicates that the data on `I_Data` of the connected registers is valid. - I_Valid : in std_logic; + I_Valid : in std_logic := '0'; --@ Ready flag; indicates that the connected registers is ready to accept data. - O_Ready : out std_logic; + O_Ready : out std_logic := '0'; --@ @end + --@ @virtualbus Output-AXI-Handshake @dir out Output AXI like Handshake --@ Valid data flag; indicates that the data on `O_Data` of the connected registers is valid. - O_Valid : out std_logic; + O_Valid : out std_logic := '0'; --@ Ready flag; indicates that the external component is ready to accept data. - I_Ready : in std_logic + I_Ready : in std_logic := '0' --@ @end ); end entity PipelineController; @@ -91,59 +93,75 @@ architecture RTL of PipelineController is signal R_Valid : std_logic_vector(G_PipelineStages - 1 downto 0) := (others => '0'); --@ Ready signal for the pipeline controller to indicate that the pipeline can accept data;
--@ mapped to `O_Enable` and `O_Ready` ports. - signal C_Ready : std_logic := '1'; + signal C_Ready : std_logic := '1'; begin - --@ Produce the `O_Valid`, `O_Enable`, and `O_Ready` signals for the pipeline controller.
- --@ - `O_Enable`, and `O_Ready` are **and** combined from the `C_Ready` and `I_CE` signals.
- --@ - `O_Valid` is the last bit of the `R_Valid` signal - --@ and represents the validity of the data in the last stage of the pipeline. - P_ExternalFlags : process (R_Valid, C_Ready, I_CE) - begin - O_Valid <= R_Valid(R_Valid'high); + GEN_ForwardExternalFlags : if G_PipelineStages = 0 generate + --@ If no pipeline stages are defined, the flags are directly connected to the input and output ports. + P_ExternalFlags : process (I_CE, I_Valid, I_Ready) + begin + O_Valid <= I_Valid; + O_Enable <= I_Ready and I_CE; + O_Ready <= I_Ready and I_CE; + end process; + end generate; - O_Enable <= C_Ready and I_CE; - O_Ready <= C_Ready and I_CE; - end process; + GEN_ExternalFlags : if G_PipelineStages > 0 generate + --@ Produce the `O_Valid`, `O_Enable`, and `O_Ready` signals for the pipeline controller.
+ --@ - `O_Enable`, and `O_Ready` are **and** combined from the `C_Ready` and `I_CE` signals.
+ --@ - `O_Valid` is the last bit of the `R_Valid` signal + --@ and represents the validity of the data in the last stage of the pipeline. + P_ExternalFlags : process (R_Valid, C_Ready, I_CE) + begin + O_Valid <= R_Valid(R_Valid'high); - --@ Produce the `C_Ready` signal for the pipeline controller, - --@ controlling the data flow in the pipeline.
- --@ `C_Ready` is asserted when the data is available in the last stage of the pipeline - --@ **and** the external component is ready to accept data - --@ **or** when no data is available in the last stage of the pipeline. - P_InternalFlags : process (R_Valid, I_Ready) - begin - if R_Valid(R_Valid'high) = '1' then - -- Data is available in the last stage of the pipeline. - if I_Ready = '1' then - -- O_Data is accepted from the external component. - C_Ready <= '1'; + O_Enable <= C_Ready and I_CE; + O_Ready <= C_Ready and I_CE; + end process; + end generate; + + GEN_InternalFlags : if G_PipelineStages > 0 generate + --@ Produce the `C_Ready` signal for the pipeline controller, + --@ controlling the data flow in the pipeline.
+ --@ `C_Ready` is asserted when the data is available in the last stage of the pipeline + --@ **and** the external component is ready to accept data + --@ **or** when no data is available in the last stage of the pipeline. + P_InternalFlags : process (R_Valid, I_Ready) + begin + if R_Valid(R_Valid'high) = '1' then + -- Data is available in the last stage of the pipeline. + if I_Ready = '1' then + -- O_Data is accepted from the external component. + C_Ready <= '1'; + else + -- O_Data is not accepted from the external component. + C_Ready <= '0'; + end if; else - -- O_Data is not accepted from the external component. - C_Ready <= '0'; + -- No data available in the last stage of the pipeline. + C_Ready <= '1'; end if; - else - -- No data available in the last stage of the pipeline. - C_Ready <= '1'; - end if; - end process; + end process; + end generate; - --@ Shift the pipeline stages with `R_Valid` signal as placeholder to control - --@ the validity of the data in the individual pipeline stages. - P_ValidPipeline : process (I_CLK) - begin - if rising_edge(I_CLK) then - if I_RST = G_ResetActiveAt then - R_Valid <= (others => '0'); - elsif I_CE = '1' then - if C_Ready = '1' then - if G_PipelineStages = 1 then - R_Valid(0) <= I_Valid; - else - R_Valid <= R_Valid(R_Valid'high - 1 downto R_Valid'low) & I_Valid; + GEN_ValidPipe : if G_PipelineStages > 0 generate + --@ Shift the pipeline stages with `R_Valid` signal as placeholder to control + --@ the validity of the data in the individual pipeline stages. + P_ValidPipeline : process (I_CLK) + begin + if rising_edge(I_CLK) then + if I_RST = G_ResetActiveAt then + R_Valid <= (others => '0'); + elsif I_CE = '1' then + if C_Ready = '1' then + if G_PipelineStages = 1 then + R_Valid(0) <= I_Valid; + else + R_Valid <= R_Valid(R_Valid'high - 1 downto R_Valid'low) & I_Valid; + end if; end if; end if; end if; - end if; - end process; -end architecture RTL; \ No newline at end of file + end process; + end generate; +end architecture RTL; diff --git a/src/PipelineRegister.vhd b/src/PipelineRegister.vhd index d2d5403..b09c352 100644 --- a/src/PipelineRegister.vhd +++ b/src/PipelineRegister.vhd @@ -39,9 +39,9 @@ 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; + G_PipelineStages : integer := 3; --@ Data width - G_Width : integer := 32; + G_Width : integer := 32; --@ Register balancing attribute
--@ - `no` : **Disable** register balancing,
--@ - `yes`: **Enable** register balancing in both directions,
@@ -49,17 +49,17 @@ entity PipelineRegister is --@ 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" + G_RegisterBalancing : string := "yes" ); port ( - --@ Clock signal; **Rising edge** triggered - I_CLK : in std_logic; + --@ Clock; (**Rising edge** triggered) + I_CLK : in std_logic := '0'; --@ Enable input from **Pipeline Controller** - I_Enable : in std_logic; + I_Enable : in std_logic := '0'; --@ Data input - I_Data : in std_logic_vector(G_Width - 1 downto 0); + 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') + O_Data : out std_logic_vector(G_Width - 1 downto 0) := (others => '0') ); end entity PipelineRegister; @@ -69,35 +69,50 @@ architecture RTL of PipelineRegister is --@ 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')); + 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 - --@ 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; + --@ 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 if; - end process; + end process; + end 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; + --@ 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; -end architecture RTL; \ No newline at end of file + --@ 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;