diff --git a/firebee_utils_pkg.vhd b/firebee_utils_pkg.vhd new file mode 100644 index 0000000..4283606 --- /dev/null +++ b/firebee_utils_pkg.vhd @@ -0,0 +1,170 @@ +---------------------------------------------------------------------- +---- ---- +---- This file is part of the 'Firebee' project. ---- +---- http://acp.atari.org ---- +---- ---- +---- Description: ---- +---- This package contains utility functions, procedures and constants +---- for the Firebee project. +---- +---- Author(s): ---- +---- - Markus Froeschle, mfro@mubf.de +---- ---- +---------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2015 Markus Froeschle +---- ---- +---- This source file is free software; you can redistribute it ---- +---- and/or modify it under the terms of the GNU General Public ---- +---- License as published by the Free Software Foundation; either ---- +---- version 2 of the License, or (at your option) any later ---- +---- version. ---- +---- ---- +---- This program is distributed in the hope that it will be ---- +---- useful, but WITHOUT ANY WARRANTY; without even the implied ---- +---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ---- +---- PURPOSE. See the GNU General Public License for more ---- +---- details. ---- +---- ---- +---- You should have received a copy of the GNU General Public ---- +---- License along with this program; if not, write to the Free ---- +---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ---- +---- Boston, MA 02110-1301, USA. ---- +---- ---- +---------------------------------------------------------------------- +-- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package firebee_utils_pkg is + function f_addr_cmp_l(signal addr : std_logic_vector; constant addr_const : std_logic_vector) return std_logic; + function f_addr_cmp_w(signal addr : std_logic_vector; constant addr_const : std_logic_vector) return std_logic; + function f_addr_cmp_b(signal addr : std_logic_vector; constant addr_const : std_logic_vector) return std_logic; + function f_addr_cmp_mask(signal addr : std_logic_vector; constant addr_const : std_logic_vector; constant num_ignore : integer) return std_logic; + + function max(left : integer; right : integer) return integer; + function min(left : integer; right : integer) return integer; + + component synchronizer IS + PORT + ( + -- Input ports + source_signal : in std_logic; + + target_clock : in std_logic; + target_signal : out std_logic + ); + end component synchronizer; + + -- size constants for the TSIZE vector + type tsize_t is (SIZE_LONG, SIZE_WORD, SIZE_BYTE, SIZE_LINE, SIZE_TRISTATE); + attribute enum_encoding : string; + attribute enum_encoding of tsize_t: type is "00 10 01 11 ZZ"; +-- constant SIZE_LONG : std_logic_vector(1 downto 0) := "00"; +-- constant SIZE_WORD : std_logic_vector(1 downto 0) := "10"; +-- constant SIZE_BYTE : std_logic_vector(1 downto 0) := "01"; +-- constant SIZE_LINE : std_logic_vector(1 downto 0) := "11"; +end firebee_utils_pkg; + +package body firebee_utils_pkg is + -- returns the smaller of two integers + function min(left : integer; right : integer) return integer is + begin + if left < right then + return left; + else + return right; + end if; + end function min; + + -- returns the larger of two integers + function max(left : integer; right : integer) return integer is + begin + if left > right then + return left; + else + return right; + end if; + end function max; + + -- returns the number of bits needed to represent n + function log2ceil(n : natural) return natural is + variable n_bit : unsigned(31 downto 0); + begin -- log2ceil + if n = 0 then + return 0; + end if; + n_bit := to_unsigned(n-1,32); + for i in 31 downto 0 loop + if n_bit(i) = '1' then + return i + 1; + end if; + end loop; -- i + return 1; + end log2ceil; + + -- this is for arbitrary sized address compares. It compares from the highest bit of addr_const to the lowest - num_ignore + -- bit, thus allowing any size of comparision. + function f_addr_cmp_mask(signal addr : std_logic_vector; + constant addr_const : std_logic_vector; + constant num_ignore : integer + ) return std_logic is + variable ret : std_logic := '1'; + variable hi : integer; + variable lo : integer; + begin + hi := min(addr_const'high, addr'high); + lo := max(addr_const'low, addr'low); + + -- report("faddr_cmp_mask(): hi = " & to_string(hi) & " lo = " & to_string(lo) & " log2ceil(num_ignore) = " & to_string(log2ceil(num_ignore))); + l_loop: for i in hi downto lo + log2ceil(num_ignore) - 1 loop + if addr(i) /= addr_const(i) then + + -- synthesis translate_off + -- report("f_addr_cmp_mask(): addr = " & to_hstring(unsigned(addr)) & " differs from addr_const = " & to_hstring(unsigned(addr_const)) & + -- " at bit = " & integer'image(i)); + -- report("addr(" & integer'image(i) & ") (" & to_string(addr) & ") = " & to_string(addr(i)) & + -- " addr_const(" & integer'image(i) & ") ( " & to_string(addr_const) & ") = " & to_string(addr_const(i))); + -- synthesis translate_on + + ret := '0'; + exit l_loop; + else + -- pragma synthesis off + -- report("f_addr_cmp_mask(): addr = " & to_hstring(unsigned(addr)) & " equals to addr_const = " & to_hstring(unsigned(addr_const)) & + -- " at bit = " & integer'image(i)); + -- report("addr(" & integer'image(i) & ") (" & to_string(addr) & ") = " & to_string(addr(i)) & + -- " addr_const(" & integer'image(i) & ") ( " & to_string(addr_const) & ") = " & to_string(addr_const(i))); + -- pragma synthesis on + end if; + end loop; + -- pragma synthesis off + report("f_addr_cmp_mask(" & to_hstring(unsigned(addr)) & ", " & to_hstring(unsigned(addr_const)) & "): return " & to_string(ret)); + -- pragma synthesis on + return ret; + end function f_addr_cmp_mask; + + + function f_addr_cmp_l(signal addr : std_logic_vector; + constant addr_const : std_logic_vector + ) return std_logic is + begin + return f_addr_cmp_mask(addr, addr_const, 2); + end function f_addr_cmp_l; + + function f_addr_cmp_w(signal addr : std_logic_vector; + constant addr_const : std_logic_vector + ) return std_logic is + begin + return f_addr_cmp_mask(addr, addr_const, 1); + end function f_addr_cmp_w; + + function f_addr_cmp_b(signal addr : std_logic_vector; + constant addr_const : std_logic_vector + ) return std_logic is + begin + return f_addr_cmp_mask(addr, addr_const, 0); + end function f_addr_cmp_b; +end package body firebee_utils_pkg; \ No newline at end of file