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:
@@ -4,23 +4,73 @@
|
|||||||
|
|
||||||
## Diagram
|
## Diagram
|
||||||

|

|
||||||
|
## Description
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
## Generics
|
## Generics
|
||||||
|
|
||||||
| Generic name | Type | Value | Description |
|
| Generic name | Type | Value | Description |
|
||||||
| ---------------- | --------- | ----- | ------------------------- |
|
| ---------------- | --------- | ----- | ----------------------------------------------------------------- |
|
||||||
| G_PipelineStages | integer | 3 | Number of pipeline stages |
|
| G_PipelineStages | integer | 3 | Number of pipeline stages (FFs in the pipeline including I/O FFs) |
|
||||||
| G_ResetActiveAt | std_logic | '1' | Reset active at: |
|
| G_ResetActiveAt | std_logic | '1' | Reset active at this level |
|
||||||
|
|
||||||
## Ports
|
## Ports
|
||||||
|
|
||||||
| Port name | Direction | Type | Description |
|
| Port name | Direction | Type | Description |
|
||||||
| -------------------- | --------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| -------------------- | --------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| I_CLK | in | std_logic | Clock signal; **Rising edge** triggered |
|
| I_CLK | in | std_logic | Clock signal; **Rising edge** triggered |
|
||||||
| I_RST | in | std_logic | Reset signal; Active at `G_ResetActiveAt` |
|
| I_RST | in | std_logic | Reset signal; Active at `G_ResetActiveAt` |
|
||||||
| I_CE | in | std_logic | Chip enable; Active high |
|
| I_CE | in | std_logic | Chip enable; Active high |
|
||||||
| O_Enable | out | 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. |
|
| O_Enable | out | std_logic | Pipeline enable; Active high when pipeline can accept data and `I_CE` is high. <br> **Note:** Connect `CE` of the registers to be controlled by this controller to `O_Enable`. |
|
||||||
| Input-AXI-Handshake | in | Virtual bus | Input AXI like Handshake |
|
| Input-AXI-Handshake | in | Virtual bus | Input AXI like Handshake |
|
||||||
| Output-AXI-Handshake | out | Virtual bus | Output AXI like Handshake |
|
| Output-AXI-Handshake | out | Virtual bus | Output AXI like Handshake |
|
||||||
|
|
||||||
### Virtual Buses
|
### Virtual Buses
|
||||||
|
|
||||||
@@ -45,9 +95,12 @@
|
|||||||
| C_Ready | std_logic | Ready signal for the pipeline controller to indicate that the pipeline can accept data; <br> mapped to `O_Enable` and `O_Ready` ports. |
|
| C_Ready | std_logic | Ready signal for the pipeline controller to indicate that the pipeline can accept data; <br> mapped to `O_Enable` and `O_Ready` ports. |
|
||||||
|
|
||||||
## Processes
|
## Processes
|
||||||
- P_Flags: ( R_Valid, I_Ready )
|
- P_ExternalFlags: ( R_Valid, C_Ready, I_CE )
|
||||||
- **Description**
|
- **Description**
|
||||||
Produce the `C_Ready` signal for the pipeline controller, controlling the data flow in the pipeline.
|
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_InternalFlags: ( R_Valid, I_Ready )
|
||||||
|
- **Description**
|
||||||
|
Produce the `C_Ready` signal for the pipeline controller, 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_ValidPipeline: ( I_CLK )
|
- P_ValidPipeline: ( I_CLK )
|
||||||
- **Description**
|
- **Description**
|
||||||
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.
|
||||||
|
@@ -4,13 +4,47 @@
|
|||||||
|
|
||||||
## Diagram
|
## Diagram
|
||||||

|

|
||||||
|
## Description
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
## Generics
|
## Generics
|
||||||
|
|
||||||
| Generic name | Type | Value | Description |
|
| Generic name | Type | Value | Description |
|
||||||
| ------------------- | ------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------- | ------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| G_PipelineStages | integer | 3 | Number of pipeline stages |
|
| G_PipelineStages | integer | 3 | Number of pipeline stages (Correspondent to the number of registers in the pipeline) |
|
||||||
| G_Width | integer | 32 | Data width |
|
| G_Width | integer | 32 | Data width |
|
||||||
| G_RegisterBalancing | string | "yes" | 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. |
|
| G_RegisterBalancing | string | "yes" | Register balancing attribute<br> - `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. |
|
||||||
|
|
||||||
## Ports
|
## Ports
|
||||||
|
|
||||||
@@ -36,4 +70,7 @@
|
|||||||
## Processes
|
## Processes
|
||||||
- P_PipelineRegister: ( I_CLK )
|
- P_PipelineRegister: ( I_CLK )
|
||||||
- **Description**
|
- **Description**
|
||||||
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_ForwardData: ( R_Data )
|
||||||
|
- **Description**
|
||||||
|
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**
|
||||||
|
@@ -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;
|
library ieee;
|
||||||
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
||||||
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
||||||
@@ -5,9 +55,9 @@ use ieee.math_real.all;
|
|||||||
|
|
||||||
entity PipelineController is
|
entity PipelineController is
|
||||||
generic (
|
generic (
|
||||||
--@ Number of pipeline stages
|
--@ Number of pipeline stages (FFs in the pipeline including I/O FFs)
|
||||||
G_PipelineStages : integer := 3;
|
G_PipelineStages : integer := 3;
|
||||||
--@ Reset active at:
|
--@ Reset active at this level
|
||||||
G_ResetActiveAt : std_logic := '1'
|
G_ResetActiveAt : std_logic := '1'
|
||||||
);
|
);
|
||||||
port (
|
port (
|
||||||
@@ -18,7 +68,7 @@ entity PipelineController is
|
|||||||
--@ Chip enable; Active high
|
--@ Chip enable; Active high
|
||||||
I_CE : in std_logic;
|
I_CE : in std_logic;
|
||||||
--@ Pipeline enable; Active high when pipeline can accept data and `I_CE` is high. <br>
|
--@ 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;
|
O_Enable : out std_logic;
|
||||||
--@ @virtualbus Input-AXI-Handshake @dir in Input AXI like Handshake
|
--@ @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.
|
--@ 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';
|
signal C_Ready : std_logic := '1';
|
||||||
begin
|
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_Enable <= C_Ready and I_CE;
|
||||||
O_Ready <= C_Ready and I_CE;
|
O_Ready <= C_Ready and I_CE;
|
||||||
|
end process;
|
||||||
|
|
||||||
--@ Produce the `C_Ready` signal for the pipeline controller,
|
--@ Produce the `C_Ready` signal for the pipeline controller,
|
||||||
--@ controlling the data flow in the pipeline.
|
--@ controlling the data flow in the pipeline. <br>
|
||||||
P_Flags : process (R_Valid, I_Ready)
|
--@ `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
|
begin
|
||||||
if R_Valid(R_Valid'high) = '1' then
|
if R_Valid(R_Valid'high) = '1' then
|
||||||
-- Data is available in the last stage of the pipeline.
|
-- Data is available in the last stage of the pipeline.
|
||||||
@@ -67,7 +127,8 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
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)
|
P_ValidPipeline : process (I_CLK)
|
||||||
begin
|
begin
|
||||||
if rising_edge(I_CLK) then
|
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;
|
library ieee;
|
||||||
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
||||||
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
||||||
@@ -5,15 +38,17 @@ use ieee.math_real.all;
|
|||||||
|
|
||||||
entity PipelineRegister is
|
entity PipelineRegister is
|
||||||
generic (
|
generic (
|
||||||
--@ Number of pipeline stages
|
--@ Number of pipeline stages (Correspondent to the number of registers in the pipeline)
|
||||||
G_PipelineStages : integer := 3;
|
G_PipelineStages : integer := 3;
|
||||||
--@ Data width
|
--@ Data width
|
||||||
G_Width : integer := 32;
|
G_Width : integer := 32;
|
||||||
--@ Register balancing attribute<br>
|
--@ Register balancing attribute<br>
|
||||||
--@ - "no" : **Disable** register balancing, <br>
|
--@ - `no` : **Disable** register balancing, <br>
|
||||||
--@ - "yes": **Enable** register balancing in both directions, <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>
|
--@ - `forward`: **Enable** register balancing
|
||||||
--@ - "backward": **Enable** and moves a single FF at the output of a LUT to a set of FFs at its inputs.
|
--@ 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"
|
G_RegisterBalancing : string := "yes"
|
||||||
);
|
);
|
||||||
port (
|
port (
|
||||||
@@ -39,15 +74,18 @@ architecture RTL of PipelineRegister is
|
|||||||
attribute register_balancing of R_Data : signal is G_RegisterBalancing;
|
attribute register_balancing of R_Data : signal is G_RegisterBalancing;
|
||||||
begin
|
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)
|
P_PipelineRegister : process (I_CLK)
|
||||||
begin
|
begin
|
||||||
if rising_edge(I_CLK) then
|
if rising_edge(I_CLK) then
|
||||||
if I_Enable = '1' then
|
if I_Enable = '1' then
|
||||||
for i in 0 to G_PipelineStages - 1 loop
|
for i in 0 to G_PipelineStages - 1 loop
|
||||||
if i = 0 then
|
if i = 0 then
|
||||||
|
--@ Input data from the input port to the first stage of the pipeline register
|
||||||
R_Data(i) <= I_Data;
|
R_Data(i) <= I_Data;
|
||||||
else
|
else
|
||||||
|
--@ Data from the previous stage of the pipeline register to the current stage
|
||||||
R_Data(i) <= R_Data(i - 1);
|
R_Data(i) <= R_Data(i - 1);
|
||||||
end if;
|
end if;
|
||||||
end loop;
|
end loop;
|
||||||
@@ -55,6 +93,11 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
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;
|
end architecture RTL;
|
@@ -1,21 +1,29 @@
|
|||||||
library ieee;
|
library ieee;
|
||||||
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
||||||
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
||||||
|
use ieee.math_real.all;
|
||||||
|
|
||||||
entity Pipeline_tb is
|
entity Pipeline_tb is
|
||||||
-- The testbench does not require any ports
|
-- The testbench does not require any ports
|
||||||
end entity Pipeline_tb;
|
end entity Pipeline_tb;
|
||||||
|
|
||||||
architecture behavior of Pipeline_tb is
|
architecture behavior of Pipeline_tb is
|
||||||
|
shared variable seed1 : integer := 483;
|
||||||
|
shared variable seed2 : integer := 847;
|
||||||
|
impure function rand_int(min_val, max_val : integer) return integer is
|
||||||
|
variable r : real;
|
||||||
|
begin
|
||||||
|
uniform(seed1, seed2, r);
|
||||||
|
return integer(
|
||||||
|
round(r * real(max_val - min_val + 1) + real(min_val) - 0.5));
|
||||||
|
end function;
|
||||||
|
|
||||||
-- Clock signal period
|
-- Clock signal period
|
||||||
constant period : time := 20 ns;
|
constant period : time := 20 ns;
|
||||||
|
|
||||||
-- Adjustable wait times
|
-- Adjustable wait times
|
||||||
constant write_delay : natural := 0; -- Wait time between write operations in clock cycles
|
constant write_delay : natural := 10; -- Maximal wait time between write operations in clock cycles
|
||||||
constant read_delay : natural := 0; -- Wait time between read operations in clock cycles
|
constant read_delay : natural := 10; -- Maximal wait time between read operations in clock cycles
|
||||||
|
|
||||||
-- Adjustable number of data values to be written
|
|
||||||
constant writes : natural := 100;
|
|
||||||
|
|
||||||
-- Setting constants for the FIFO to be tested
|
-- Setting constants for the FIFO to be tested
|
||||||
constant K_Width : integer := 32; -- Data width of the FIFO
|
constant K_Width : integer := 32; -- Data width of the FIFO
|
||||||
@@ -25,22 +33,18 @@ architecture behavior of Pipeline_tb is
|
|||||||
-- Testbench signals
|
-- Testbench signals
|
||||||
signal CLK : std_logic := '0';
|
signal CLK : std_logic := '0';
|
||||||
signal RST : std_logic := '1';
|
signal RST : std_logic := '1';
|
||||||
|
signal CE : std_logic := '1';
|
||||||
|
|
||||||
signal I_WriteCE : std_logic := '0';
|
signal I_Data : std_logic_vector(K_Width - 1 downto 0) := (others => 'U');
|
||||||
signal I_Data : std_logic_vector(K_Width - 1 downto 0) := (others => 'U');
|
signal I_Valid : std_logic := '0';
|
||||||
signal I_Valid : std_logic := '0';
|
signal O_Ready : std_logic;
|
||||||
signal O_Ready : std_logic;
|
|
||||||
|
|
||||||
signal I_ReadCE : std_logic := '0';
|
signal O_Data : std_logic_vector(K_Width - 1 downto 0) := (others => 'U');
|
||||||
signal O_Data : std_logic_vector(K_Width - 1 downto 0);
|
signal O_Valid : std_logic;
|
||||||
signal O_Valid : std_logic;
|
signal I_Ready : std_logic := '0';
|
||||||
signal I_Ready : std_logic := '0';
|
|
||||||
|
|
||||||
signal CE : std_logic := '1';
|
|
||||||
|
|
||||||
signal PipelineEnable : std_logic;
|
signal PipelineEnable : std_logic;
|
||||||
begin
|
begin
|
||||||
CE <= I_WriteCE or I_ReadCE;
|
|
||||||
|
|
||||||
uut0 : entity work.PipelineController
|
uut0 : entity work.PipelineController
|
||||||
generic map(
|
generic map(
|
||||||
@@ -72,61 +76,79 @@ begin
|
|||||||
);
|
);
|
||||||
|
|
||||||
-- Clock process
|
-- Clock process
|
||||||
clocking : process
|
Clocking : process
|
||||||
begin
|
begin
|
||||||
while true loop
|
while true loop
|
||||||
CLK <= '0';
|
CLK <= '0';
|
||||||
wait for period / 2;
|
wait for (period / 2);
|
||||||
CLK <= '1';
|
CLK <= '1';
|
||||||
wait for period / 2;
|
wait for (period / 2);
|
||||||
end loop;
|
end loop;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
-- Write process adapted for the falling edge of the clock signal
|
-- Clock enable process
|
||||||
write_process : process
|
-- This process is used to enable the clock signal for a certain amount of time
|
||||||
begin
|
-- and only for the Pipeline Controller to check if the dataflow is working correctly.
|
||||||
wait for 100 ns; -- Initial wait time for reset and FIFO initialization
|
-- ClockEnable : process
|
||||||
RST <= '0';
|
-- begin
|
||||||
wait for period; -- Wait an additional clock cycle after reset
|
-- while true loop
|
||||||
I_WriteCE <= '1';
|
-- CE <= '1';
|
||||||
wait until falling_edge(CLK);
|
-- wait for 1000 ns;
|
||||||
for i in 0 to writes loop -- Writing loop for data values
|
-- CE <= '0';
|
||||||
if O_Ready = '0' then
|
-- wait for 500 ns;
|
||||||
wait on O_Ready until O_Ready = '1';
|
-- end loop;
|
||||||
wait until falling_edge(CLK);
|
-- end process;
|
||||||
end if;
|
|
||||||
|
|
||||||
I_Data <= std_logic_vector(to_unsigned(i, K_Width)); -- Data to be written
|
-- 100 ns Reset
|
||||||
I_Valid <= '1';
|
RST <= '1', '0' after 100 ns;
|
||||||
wait until falling_edge(CLK);
|
|
||||||
I_Valid <= '0'; -- Reset 'valid' after writing
|
|
||||||
for j in 1 to write_delay loop
|
|
||||||
wait until falling_edge(CLK); -- Wait based on the set wait time
|
|
||||||
end loop;
|
|
||||||
end loop;
|
|
||||||
I_WriteCE <= '0'; -- Deactivate write signal after writing
|
|
||||||
wait;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
-- Read process adapted for the falling edge of the clock signal
|
-- Write process
|
||||||
read_process : process
|
Write : process (CLK)
|
||||||
|
variable delay : integer := 0;
|
||||||
|
variable i : integer := 1;
|
||||||
begin
|
begin
|
||||||
wait for 110 ns; -- Delay to start writing
|
if rising_edge(CLK) then
|
||||||
I_ReadCE <= '1';
|
if RST = '1' then
|
||||||
while true loop
|
I_Valid <= '0';
|
||||||
if O_Valid = '1' and I_Ready = '0' then
|
delay := write_delay;
|
||||||
I_Ready <= '1'; -- Signal readiness to read
|
i := 1;
|
||||||
wait until falling_edge(CLK);
|
I_Data <= (others => 'U');
|
||||||
if read_delay /= 0 then
|
|
||||||
I_Ready <= '0'; -- Reset the signal after reading
|
|
||||||
end if;
|
|
||||||
for j in 1 to read_delay loop
|
|
||||||
wait until falling_edge(CLK); -- Wait based on the set wait time
|
|
||||||
end loop;
|
|
||||||
else
|
else
|
||||||
wait until falling_edge(CLK); -- Synchronize with the clock when not ready to read
|
if O_Ready = '1' and delay = 0 then
|
||||||
|
I_Data <= std_logic_vector(to_unsigned(i, K_Width)); -- Data to be written
|
||||||
|
I_Valid <= '1';
|
||||||
|
i := i + 1;
|
||||||
|
delay := rand_int(1, write_delay);
|
||||||
|
elsif O_Ready = '1' and I_Valid = '1' then
|
||||||
|
I_Valid <= '0';
|
||||||
|
end if;
|
||||||
|
if delay /= 0 then
|
||||||
|
delay := delay - 1;
|
||||||
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end loop;
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Read process
|
||||||
|
Read : process (CLK)
|
||||||
|
variable delay : integer := 0;
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK) then
|
||||||
|
if RST = '1' then
|
||||||
|
I_Ready <= '0';
|
||||||
|
delay := read_delay;
|
||||||
|
else
|
||||||
|
if O_Valid = '1' and delay = 0 then
|
||||||
|
I_Ready <= '1'; -- Signal readiness to read
|
||||||
|
delay := rand_int(1, read_delay);
|
||||||
|
elsif O_Valid = '1' and I_Ready = '1' then
|
||||||
|
I_Ready <= '0';
|
||||||
|
end if;
|
||||||
|
if delay /= 0 then
|
||||||
|
delay := delay - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
end architecture behavior;
|
end architecture behavior;
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
</top_modules>
|
</top_modules>
|
||||||
</db_ref>
|
</db_ref>
|
||||||
</db_ref_list>
|
</db_ref_list>
|
||||||
<WVObjectSize size="11" />
|
<WVObjectSize size="13" />
|
||||||
<wvobject fp_name="/pipeline_tb/clk" type="logic" db_ref_id="1">
|
<wvobject fp_name="/pipeline_tb/clk" type="logic" db_ref_id="1">
|
||||||
<obj_property name="ElementShortName">clk</obj_property>
|
<obj_property name="ElementShortName">clk</obj_property>
|
||||||
<obj_property name="ObjectShortName">clk</obj_property>
|
<obj_property name="ObjectShortName">clk</obj_property>
|
||||||
@@ -22,6 +22,10 @@
|
|||||||
<obj_property name="ElementShortName">rst</obj_property>
|
<obj_property name="ElementShortName">rst</obj_property>
|
||||||
<obj_property name="ObjectShortName">rst</obj_property>
|
<obj_property name="ObjectShortName">rst</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
|
<wvobject fp_name="/pipeline_tb/ce" type="logic" db_ref_id="1">
|
||||||
|
<obj_property name="ElementShortName">ce</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">ce</obj_property>
|
||||||
|
</wvobject>
|
||||||
<wvobject fp_name="/pipeline_tb/i_data" type="array" db_ref_id="1">
|
<wvobject fp_name="/pipeline_tb/i_data" type="array" db_ref_id="1">
|
||||||
<obj_property name="ElementShortName">i_data[31:0]</obj_property>
|
<obj_property name="ElementShortName">i_data[31:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">i_data[31:0]</obj_property>
|
<obj_property name="ObjectShortName">i_data[31:0]</obj_property>
|
||||||
@@ -47,6 +51,8 @@
|
|||||||
<wvobject fp_name="/pipeline_tb/i_ready" type="logic" db_ref_id="1">
|
<wvobject fp_name="/pipeline_tb/i_ready" type="logic" db_ref_id="1">
|
||||||
<obj_property name="ElementShortName">i_ready</obj_property>
|
<obj_property name="ElementShortName">i_ready</obj_property>
|
||||||
<obj_property name="ObjectShortName">i_ready</obj_property>
|
<obj_property name="ObjectShortName">i_ready</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#00ff00</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject fp_name="divider56" type="divider">
|
<wvobject fp_name="divider56" type="divider">
|
||||||
<obj_property name="label">Pipeline</obj_property>
|
<obj_property name="label">Pipeline</obj_property>
|
||||||
@@ -54,6 +60,10 @@
|
|||||||
<obj_property name="BkColor">128 128 255</obj_property>
|
<obj_property name="BkColor">128 128 255</obj_property>
|
||||||
<obj_property name="TextColor">230 230 230</obj_property>
|
<obj_property name="TextColor">230 230 230</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
|
<wvobject fp_name="/pipeline_tb/pipelineenable" type="logic" db_ref_id="1">
|
||||||
|
<obj_property name="ElementShortName">pipelineenable</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">pipelineenable</obj_property>
|
||||||
|
</wvobject>
|
||||||
<wvobject fp_name="group61" type="group">
|
<wvobject fp_name="group61" type="group">
|
||||||
<obj_property name="label">Controller</obj_property>
|
<obj_property name="label">Controller</obj_property>
|
||||||
<obj_property name="DisplayName">label</obj_property>
|
<obj_property name="DisplayName">label</obj_property>
|
||||||
@@ -69,10 +79,27 @@
|
|||||||
<obj_property name="ElementShortName">o_ready</obj_property>
|
<obj_property name="ElementShortName">o_ready</obj_property>
|
||||||
<obj_property name="ObjectShortName">o_ready</obj_property>
|
<obj_property name="ObjectShortName">o_ready</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject fp_name="/pipeline_tb/uut0/r_valid" type="array" db_ref_id="1">
|
<wvobject fp_name="vbus67" type="vbus" db_ref_id="1">
|
||||||
<obj_property name="ElementShortName">r_valid[2:0]</obj_property>
|
<obj_property name="label">r_valid[0:2]</obj_property>
|
||||||
<obj_property name="ObjectShortName">r_valid[2:0]</obj_property>
|
<obj_property name="DisplayName">label</obj_property>
|
||||||
<obj_property name="Radix">BINARYRADIX</obj_property>
|
<wvobject fp_name="/pipeline_tb/uut0/r_valid[0]" type="logic" db_ref_id="1">
|
||||||
|
<obj_property name="ElementShortName">[0]</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">r_valid[0]</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#ff00ff</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/pipeline_tb/uut0/r_valid[1]" type="logic" db_ref_id="1">
|
||||||
|
<obj_property name="ElementShortName">[1]</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">r_valid[1]</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#ff00ff</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/pipeline_tb/uut0/r_valid[2]" type="logic" db_ref_id="1">
|
||||||
|
<obj_property name="ElementShortName">[2]</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">r_valid[2]</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#ff00ff</obj_property>
|
||||||
|
</wvobject>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject fp_name="/pipeline_tb/uut0/o_valid" type="logic" db_ref_id="1">
|
<wvobject fp_name="/pipeline_tb/uut0/o_valid" type="logic" db_ref_id="1">
|
||||||
<obj_property name="ElementShortName">o_valid</obj_property>
|
<obj_property name="ElementShortName">o_valid</obj_property>
|
||||||
@@ -113,16 +140,22 @@
|
|||||||
<obj_property name="ElementShortName">[0]</obj_property>
|
<obj_property name="ElementShortName">[0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">r_data[0]</obj_property>
|
<obj_property name="ObjectShortName">r_data[0]</obj_property>
|
||||||
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
|
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#ff00ff</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject fp_name="/pipeline_tb/uut1/r_data[1]" type="array" db_ref_id="1">
|
<wvobject fp_name="/pipeline_tb/uut1/r_data[1]" type="array" db_ref_id="1">
|
||||||
<obj_property name="ElementShortName">[1]</obj_property>
|
<obj_property name="ElementShortName">[1]</obj_property>
|
||||||
<obj_property name="ObjectShortName">r_data[1]</obj_property>
|
<obj_property name="ObjectShortName">r_data[1]</obj_property>
|
||||||
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
|
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#ff00ff</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject fp_name="/pipeline_tb/uut1/r_data[2]" type="array" db_ref_id="1">
|
<wvobject fp_name="/pipeline_tb/uut1/r_data[2]" type="array" db_ref_id="1">
|
||||||
<obj_property name="ElementShortName">[2]</obj_property>
|
<obj_property name="ElementShortName">[2]</obj_property>
|
||||||
<obj_property name="ObjectShortName">r_data[2]</obj_property>
|
<obj_property name="ObjectShortName">r_data[2]</obj_property>
|
||||||
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
|
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#ff00ff</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject fp_name="/pipeline_tb/uut1/o_data" type="array" db_ref_id="1">
|
<wvobject fp_name="/pipeline_tb/uut1/o_data" type="array" db_ref_id="1">
|
||||||
|
Reference in New Issue
Block a user