use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
+use work.StdTypes.all;
+
entity CircularMemory is
generic(
g_datawidth : integer := 32; -- width of data words
- g_addresswidth : integer := 10 -- width of address pointers, number of words is 2**g_addresswidth
+ g_addresswidth : integer := 10; -- width of address pointers, number of words is 2**g_addresswidth
+ g_clockspeed : integer := 1e8 -- FPGA clock speed in Hz
);
port(
- clk : in std_logic; -- clock input
- rst : in std_logic; -- reset
- wr_en : in std_logic; -- write enable
- data_in : in std_logic_vector(g_datawidth - 1 downto 0); -- input word
- rd_en : in std_logic; --read enable
- data_out : out std_logic_vector(g_datawidth - 1 downto 0); -- output word
- empty : out std_logic; --empty flag
- full : out std_logic --full flag
+ clk : in std_logic; -- clock input
+ rst : in std_logic; -- reset
+ wr_en : in std_logic; -- write enable
+ data_in : in std_logic_vector(g_datawidth - 1 downto 0); -- input word
+ rd_en : in std_logic; --read enable
+ data_out : out std_logic_vector(g_datawidth - 1 downto 0); -- output word
+ empty : out std_logic; --empty flag
+ full : out std_logic; --full flag
+ fillcnt : out std_logic_vector(g_addresswidth - 1 downto 0); -- number of words in circullar buffer
+ inword_freq : out std_logic_vector(31 downto 0); -- number of input words per second
+ outword_freq : out std_logic_vector(31 downto 0) -- number of output words per second
);
end entity CircularMemory;
);
end component BlockMemory;
+ --counters for write/read frequency
+ signal ticks_counter : unsigned(f_log2(g_clockspeed) - 1 downto 0) := (others => '0');
+ signal inword_counter, outword_counter : unsigned(31 downto 0) := (others => '0');
+
--read and write pointers
constant c_high_address : integer := 2**g_addresswidth;
signal readpointer : integer range 0 to c_high_address - 1 := 0;
end if;
end process word_counter_proc;
+ throughput_proc : process (clk) is
+ begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ ticks_counter <= (others => '0');
+ inword_counter <= (others => '0');
+ outword_counter <= (others => '0');
+ else
+ if wr_en = '1' then
+ inword_counter <= inword_counter + 1;
+ end if;
+ if rd_en = '1' then
+ outword_counter <= outword_counter + 1;
+ end if;
+ if ticks_counter = g_clockspeed - 1 then
+ ticks_counter <= (others => '0');
+ inword_freq <= std_logic_vector(inword_counter);
+ outword_freq <= std_logic_vector(outword_counter);
+ inword_counter <= (others => '0');
+ outword_counter <= (others => '0');
+ else
+ ticks_counter <= ticks_counter + 1;
+ end if;
+ end if;
+ end if;
+ end process throughput_proc;
+
+
empty <= '1' after 1 ns when words_in_buffer = 0 else '0' after 1 ns;
full <= '1' after 1 ns when words_in_buffer = c_high_address else '0' after 1 ns;
+ fillcnt <= std_logic_vector(to_unsigned(words_in_buffer, g_addresswidth));
data_out <= Dout_mem;
end architecture RTL;
end record MupixSlowControl;
constant c_mupix_slctrl_init : MupixSlowControl := ('0', '0', '0', '0');
-
+
+ type t_counter_array is array(integer range <>) of unsigned(31 downto 0);
+
+ function f_log2(x : positive) return natural;
+ function counter_array_to_stdvec(x : t_counter_array) return std_logic_vector;
+
end package StdTypes;
+package body StdTypes is
+
+function f_log2(x : positive) return natural is
+ variable i : natural;
+ begin
+ i := 0;
+ while (2**i < x) loop
+ i := i + 1;
+ end loop;
+ return i;
+ end function;
+
+
+function counter_array_to_stdvec(x : t_counter_array) return std_logic_vector is
+ variable tmp : std_logic_vector(32*x'length - 1 downto 0);
+begin
+ tmp := (others => '0');
+ for i in 0 to x'length - 1 loop
+ tmp(32*(i + 1) - 1 downto 32*i) := std_logic_vector(x(i));
+ end loop;
+ return tmp;
+end function;
+
+end package body StdTypes;
rd_en : in std_logic;
data_out : out std_logic_vector(g_datawidth - 1 downto 0);
empty : out std_logic;
- full : out std_logic
+ full : out std_logic;
+ fillcnt : out std_logic_vector(g_addresswidth - 1 downto 0);
+ inword_freq : out std_logic_vector(31 downto 0);
+ outword_freq : out std_logic_vector(31 downto 0)
);
end component CircularMemory;
signal data_out : std_logic_vector(c_data_width - 1 downto 0);
signal empty : std_logic;
signal full : std_logic;
+ signal fillcnt : std_logic_vector(c_address_width - 1 downto 0);
+ signal inword_freq : std_logic_vector(31 downto 0);
+ signal outword_freq : std_logic_vector(31 downto 0);
begin
dut : entity work.CircularMemory
generic map(
g_datawidth => c_data_width,
- g_addresswidth => c_address_width
+ g_addresswidth => c_address_width,
+ g_clockspeed => 1e3
)
port map(
clk => clk,
rd_en => rd_en,
data_out => data_out,
empty => empty,
- full => full
+ full => full,
+ fillcnt => fillcnt,
+ inword_freq => inword_freq,
+ outword_freq => outword_freq
);
clk_gen : process is