Enhance Pipeline Controller and Register with AXI-Like Handshaking and Register Rebalancing
- Introduce comprehensive documentation for Pipeline Controller and Register, detailing core functions, generics, ports, and processes. Focus on data flow control, validity control, adjustability, and register rebalancing mechanisms. - Implement AXI-Like handshaking in Pipeline Controller for improved input and output data handling, supporting active-high ready and valid signals for efficient data transfer. - Refine Pipeline Register with register rebalancing options (no, yes, forward, backward) to optimize combinatorial logic pipelining in synthesis, configurable via `G_RegisterBalancing` generic. - Update generics and ports descriptions to reflect the inclusion of I/O FFs in pipeline depth calculation and clarify the reset active level and handshaking protocol. - Extend VHDL source for both modules to embody described functionalities and adjustments, ensuring alignment with documentation enhancements. - Augment testbench `Pipeline_tb.vhd` with random intervals for write and read operations, emphasizing dynamic testing scenarios.
This commit is contained in:
@@ -1,3 +1,53 @@
|
||||
----------------------------------------------------------------------------------
|
||||
--@ - Name: **Pipeline Controller**
|
||||
--@ - Version: 0.0.1
|
||||
--@ - Author: _Maximilian Passarello ([Blog](mpassarello.de))_
|
||||
--@ - License: [MIT](LICENSE)
|
||||
--@
|
||||
--@ The Pipeline Controller provides an easy way to construct a pipeline
|
||||
--@ with AXI-Like handshaking at the input and output of the pipeline.
|
||||
--@
|
||||
--@ ### Core functions
|
||||
--@
|
||||
--@ - **Data flow control**: Data flow control is implemented via handshaking at the input and output ports.
|
||||
--@ - **Validity control**: The controller keeps the validity of the data in the individual pipeline stages under control.
|
||||
--@ - **Adjustability**: The pipeline controller can be customized via the generics.
|
||||
--@
|
||||
--@ ### Generics
|
||||
--@
|
||||
--@ Use the generic `G_PipelineStages` to set how deep the pipeline is.
|
||||
--@ This depth contains all the registers associated with the pipeline.
|
||||
--@ For example, for an _I_FF ⇨ Combinatorics ⇨ O_FF_ construction, the generic must be set to **2**.
|
||||
--@
|
||||
--@ The active level of the reset input can also be set.
|
||||
--@
|
||||
--@ ### Clock Enable
|
||||
--@
|
||||
--@ The `I_CE` port is active high and, when deactivated,
|
||||
--@ effectively switches on the acceptance or output of data via handshaking in addition to the pipeline.
|
||||
--@
|
||||
--@ ### Reset
|
||||
--@
|
||||
--@ A reset is explicitly **not** necessary on the pipeline registers.
|
||||
--@ The validity of the data is kept under control via the pipeline controller
|
||||
--@ and only this requires a dedicated reset if necessary.
|
||||
--@
|
||||
--@ ### Pipeline control
|
||||
--@
|
||||
--@ You must connect the `O_Enable` port to the CE input of the corresponding pipeline registers.
|
||||
--@ This is used to activate or deactivate the pipeline in full or via CE deactivated state.
|
||||
--@
|
||||
--@ ### AXI like Handshaking
|
||||
--@
|
||||
--@ - **Input**: The `O_Ready` (active high) port is used to signal to the data-supplying component that data should be accepted.
|
||||
--@ If it switches on `I_Valid` (active high), this in turn signals that data is ready to be accepted at its output.
|
||||
--@ If both ports are active at the same time, the transfer is executed.
|
||||
--@ - **Output**: The process runs analogously at the pipeline output.
|
||||
--@
|
||||
--@ ## History
|
||||
--@ - 0.0.1 (2024-03-24) Initial version
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
@@ -5,9 +55,9 @@ use ieee.math_real.all;
|
||||
|
||||
entity PipelineController is
|
||||
generic (
|
||||
--@ Number of pipeline stages
|
||||
--@ Number of pipeline stages (FFs in the pipeline including I/O FFs)
|
||||
G_PipelineStages : integer := 3;
|
||||
--@ Reset active at:
|
||||
--@ Reset active at this level
|
||||
G_ResetActiveAt : std_logic := '1'
|
||||
);
|
||||
port (
|
||||
@@ -18,7 +68,7 @@ entity PipelineController is
|
||||
--@ Chip enable; Active high
|
||||
I_CE : in std_logic;
|
||||
--@ Pipeline enable; Active high when pipeline can accept data and `I_CE` is high. <br>
|
||||
--@ **Note:** Connect to `I_Enable` of the registers to be controlled by this controller.
|
||||
--@ **Note:** Connect `CE` of the registers to be controlled by this controller to `O_Enable`.
|
||||
O_Enable : out std_logic;
|
||||
--@ @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.
|
||||
@@ -43,14 +93,24 @@ architecture RTL of PipelineController is
|
||||
signal C_Ready : std_logic := '1';
|
||||
begin
|
||||
|
||||
O_Valid <= R_Valid(R_Valid'high);
|
||||
--@ Produce the `O_Valid`, `O_Enable`, and `O_Ready` signals for the pipeline controller. <br>
|
||||
--@ - `O_Enable`, and `O_Ready` are **and** combined from the `C_Ready` and `I_CE` signals. <br>
|
||||
--@ - `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);
|
||||
|
||||
O_Enable <= C_Ready and I_CE;
|
||||
O_Ready <= C_Ready and I_CE;
|
||||
O_Enable <= C_Ready and I_CE;
|
||||
O_Ready <= C_Ready and I_CE;
|
||||
end process;
|
||||
|
||||
--@ Produce the `C_Ready` signal for the pipeline controller,
|
||||
--@ controlling the data flow in the pipeline.
|
||||
P_Flags : process (R_Valid, I_Ready)
|
||||
--@ controlling the data flow in the pipeline. <br>
|
||||
--@ `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.
|
||||
@@ -67,7 +127,8 @@ begin
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--@ Shift the pipeline stages with `R_Valid` signal as placeholder to control the pipeline stages.
|
||||
--@ 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
|
||||
|
@@ -1,3 +1,36 @@
|
||||
----------------------------------------------------------------------------------
|
||||
--@ - 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;
|
||||
@@ -5,15 +38,17 @@ use ieee.math_real.all;
|
||||
|
||||
entity PipelineRegister is
|
||||
generic (
|
||||
--@ Number of pipeline stages
|
||||
--@ 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<br>
|
||||
--@ - "no" : **Disable** register balancing, <br>
|
||||
--@ - "yes": **Enable** register balancing in both directions, <br>
|
||||
--@ - "forward": **Enable** and moves a set of FFs at the inputs of a LUT to a single FF at its output, <br>
|
||||
--@ - "backward": **Enable** and moves a single FF at the output of a LUT to a set of FFs at its inputs.
|
||||
--@ - `no` : **Disable** register balancing, <br>
|
||||
--@ - `yes`: **Enable** register balancing in both directions, <br>
|
||||
--@ - `forward`: **Enable** register balancing
|
||||
--@ and moves a set of FFs at the inputs of a LUT to a single FF at its output, <br>
|
||||
--@ - `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 (
|
||||
@@ -39,15 +74,18 @@ architecture RTL of PipelineRegister is
|
||||
attribute register_balancing of R_Data : signal is G_RegisterBalancing;
|
||||
begin
|
||||
|
||||
--@ Pipeline register I_Data -> R_Data(0) -> R_Data(1) -> ... -> R_Data(G_PipelineStages - 1) -> O_Data
|
||||
--@ Pipeline register and connection of the data from the input port to the first stage of the pipeline register. <br>
|
||||
--@ **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;
|
||||
@@ -55,6 +93,11 @@ begin
|
||||
end if;
|
||||
end process;
|
||||
|
||||
O_Data <= R_Data(G_PipelineStages - 1);
|
||||
--@ Connect (combinatoric) data from the last stage of the pipeline register to the output port. <br>
|
||||
--@ 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 architecture RTL;
|
Reference in New Issue
Block a user