Compare commits

...

2 Commits

Author SHA1 Message Date
3a588948a6 Adds PipelineSwitch entity and testbench
Introduces the PipelineSwitch component with configurable routing behavior based on input comparison modes. Implements modes such as "none", "or", "and", "xor", "equal", and others. Adds a comprehensive testbench to validate functionality across all supported modes.
2025-04-19 20:39:29 +00:00
286ae5a12c Adds pipeline buffer and controller with testbench
Implements a pipeline buffer component supporting passthrough and register modes, controlled via a dedicated controller.
Adds AXI-like handshake signals for data flow management.
Includes a testbench to validate functionality with randomized delays.

Addresses robust data buffering and flow control.
2025-04-19 20:39:13 +00:00
7 changed files with 1114 additions and 1 deletions

View File

@@ -29,9 +29,11 @@ VHDSOURCE += src/Pipeline_pb.vhd
VHDSOURCE += src/PipelineController.vhd
VHDSOURCE += src/PipelineRegister.vhd
VHDSOURCE += src/PipelineFilter.vhd
VHDSOURCE += src/PipelineSwitch.vhd
# VHDTEST += tests/Pipeline_tb.vhd
VHDTEST += tests/PipelineFilter_tb.vhd
# VHDTEST += tests/PipelineFilter_tb.vhd
VHDTEST += tests/PipelineSwitch_tb.vhd
## ## ## ## ## ## ## ##
# ---------------------

52
src/PipelineBuffer.vhd Normal file
View File

@@ -0,0 +1,52 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity PipelineBuffer is
generic (
--@ Data width
G_Width : integer := 32
);
port (
--@ Clock signal; (**Rising edge** triggered)
I_CLK : in std_logic := '0';
--@ Enable input from **Pipeline Buffer Controller**
--@ [1]: If low, data is passed through, else data is registered
--@ [0]: Enable for register
I_Enable : in std_logic_vector(1 downto 0) := (others => '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 PipelineBuffer;
architecture RTL of PipelineBuffer is
signal C_MUX : std_logic := '0';
signal C_Enable : std_logic := '0';
signal R_Data : std_logic_vector(G_Width - 1 downto 0) := (others => '0');
begin
C_MUX <= I_Enable(1);
C_Enable <= I_Enable(0);
P_MUX : process (C_MUX, I_Data, R_Data)
begin
if C_MUX = '0' then -- Passthrough mode
O_Data <= I_Data;
else -- Register mode
O_Data <= R_Data;
end if;
end process;
P_Register : process (I_CLK)
begin
if rising_edge(I_CLK) then
if C_Enable = '1' then
R_Data <= I_Data;
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,73 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity PipelineBufferController is
generic (
--@ Reset active at this level
G_ResetActiveAt : std_logic := '1'
);
port (
--@ Clock signal; (**Rising edge** triggered)
I_CLK : in std_logic := '0';
--@ Reset; (**Synchronous**, **Active at `G_ResetActiveAt`**)
I_RST : in std_logic := '0';
--@ Chip enable; (**Synchronous**, **Active high**)
I_CE : in std_logic := '1';
--@ [1]: If low, data is passed through, else data is registered
--@ [0]: Enable for register
O_Enable : out std_logic_vector(1 downto 0) := (others => '0');
--@ @virtualbus AXI-Flags-In @dir In Input interface for AXI-like handshake
--@ AXI like valid; (**Synchronous**, **Active high**)
I_Valid : in std_logic := '0';
--@ AXI like ready; (**Synchronous**, **Active high**)
O_Ready : out std_logic := '0';
--@ @end
--@ @virtualbus AXI-Flags-Out @dir Out Output interface for AXI-like handshake
--@ AXI like valid; (**Synchronous**, **Active high**)
O_Valid : out std_logic := '0';
--@ AXI like ready; (**Synchronous**, **Active high**)
I_Ready : in std_logic := '0'
--@ @end
);
end entity PipelineBufferController;
architecture RTL of PipelineBufferController is
signal C_MUX : std_logic := '0';
signal C_Enable : std_logic := '0';
signal R_IsBuffered : std_logic := '0';
begin
--@ Set mux to buffered mode if data is available in the buffer.
C_MUX <= R_IsBuffered;
--@ Enable the buffer register if not buffered and chip enable is high.
C_Enable <= I_CE and not R_IsBuffered;
--@ Set the ready signal to high if not buffered.
O_Ready <= not R_IsBuffered;
--@ Set the valid signal to high if data is available in the buffer or if data is valid.
O_Valid <= R_IsBuffered or I_Valid;
process (I_CLK)
begin
if rising_edge(I_CLK) then
if I_RST = G_ResetActiveAt then
R_IsBuffered <= '0';
elsif I_CE = '1' then
if R_IsBuffered = '0' and I_Valid = '1' then
R_IsBuffered <= '1';
elsif I_Ready = '1' and (R_IsBuffered or I_Valid) = '1' then
R_IsBuffered <= '0';
end if;
end if;
end if;
end process;
O_Enable(1) <= C_MUX;
O_Enable(0) <= C_Enable;
end architecture;

192
src/PipelineSwitch.vhd Normal file
View File

@@ -0,0 +1,192 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity PipelineSwitch is
generic (
--@ Width of the comparison input and mask.
--@ This defines the bit width of `I_Match` and `G_Mask`.
G_MaskWidth : integer := 4;
--@ Comparison mask or reference value used to control routing.
--@ Its width must match `G_MaskWidth`.
G_Mask : std_logic_vector := "1010";
--@ Comparison mode that determines to which output the data is routed.
--@ Available modes:
--@ - `"none"`: Always route to `Default`.
--@ - `"or"`: Route to `Selected` if **any** bit in `I_Match` matches a set bit in `G_Mask`.
--@ - `"and"`: Route to `Selected` if **all** bits set in `G_Mask` are also set in `I_Match`.
--@ - `"xor"`: Route to `Selected` if **any** bit differs between `I_Match` and `G_Mask`.
--@ - `"equal"`: Route to `Selected` if `I_Match` is **bitwise equal** to `G_Mask`.
--@ - `"not_equal"`: Route to `Selected` if `I_Match` is **not equal** to `G_Mask`.
--@ - `"gt"`: Route to `Selected` if `I_Match` **>** `G_Mask` (unsigned).
--@ - `"ge"`: Route to `Selected` if `I_Match` **≥** `G_Mask`.
--@ - `"lt"`: Route to `Selected` if `I_Match` **<** `G_Mask`.
--@ - `"le"`: Route to `Selected` if `I_Match` **≤** `G_Mask`.
G_MaskMode : string := "equal"
);
port (
--@ Input value to be compared against `G_Mask` to determine routing.
I_Match : in std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
--@ @virtualbus AXI-Flags-In @dir In Input interface for AXI-like handshake
--@ AXI-like valid; (**Synchronous**, **Active high**)
I_Valid : in std_logic := '0';
--@ AXI-like ready; (**Synchronous**, **Active high**)
O_Ready : out std_logic := '0';
--@ @end
--@ @virtualbus AXI-Flags-Out @dir Out Output interface for unmatched routing
--@ Activated when the comparison **fails**.
--@ AXI-like valid; (**Synchronous**, **Active high**)
O_Default_Valid : out std_logic := '0';
--@ AXI-like ready; (**Synchronous**, **Active high**)
I_Default_Ready : in std_logic := '0';
--@ @end
--@ @virtualbus AXI-Flags-Out @dir Out Output interface for matched routing
--@ Activated when the comparison **succeeds**.
--@ AXI-like valid; (**Synchronous**, **Active high**)
O_Selected_Valid : out std_logic := '0';
--@ AXI-like ready; (**Synchronous**, **Active high**)
I_Selected_Ready : in std_logic := '0'
--@ @end
);
end entity PipelineSwitch;
architecture RTL of PipelineSwitch is
function strings_equal(A, B : string) return boolean is
begin
if A'length /= B'length then
return false;
end if;
for i in A'range loop
if A(i) /= B(i) then
return false;
end if;
end loop;
return true;
end function;
constant K_Mode_None : string := "none";
constant K_Mode_OR : string := "or";
constant K_Mode_XOR : string := "xor";
constant K_Mode_AND : string := "and";
constant K_Mode_Equal : string := "equal";
constant K_Mode_NotEqual : string := "not_equal";
constant K_Mode_GT : string := "gt";
constant K_Mode_GE : string := "ge";
constant K_Mode_LT : string := "lt";
constant K_Mode_LE : string := "le";
signal C_ShouldRouteToSelected : std_logic := '0';
begin
assert G_Mask'length = G_MaskWidth
report "G_Mask length does not match G_MaskWidth" severity failure;
process (I_Match)
begin
if strings_equal(G_MaskMode, K_Mode_None) then
--@ No condition: Always route to Default
C_ShouldRouteToSelected <= '0';
elsif strings_equal(G_MaskMode, K_Mode_OR) then
--@ Route to Selected if any bit in I_Match is also set in G_Mask
if (I_Match and G_Mask) /= (G_MaskWidth - 1 downto 0 => '0') then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_XOR) then
--@ Route to Selected if any bit differs between I_Match and G_Mask
if (I_Match xor G_Mask) /= (G_MaskWidth - 1 downto 0 => '0') then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_AND) then
--@ Route to Selected if all bits set in G_Mask are also set in I_Match
if (I_Match and G_Mask) = G_Mask then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_Equal) then
--@ Route to Selected if I_Match is exactly equal to G_Mask
if I_Match = G_Mask then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_NotEqual) then
--@ Route to Selected if I_Match is not equal to G_Mask
if I_Match /= G_Mask then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_GT) then
--@ Route to Selected if I_Match > G_Mask (interpreted as unsigned)
if unsigned(I_Match) > unsigned(G_Mask) then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_GE) then
--@ Route to Selected if I_Match >= G_Mask (unsigned)
if unsigned(I_Match) >= unsigned(G_Mask) then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_LT) then
--@ Route to Selected if I_Match < G_Mask (unsigned)
if unsigned(I_Match) < unsigned(G_Mask) then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_LE) then
--@ Route to Selected if I_Match <= G_Mask (unsigned)
if unsigned(I_Match) <= unsigned(G_Mask) then
C_ShouldRouteToSelected <= '1';
else
C_ShouldRouteToSelected <= '0';
end if;
else
--@ Unknown comparison mode: fallback to Default
C_ShouldRouteToSelected <= '0';
end if;
end process;
process (I_Valid, I_Default_Ready, I_Selected_Ready, C_ShouldRouteToSelected)
begin
if C_ShouldRouteToSelected = '1' then
-- Route to Selected
O_Selected_Valid <= I_Valid;
O_Default_Valid <= '0';
O_Ready <= I_Selected_Ready;
else
-- Route to Default
O_Selected_Valid <= '0';
O_Default_Valid <= I_Valid;
O_Ready <= I_Default_Ready;
end if;
end process;
end architecture;

169
tests/PipelineBuffer_tb.vhd Normal file
View File

@@ -0,0 +1,169 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use std.env.stop;
entity PipelineBuffer_tb is
end entity PipelineBuffer_tb;
architecture RTL of PipelineBuffer_tb is
-- Clock signal period
constant K_Period : time := 20 ns;
-- Zufallsverzögerungen
constant K_WriteDelay : natural := 40;
constant K_ReadDelay : natural := 60;
-- Konstanten
constant G_ResetActiveAt : std_logic := '1';
constant G_Width : integer := 32;
-- Zufalls-Seed
shared variable seed1 : integer := 42;
shared variable seed2 : integer := 1337;
-- Randomfunktion
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;
-- Signale
signal I_CLK : std_logic := '0';
signal I_RST : std_logic := '1';
signal I_CE : std_logic := '1';
signal O_Enable : std_logic_vector(1 downto 0) := (others => '0');
signal I_Valid : std_logic := '0';
signal O_Ready : std_logic := '0';
signal O_Valid : std_logic := '0';
signal I_Ready : std_logic := '0';
signal I_Data : std_logic_vector(G_Width - 1 downto 0) := (others => 'U');
signal O_Data : std_logic_vector(G_Width - 1 downto 0) := (others => 'U');
begin
-- Clock
Clocking : process
begin
while true loop
I_CLK <= '0';
wait for (K_Period / 2);
I_CLK <= '1';
wait for (K_Period / 2);
end loop;
end process;
-- Reset
I_RST <= G_ResetActiveAt, not G_ResetActiveAt after 100 ns;
-- DUT: Controller
i_PipelineBufferController : entity work.PipelineBufferController
generic map(
G_ResetActiveAt => G_ResetActiveAt
)
port map(
I_CLK => I_CLK,
I_RST => I_RST,
I_CE => I_CE,
O_Enable => O_Enable,
I_Valid => I_Valid,
O_Ready => O_Ready,
O_Valid => O_Valid,
I_Ready => I_Ready
);
-- DUT: Register
i_PipelineBuffer : entity work.PipelineBuffer
generic map(
G_Width => G_Width
)
port map(
I_CLK => I_CLK,
I_Enable => O_Enable,
I_Data => I_Data,
O_Data => O_Data
);
-- Write Stimulus
Stim_Write : process
variable delay : integer := 0;
variable i : integer := 1;
variable pending : boolean := false;
begin
I_Valid <= '0';
I_Data <= (others => 'U');
wait until I_RST = '0';
while true loop
wait until rising_edge(I_CLK);
-- Neues Paket vorbereiten
if not pending and delay = 0 then
I_Data <= std_logic_vector(to_unsigned(i, G_Width));
I_Valid <= '1';
pending := true;
report "Sende Paket #" & integer'image(i) severity note;
end if;
-- Handshake erfolgt
if O_Ready = '1' and I_Valid = '1' then
I_Valid <= '0';
i := i + 1;
delay := rand_int(1, K_WriteDelay);
pending := false;
end if;
-- Verzögerung herunterzählen
if delay > 0 and not pending then
delay := delay - 1;
end if;
end loop;
end process;
-- Read Stimulus (robust)
Stim_Read : process
variable delay : integer := 0;
variable expected : integer := 1;
variable received : integer;
variable consume_now : boolean := false;
begin
I_Ready <= '0';
wait until I_RST = '0';
while true loop
wait until rising_edge(I_CLK);
-- Wenn O_Valid vorhanden und kein Delay mehr: jetzt lesen
if O_Valid = '1' and delay = 0 and not consume_now then
I_Ready <= '1';
consume_now := true; -- Warte auf nächste Gültigkeit
end if;
-- Sobald Handshake erfolgt (O_Valid & I_Ready), auswerten
if O_Valid = '1' and I_Ready = '1' and consume_now then
received := to_integer(unsigned(O_Data));
if received = expected then
report "Empfange Paket #" & integer'image(expected) severity note;
else
report "FEHLER bei Paket #" & integer'image(expected) &
": erwartet " & integer'image(expected) &
", empfangen " & integer'image(received) severity error;
end if;
expected := expected + 1;
delay := rand_int(1, K_ReadDelay);
consume_now := false;
I_Ready <= '0';
end if;
-- Wartezeit herunterzählen
if delay > 0 and not consume_now then
delay := delay - 1;
end if;
end loop;
end process;
end architecture RTL;

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<wave_config>
<wave_state>
</wave_state>
<db_ref_list>
<db_ref path="./isim.wdb" id="1" type="auto">
<top_modules>
<top_module name="env" />
<top_module name="glbl" />
<top_module name="math_real" />
<top_module name="numeric_std" />
<top_module name="pipelinebuffer_tb" />
<top_module name="std_logic_1164" />
</top_modules>
</db_ref>
</db_ref_list>
<WVObjectSize size="12" />
<wvobject fp_name="/pipelinebuffer_tb/i_clk" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">i_clk</obj_property>
<obj_property name="ObjectShortName">i_clk</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_rst" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">i_rst</obj_property>
<obj_property name="ObjectShortName">i_rst</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_ce" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">i_ce</obj_property>
<obj_property name="ObjectShortName">i_ce</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/o_enable" type="array" db_ref_id="1">
<obj_property name="ElementShortName">o_enable[1:0]</obj_property>
<obj_property name="ObjectShortName">o_enable[1:0]</obj_property>
<wvobject fp_name="/pipelinebuffer_tb/o_enable[1]" type="logic" db_ref_id="1">
<obj_property name="DisplayName">label</obj_property>
<obj_property name="ElementShortName">[1]</obj_property>
<obj_property name="ObjectShortName">o_enable[1]</obj_property>
<obj_property name="label">MUX</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/o_enable[0]" type="logic" db_ref_id="1">
<obj_property name="DisplayName">label</obj_property>
<obj_property name="ElementShortName">[0]</obj_property>
<obj_property name="ObjectShortName">o_enable[0]</obj_property>
<obj_property name="label">Enable</obj_property>
</wvobject>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_valid" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">i_valid</obj_property>
<obj_property name="ObjectShortName">i_valid</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/o_ready" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">o_ready</obj_property>
<obj_property name="ObjectShortName">o_ready</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/o_data" type="array" db_ref_id="1">
<obj_property name="ElementShortName">o_data[31:0]</obj_property>
<obj_property name="ObjectShortName">o_data[31:0]</obj_property>
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject fp_name="divider12" type="divider">
<obj_property name="label">Out</obj_property>
<obj_property name="DisplayName">label</obj_property>
<obj_property name="BkColor">128 128 255</obj_property>
<obj_property name="TextColor">230 230 230</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/o_valid" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">o_valid</obj_property>
<obj_property name="ObjectShortName">o_valid</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_ready" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">i_ready</obj_property>
<obj_property name="ObjectShortName">i_ready</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_data" type="array" db_ref_id="1">
<obj_property name="ElementShortName">i_data[31:0]</obj_property>
<obj_property name="ObjectShortName">i_data[31:0]</obj_property>
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject fp_name="group15" type="group">
<obj_property name="label">Buffer</obj_property>
<obj_property name="DisplayName">label</obj_property>
<wvobject fp_name="/pipelinebuffer_tb/i_PipelineBuffer/i_enable" type="array" db_ref_id="1">
<obj_property name="ElementShortName">i_enable[1:0]</obj_property>
<obj_property name="ObjectShortName">i_enable[1:0]</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_PipelineBuffer/i_data" type="array" db_ref_id="1">
<obj_property name="ElementShortName">i_data[31:0]</obj_property>
<obj_property name="ObjectShortName">i_data[31:0]</obj_property>
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_PipelineBuffer/o_data" type="array" db_ref_id="1">
<obj_property name="ElementShortName">o_data[31:0]</obj_property>
<obj_property name="ObjectShortName">o_data[31:0]</obj_property>
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_PipelineBuffer/c_mux" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">c_mux</obj_property>
<obj_property name="ObjectShortName">c_mux</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_PipelineBuffer/c_enable" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">c_enable</obj_property>
<obj_property name="ObjectShortName">c_enable</obj_property>
</wvobject>
<wvobject fp_name="/pipelinebuffer_tb/i_PipelineBuffer/r_data" type="array" db_ref_id="1">
<obj_property name="ElementShortName">r_data[31:0]</obj_property>
<obj_property name="ObjectShortName">r_data[31:0]</obj_property>
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
</wvobject>
</wvobject>
</wave_config>

516
tests/PipelineSwitch_tb.vhd Normal file
View File

@@ -0,0 +1,516 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity PipelineSwitch_tb is
end entity PipelineSwitch_tb;
architecture RTL of PipelineSwitch_tb is
constant G_MaskWidth : integer := 4;
constant G_Mask : std_logic_vector(G_MaskWidth - 1 downto 0) := "1101";
-- === Signals for mode "none" ===
signal I_Match_none : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_none : std_logic := '0';
signal O_Ready_none : std_logic;
signal O_Default_Valid_none : std_logic;
signal I_Default_Ready_none : std_logic := '0';
signal O_Selected_Valid_none : std_logic;
signal I_Selected_Ready_none : std_logic := '0';
-- === Signals for mode "or" ===
signal I_Match_or : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_or : std_logic := '0';
signal O_Ready_or : std_logic;
signal O_Default_Valid_or : std_logic;
signal I_Default_Ready_or : std_logic := '0';
signal O_Selected_Valid_or : std_logic;
signal I_Selected_Ready_or : std_logic := '0';
-- === Signals for mode "and" ===
signal I_Match_and : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_and : std_logic := '0';
signal O_Ready_and : std_logic;
signal O_Default_Valid_and : std_logic;
signal I_Default_Ready_and : std_logic := '0';
signal O_Selected_Valid_and : std_logic;
signal I_Selected_Ready_and : std_logic := '0';
-- === Signals for mode "xor" ===
signal I_Match_xor : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_xor : std_logic := '0';
signal O_Ready_xor : std_logic;
signal O_Default_Valid_xor : std_logic;
signal I_Default_Ready_xor : std_logic := '0';
signal O_Selected_Valid_xor : std_logic;
signal I_Selected_Ready_xor : std_logic := '0';
-- === Signals for mode "equal" ===
signal I_Match_eq : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_eq : std_logic := '0';
signal O_Ready_eq : std_logic;
signal O_Default_Valid_eq : std_logic;
signal I_Default_Ready_eq : std_logic := '0';
signal O_Selected_Valid_eq : std_logic;
signal I_Selected_Ready_eq : std_logic := '0';
-- === Signals for mode "not_eq" ===
signal I_Match_neq : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_neq : std_logic := '0';
signal O_Ready_neq : std_logic;
signal O_Default_Valid_neq : std_logic;
signal I_Default_Ready_neq : std_logic := '0';
signal O_Selected_Valid_neq : std_logic;
signal I_Selected_Ready_neq : std_logic := '0';
-- === Signals for mode "gt" ===
signal I_Match_gt : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_gt : std_logic := '0';
signal O_Ready_gt : std_logic;
signal O_Default_Valid_gt : std_logic;
signal I_Default_Ready_gt : std_logic := '0';
signal O_Selected_Valid_gt : std_logic;
signal I_Selected_Ready_gt : std_logic := '0';
-- === Signals for mode "ge" ===
signal I_Match_ge : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_ge : std_logic := '0';
signal O_Ready_ge : std_logic;
signal O_Default_Valid_ge : std_logic;
signal I_Default_Ready_ge : std_logic := '0';
signal O_Selected_Valid_ge : std_logic;
signal I_Selected_Ready_ge : std_logic := '0';
-- === Signals for mode "lt" ===
signal I_Match_lt : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_lt : std_logic := '0';
signal O_Ready_lt : std_logic;
signal O_Default_Valid_lt : std_logic;
signal I_Default_Ready_lt : std_logic := '0';
signal O_Selected_Valid_lt : std_logic;
signal I_Selected_Ready_lt : std_logic := '0';
-- === Signals for mode "le" ===
signal I_Match_le : std_logic_vector(G_MaskWidth - 1 downto 0) := (others => '0');
signal I_Valid_le : std_logic := '0';
signal O_Ready_le : std_logic;
signal O_Default_Valid_le : std_logic;
signal I_Default_Ready_le : std_logic := '0';
signal O_Selected_Valid_le : std_logic;
signal I_Selected_Ready_le : std_logic := '0';
begin
-- === Instanz: "none" ===
UUT_none : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "none"
)
port map(
I_Match => I_Match_none,
I_Valid => I_Valid_none,
O_Ready => O_Ready_none,
O_Default_Valid => O_Default_Valid_none,
I_Default_Ready => I_Default_Ready_none,
O_Selected_Valid => O_Selected_Valid_none,
I_Selected_Ready => I_Selected_Ready_none
);
-- === Instanz: "or" ===
UUT_or : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "or"
)
port map(
I_Match => I_Match_or,
I_Valid => I_Valid_or,
O_Ready => O_Ready_or,
O_Default_Valid => O_Default_Valid_or,
I_Default_Ready => I_Default_Ready_or,
O_Selected_Valid => O_Selected_Valid_or,
I_Selected_Ready => I_Selected_Ready_or
);
-- === Instanz: "and" ===
UUT_and : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "and"
)
port map(
I_Match => I_Match_and,
I_Valid => I_Valid_and,
O_Ready => O_Ready_and,
O_Default_Valid => O_Default_Valid_and,
I_Default_Ready => I_Default_Ready_and,
O_Selected_Valid => O_Selected_Valid_and,
I_Selected_Ready => I_Selected_Ready_and
);
-- === Instanz: "xor" ===
UUT_xor : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "xor"
)
port map(
I_Match => I_Match_xor,
I_Valid => I_Valid_xor,
O_Ready => O_Ready_xor,
O_Default_Valid => O_Default_Valid_xor,
I_Default_Ready => I_Default_Ready_xor,
O_Selected_Valid => O_Selected_Valid_xor,
I_Selected_Ready => I_Selected_Ready_xor
);
-- === Instanz: "equal" ===
UUT_eq : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "equal"
)
port map(
I_Match => I_Match_eq,
I_Valid => I_Valid_eq,
O_Ready => O_Ready_eq,
O_Default_Valid => O_Default_Valid_eq,
I_Default_Ready => I_Default_Ready_eq,
O_Selected_Valid => O_Selected_Valid_eq,
I_Selected_Ready => I_Selected_Ready_eq
);
-- === Instanz: "not_eq" ===
UUT_neq : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "not_equal"
)
port map(
I_Match => I_Match_neq,
I_Valid => I_Valid_neq,
O_Ready => O_Ready_neq,
O_Default_Valid => O_Default_Valid_neq,
I_Default_Ready => I_Default_Ready_neq,
O_Selected_Valid => O_Selected_Valid_neq,
I_Selected_Ready => I_Selected_Ready_neq
);
-- === Instanz: "gt" ===
UUT_gt : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "gt"
)
port map(
I_Match => I_Match_gt,
I_Valid => I_Valid_gt,
O_Ready => O_Ready_gt,
O_Default_Valid => O_Default_Valid_gt,
I_Default_Ready => I_Default_Ready_gt,
O_Selected_Valid => O_Selected_Valid_gt,
I_Selected_Ready => I_Selected_Ready_gt
);
-- === Instanz: "ge" ===
UUT_ge : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "ge"
)
port map(
I_Match => I_Match_ge,
I_Valid => I_Valid_ge,
O_Ready => O_Ready_ge,
O_Default_Valid => O_Default_Valid_ge,
I_Default_Ready => I_Default_Ready_ge,
O_Selected_Valid => O_Selected_Valid_ge,
I_Selected_Ready => I_Selected_Ready_ge
);
-- === Instanz: "lt" ===
UUT_lt : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "lt"
)
port map(
I_Match => I_Match_lt,
I_Valid => I_Valid_lt,
O_Ready => O_Ready_lt,
O_Default_Valid => O_Default_Valid_lt,
I_Default_Ready => I_Default_Ready_lt,
O_Selected_Valid => O_Selected_Valid_lt,
I_Selected_Ready => I_Selected_Ready_lt
);
-- === Instanz: "le" ===
UUT_le : entity work.PipelineSwitch
generic map(
G_MaskWidth => G_MaskWidth,
G_Mask => G_Mask,
G_MaskMode => "le"
)
port map(
I_Match => I_Match_le,
I_Valid => I_Valid_le,
O_Ready => O_Ready_le,
O_Default_Valid => O_Default_Valid_le,
I_Default_Ready => I_Default_Ready_le,
O_Selected_Valid => O_Selected_Valid_le,
I_Selected_Ready => I_Selected_Ready_le
);
stimulus : process
begin
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "none"
----------------------------------------------------------------
report "Testmodus: none";
I_Default_Ready_none <= '1';
I_Match_none <= "0000";
I_Valid_none <= '1';
wait for 10 ns;
assert O_Default_Valid_none = '1' and O_Selected_Valid_none = '0'
report "Fehler im Modus 'none'" severity error;
I_Valid_none <= '0';
I_Default_Ready_none <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "or"
----------------------------------------------------------------
report "Testmodus: or";
I_Selected_Ready_or <= '1';
I_Match_or <= "0100"; -- bit 2 matches mask
I_Valid_or <= '1';
wait for 10 ns;
assert O_Selected_Valid_or = '1' and O_Default_Valid_or = '0'
report "Fehler im Modus 'or' (Match-Fall)" severity error;
I_Selected_Ready_or <= '0';
I_Valid_or <= '0';
wait for 10 ns;
I_Default_Ready_or <= '1';
I_Match_or <= "0010"; -- no bit matches mask
I_Valid_or <= '1';
wait for 10 ns;
assert O_Default_Valid_or = '1' and O_Selected_Valid_or = '0'
report "Fehler im Modus 'or' (No-Match-Fall)" severity error;
I_Default_Ready_or <= '0';
I_Valid_or <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "and"
----------------------------------------------------------------
report "Testmodus: and";
I_Selected_Ready_and <= '1';
I_Match_and <= "1101";
I_Valid_and <= '1';
wait for 10 ns;
assert O_Selected_Valid_and = '1' and O_Default_Valid_and = '0'
report "Fehler im Modus 'and' (Match-Fall)" severity error;
I_Selected_Ready_and <= '0';
I_Valid_and <= '0';
wait for 10 ns;
I_Default_Ready_and <= '1';
I_Match_and <= "1001"; -- bit 2 missing
I_Valid_and <= '1';
wait for 10 ns;
assert O_Default_Valid_and = '1' and O_Selected_Valid_and = '0'
report "Fehler im Modus 'and' (No-Match-Fall)" severity error;
I_Default_Ready_and <= '0';
I_Valid_and <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "xor"
----------------------------------------------------------------
report "Testmodus: xor";
I_Selected_Ready_xor <= '1';
I_Match_xor <= "1001"; -- differs at bit 2
I_Valid_xor <= '1';
wait for 10 ns;
assert O_Selected_Valid_xor = '1' and O_Default_Valid_xor = '0'
report "Fehler im Modus 'xor' (Match-Fall)" severity error;
I_Selected_Ready_xor <= '0';
I_Valid_xor <= '0';
wait for 10 ns;
I_Default_Ready_xor <= '1';
I_Match_xor <= "1101";
I_Valid_xor <= '1';
wait for 10 ns;
assert O_Default_Valid_xor = '1' and O_Selected_Valid_xor = '0'
report "Fehler im Modus 'xor' (No-Match-Fall)" severity error;
I_Default_Ready_xor <= '0';
I_Valid_xor <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "equal"
----------------------------------------------------------------
report "Testmodus: equal";
I_Selected_Ready_eq <= '1';
I_Match_eq <= "1101";
I_Valid_eq <= '1';
wait for 10 ns;
assert O_Selected_Valid_eq = '1' and O_Default_Valid_eq = '0'
report "Fehler im Modus 'equal' (Match-Fall)" severity error;
I_Selected_Ready_eq <= '0';
I_Valid_eq <= '0';
wait for 10 ns;
I_Default_Ready_eq <= '1';
I_Match_eq <= "1111";
I_Valid_eq <= '1';
wait for 10 ns;
assert O_Default_Valid_eq = '1' and O_Selected_Valid_eq = '0'
report "Fehler im Modus 'equal' (No-Match-Fall)" severity error;
I_Default_Ready_eq <= '0';
I_Valid_eq <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "not_equal"
----------------------------------------------------------------
report "Testmodus: not_equal";
I_Selected_Ready_neq <= '1';
I_Match_neq <= "1111"; -- not equal
I_Valid_neq <= '1';
wait for 10 ns;
assert O_Selected_Valid_neq = '1' and O_Default_Valid_neq = '0'
report "Fehler im Modus 'not_equal' (Match-Fall)" severity error;
I_Selected_Ready_neq <= '0';
I_Valid_neq <= '0';
wait for 10 ns;
I_Default_Ready_neq <= '1';
I_Match_neq <= "1101";
I_Valid_neq <= '1';
wait for 10 ns;
assert O_Default_Valid_neq = '1' and O_Selected_Valid_neq = '0'
report "Fehler im Modus 'not_equal' (No-Match-Fall)" severity error;
I_Default_Ready_neq <= '0';
I_Valid_neq <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "gt"
----------------------------------------------------------------
report "Testmodus: gt";
I_Selected_Ready_gt <= '1';
I_Match_gt <= "1110"; -- > 1101
I_Valid_gt <= '1';
wait for 10 ns;
assert O_Selected_Valid_gt = '1' and O_Default_Valid_gt = '0'
report "Fehler im Modus 'gt' (Match-Fall)" severity error;
I_Selected_Ready_gt <= '0';
I_Valid_gt <= '0';
wait for 10 ns;
I_Default_Ready_gt <= '1';
I_Match_gt <= "1010"; -- < 1101
I_Valid_gt <= '1';
wait for 10 ns;
assert O_Default_Valid_gt = '1' and O_Selected_Valid_gt = '0'
report "Fehler im Modus 'gt' (No-Match-Fall)" severity error;
I_Default_Ready_gt <= '0';
I_Valid_gt <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "ge"
----------------------------------------------------------------
report "Testmodus: ge";
I_Selected_Ready_ge <= '1';
I_Match_ge <= "1101"; -- == 1101
I_Valid_ge <= '1';
wait for 10 ns;
assert O_Selected_Valid_ge = '1' and O_Default_Valid_ge = '0'
report "Fehler im Modus 'ge' (Match-Fall ==)" severity error;
I_Selected_Ready_ge <= '0';
I_Valid_ge <= '0';
wait for 10 ns;
I_Default_Ready_ge <= '1';
I_Match_ge <= "0101"; -- < 1101
I_Valid_ge <= '1';
wait for 10 ns;
assert O_Default_Valid_ge = '1' and O_Selected_Valid_ge = '0'
report "Fehler im Modus 'ge' (No-Match-Fall)" severity error;
I_Default_Ready_ge <= '0';
I_Valid_ge <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "lt"
----------------------------------------------------------------
report "Testmodus: lt";
I_Selected_Ready_lt <= '1';
I_Match_lt <= "0101"; -- < 1101
I_Valid_lt <= '1';
wait for 10 ns;
assert O_Selected_Valid_lt = '1' and O_Default_Valid_lt = '0'
report "Fehler im Modus 'lt' (Match-Fall)" severity error;
I_Selected_Ready_lt <= '0';
I_Valid_lt <= '0';
wait for 10 ns;
I_Default_Ready_lt <= '1';
I_Match_lt <= "1111"; -- > 1101
I_Valid_lt <= '1';
wait for 10 ns;
assert O_Default_Valid_lt = '1' and O_Selected_Valid_lt = '0'
report "Fehler im Modus 'lt' (No-Match-Fall)" severity error;
I_Default_Ready_lt <= '0';
I_Valid_lt <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Mode: "le"
----------------------------------------------------------------
report "Testmodus: le";
I_Selected_Ready_le <= '1';
I_Match_le <= "1101"; -- == 1101
I_Valid_le <= '1';
wait for 10 ns;
assert O_Selected_Valid_le = '1' and O_Default_Valid_le = '0'
report "Fehler im Modus 'le' (Match-Fall ==)" severity error;
I_Selected_Ready_le <= '0';
I_Valid_le <= '0';
wait for 10 ns;
I_Default_Ready_le <= '1';
I_Match_le <= "1111"; -- > 1101
I_Valid_le <= '1';
wait for 10 ns;
assert O_Default_Valid_le = '1' and O_Selected_Valid_le = '0'
report "Fehler im Modus 'le' (No-Match-Fall)" severity error;
I_Default_Ready_le <= '0';
I_Valid_le <= '0';
wait for 10 ns;
----------------------------------------------------------------
-- Done!
----------------------------------------------------------------
report "Alle Tests abgeschlossen!" severity note;
wait;
end process;
end architecture RTL;