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:
140
src/PipelineFilter.vhd
Normal file
140
src/PipelineFilter.vhd
Normal 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;
|
Reference in New Issue
Block a user