From d8166ba1805cce50265e1654f7ed22a71b7cd09f Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Wed, 22 Nov 2017 10:13:00 +0100 Subject: [PATCH] circular memory buffer. --- mupix/Mupix8/sources/CircularMemory.vhd | 148 ++++++++++++++++++++++++ mupix/Mupix8/sources/StdTypes.vhd | 17 +++ mupix/Mupix8/tb/CircularMemoryTest.vhd | 86 ++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 mupix/Mupix8/sources/CircularMemory.vhd create mode 100644 mupix/Mupix8/sources/StdTypes.vhd create mode 100644 mupix/Mupix8/tb/CircularMemoryTest.vhd diff --git a/mupix/Mupix8/sources/CircularMemory.vhd b/mupix/Mupix8/sources/CircularMemory.vhd new file mode 100644 index 0000000..c7c3012 --- /dev/null +++ b/mupix/Mupix8/sources/CircularMemory.vhd @@ -0,0 +1,148 @@ +------------------------------------------------------------------------------- +--Circular Memory to save sensor data +-- Note that writing into a full buffer will overwrite parts of the old data +--T. Weber, University Mainz +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.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 + ); + 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 + ); +end entity CircularMemory; + +architecture RTL of CircularMemory is + + component BlockMemory + generic( + DataWidth : integer := 10; + AddressWidth : integer := 10 + ); + port( + clk : in std_logic; + WrEn : in std_logic; + WrAddr : in std_logic_vector(AddressWidth - 1 downto 0); + Din : in std_logic_vector(DataWidth - 1 downto 0); + ReAddr : in std_logic_vector(AddressWidth - 1 downto 0); + Dout : out std_logic_vector(DataWidth - 1 downto 0) + ); + end component BlockMemory; + + --read and write pointers + constant c_high_address : integer := 2**g_addresswidth; + signal readpointer : integer range 0 to c_high_address - 1 := 0; + signal writepointer : integer range 0 to c_high_address - 1 := 0; + signal words_in_buffer : integer range 0 to c_high_address := 0; + + --wires to block memory + signal WrEn_mem : std_logic; + signal WrAddr_mem : std_logic_vector(g_addresswidth - 1 downto 0); + signal Din_mem : std_logic_vector(g_datawidth - 1 downto 0); + signal ReAddr_mem : std_logic_vector(g_addresswidth - 1 downto 0); + signal Dout_mem : std_logic_vector(g_datawidth - 1 downto 0); + +begin + + memory : entity work.BlockMemory + generic map( + DataWidth => g_datawidth, + AddressWidth => g_addresswidth + ) + port map( + clk => clk, + WrEn => WrEn_mem, + WrAddr => WrAddr_mem, + Din => Din_mem, + ReAddr => ReAddr_mem, + Dout => Dout_mem + ); + + write_proc : process(clk) is + begin + if rising_edge(clk) then + if rst = '1' then + writepointer <= 0; + else + if wr_en = '1' then + WrAddr_mem <= std_logic_vector(to_unsigned(writepointer, g_addresswidth)); + Din_mem <= data_in; + WrEn_mem <= '1'; + if writepointer = c_high_address - 1 then + writepointer <= 0; + else + writepointer <= writepointer + 1; + end if; + else + writepointer <= writepointer; + WrAddr_mem <= (others => '0'); + Din_mem <= (others => '0'); + WrEn_mem <= '0'; + end if; + end if; + end if; + end process write_proc; + + read_proc : process (clk) is + begin + if rising_edge(clk) then + if rst = '1' then + readpointer <= 0; + else + if rd_en = '1' then + ReAddr_mem <= std_logic_vector(to_unsigned(readpointer, g_addresswidth)); + if readpointer = c_high_address - 1 then + readpointer <= 0; + else + readpointer <= readpointer + 1; + end if; + else + readpointer <= readpointer; + ReAddr_mem <= (others => '0'); + end if; + end if; + end if; + end process read_proc; + + word_counter_proc : process (clk) is + begin + if rising_edge(clk) then + if rst = '1' then + words_in_buffer <= 0; + else + words_in_buffer <= words_in_buffer; + if wr_en = '1' and rd_en = '0' then + if words_in_buffer < c_high_address then + words_in_buffer <= words_in_buffer + 1; + else + words_in_buffer <= words_in_buffer; + end if; + elsif wr_en = '0' and rd_en = '1' then + if words_in_buffer > 0 then + words_in_buffer <= words_in_buffer - 1; + else + words_in_buffer <= 0; + end if; + end if; + end if; + end if; + end process word_counter_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; + data_out <= Dout_mem; + +end architecture RTL; diff --git a/mupix/Mupix8/sources/StdTypes.vhd b/mupix/Mupix8/sources/StdTypes.vhd new file mode 100644 index 0000000..a0a891b --- /dev/null +++ b/mupix/Mupix8/sources/StdTypes.vhd @@ -0,0 +1,17 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package StdTypes is + + type MupixSlowControl is record + sin : std_logic; + clk1 : std_logic; + clk2 : std_logic; + load : std_logic; + end record MupixSlowControl; + + constant c_mupix_slctrl_init : MupixSlowControl := ('0', '0', '0', '0'); + +end package StdTypes; + diff --git a/mupix/Mupix8/tb/CircularMemoryTest.vhd b/mupix/Mupix8/tb/CircularMemoryTest.vhd new file mode 100644 index 0000000..a1552a9 --- /dev/null +++ b/mupix/Mupix8/tb/CircularMemoryTest.vhd @@ -0,0 +1,86 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity CircularMemoryTest is +end entity CircularMemoryTest; + +architecture sim of CircularMemoryTest is + + component CircularMemory + generic( + g_datawidth : integer := 32; + g_addresswidth : integer := 10 + ); + port( + clk : in std_logic; + rst : in std_logic; + wr_en : in std_logic; + data_in : in std_logic_vector(g_datawidth - 1 downto 0); + rd_en : in std_logic; + data_out : out std_logic_vector(g_datawidth - 1 downto 0); + empty : out std_logic; + full : out std_logic + ); + end component CircularMemory; + + constant c_data_width : integer := 32; + constant c_address_width : integer := 3; + constant c_clk_period : time := 10 ns; + + signal clk : std_logic; + signal rst : std_logic := '0'; + signal wr_en : std_logic := '0'; + signal data_in : std_logic_vector(c_data_width - 1 downto 0) := (others => '0'); + signal rd_en : std_logic := '0'; + signal data_out : std_logic_vector(c_data_width - 1 downto 0); + signal empty : std_logic; + signal full : std_logic; + +begin + + dut : entity work.CircularMemory + generic map( + g_datawidth => c_data_width, + g_addresswidth => c_address_width + ) + port map( + clk => clk, + rst => rst, + wr_en => wr_en, + data_in => data_in, + rd_en => rd_en, + data_out => data_out, + empty => empty, + full => full + ); + + clk_gen : process is + begin + clk <= '0'; + wait for c_clk_period/2; + clk <= '1'; + wait for c_clk_period/2; + end process clk_gen; + + stimulus : process is + begin + wait for 100 ns; + for i in 1 to 7 loop + wr_en <= '1'; + data_in <= std_logic_vector(to_unsigned(i, c_data_width)); + wait for c_clk_period; + end loop; + wr_en <= '0'; + wait for 50 ns; + for i in 1 to 7 loop + rd_en <= '1'; + wait for c_clk_period; + end loop; + rd_en <= '0'; + wait; + end process stimulus; + + +end architecture sim; + -- 2.43.0