]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
circular memory buffer.
authorTobias Weber <toweber86@gmail.com>
Wed, 22 Nov 2017 09:13:00 +0000 (10:13 +0100)
committerTobias Weber <toweber86@gmail.com>
Wed, 22 Nov 2017 09:13:00 +0000 (10:13 +0100)
mupix/Mupix8/sources/CircularMemory.vhd [new file with mode: 0644]
mupix/Mupix8/sources/StdTypes.vhd [new file with mode: 0644]
mupix/Mupix8/tb/CircularMemoryTest.vhd [new file with mode: 0644]

diff --git a/mupix/Mupix8/sources/CircularMemory.vhd b/mupix/Mupix8/sources/CircularMemory.vhd
new file mode 100644 (file)
index 0000000..c7c3012
--- /dev/null
@@ -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 (file)
index 0000000..a0a891b
--- /dev/null
@@ -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 (file)
index 0000000..a1552a9
--- /dev/null
@@ -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;
+