Adds configurable PipelineFilter with AXI-like handshake

Implements a generic VHDL entity for data filtering based on a bitmask and comparison modes.
Supports configurable filtering modes such as 'none', 'or', 'and', 'xor', 'equal', and 'not_equal'.
Integrates AXI-like valid/ready handshake for synchronous data transfer.

Ensures proper handling of unrecognized modes and validates mask size at runtime.
This commit is contained in:
2025-04-16 17:25:35 +00:00
parent 87b9bf20bf
commit 9a7bffadec

140
src/PipelineFilter.vhd Normal file
View File

@@ -0,0 +1,140 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity PipelineFilter is
generic (
--@ Width of the comparison input and mask.
G_MaskWidth : integer := 4;
--@ Bit mask to be compared against `I_Match` input.
G_Mask : std_logic_vector := "1010";
--@ Comparison mode that defines the filter behavior.
--@ Available modes:
--@ - `"none"`: Disables filtering; always passes data.
--@ - `"or"`: Filters if **any** bit in `I_Match` matches a bit set in `G_Mask`.
--@ - `"and"`: Filters if **all** bits set in `G_Mask` are also set in `I_Match`.
--@ - `"xor"`: Filters if **any** bit differs between `I_Match` and `G_Mask`.
--@ - `"equal"`: Filters if `I_Match` is **bitwise equal** to `G_Mask`.
--@ - `"not_equal"`: Filters if `I_Match` is **not equal** to `G_Mask`.
G_MaskMode : string := "equal"
);
port (
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 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 PipelineFilter;
architecture RTL of PipelineFilter 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";
signal C_ShouldFiltered : 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 filtering: Always pass the data through.
C_ShouldFiltered <= '0';
elsif strings_equal(G_MaskMode, K_Mode_OR) then
--@ Filter if **any** bit in I_Match matches a bit set in G_Mask.
--@ Equivalent to: (I_Match AND G_Mask) /= 0
if (I_Match and G_Mask) /= (G_MaskWidth - 1 downto 0 => '0') then
C_ShouldFiltered <= '1';
else
C_ShouldFiltered <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_XOR) then
--@ Filter if **any** bit differs between I_Match and G_Mask.
--@ This checks if the vectors are **not bitwise equal**.
if (I_Match xor G_Mask) /= (G_MaskWidth - 1 downto 0 => '0') then
C_ShouldFiltered <= '1';
else
C_ShouldFiltered <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_AND) then
--@ Filter if **all bits** set in G_Mask are also set in I_Match.
--@ In other words, I_Match must contain the full mask.
if (I_Match and G_Mask) = G_Mask then
C_ShouldFiltered <= '1';
else
C_ShouldFiltered <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_Equal) then
--@ Filter if I_Match is **exactly equal** to G_Mask.
if I_Match = G_Mask then
C_ShouldFiltered <= '1';
else
C_ShouldFiltered <= '0';
end if;
elsif strings_equal(G_MaskMode, K_Mode_NotEqual) then
--@ Filter if I_Match is **not equal** to G_Mask.
if I_Match /= G_Mask then
C_ShouldFiltered <= '1';
else
C_ShouldFiltered <= '0';
end if;
else
--@ Unknown mode: fallback to no filtering.
C_ShouldFiltered <= '0';
end if;
end process;
process (I_Valid, I_Ready, C_ShouldFiltered)
begin
if C_ShouldFiltered = '1' then
--@ Data is filtered: do not pass it through.
O_Valid <= '0';
--@ Assert O_Ready to indicate that the input is ready to accept data.
O_Ready <= '1';
else
--@ Data is not filtered: pass it through.
O_Valid <= I_Valid;
O_Ready <= I_Ready;
end if;
end process;
end architecture;