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_clockspeed : integer := 1e8; -- FPGA clock speed in Hz
- g_boundedbuf : boolean := false -- stop writing when buffer is full (FIFO mode)
- );
- 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
- offset_en : in std_logic; -- set offset between write and read pointer
- offset : in std_logic_vector(g_addresswidth - 1 downto 0); -- read - write pointer offset
- 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
- almost_empty : out std_logic; --one more word remaining in buffer
- almost_full : out std_logic; --one more word to write before buffer overflow
- fillcnt : out std_logic_vector(g_addresswidth downto 0); -- number of words in circular 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
- );
+ 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_clockspeed : integer := 1e8; -- FPGA clock speed in Hz
+ g_boundedbuf : boolean := false -- stop writing when buffer is full (FIFO mode)
+ );
+ 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
+ offset_en : in std_logic; -- set offset between write and read pointer
+ offset : in std_logic_vector(g_addresswidth - 1 downto 0); -- read - write pointer offset
+ 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
+ almost_empty : out std_logic; --one more word remaining in buffer
+ almost_full : out std_logic; --one more word to write before buffer overflow
+ fillcnt : out std_logic_vector(g_addresswidth downto 0); -- number of words in circular 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;
architecture RTL of CircularMemory is
-
- component BlockMemory
- generic(
- DataWidth : integer := 10;
- AddressWidth : integer := 10
- );
- port(
- clk : in std_logic;
- reset : 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;
-
- --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;
- signal writepointer : integer range 0 to c_high_address - 1 := 0;
- signal words_in_buffer : integer range 0 to c_high_address := 0;
- signal read_write_pointer_offset : integer range -(c_high_address - 1) to c_high_address - 1 := 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);
-
- signal empty_i : std_logic;
- signal full_i : std_logic;
- signal rd_en_i : std_logic;
- signal wr_en_i : std_logic;
- signal increment_wd_cnt : std_logic := '0';
- signal decrement_wd_cnt : std_logic := '0';
-
+
+ component RAM_DP_4096_32 is
+ port (
+ WrAddress : in std_logic_vector(11 downto 0);
+ RdAddress : in std_logic_vector(11 downto 0);
+ Data : in std_logic_vector(31 downto 0);
+ WE : in std_logic;
+ RdClock : in std_logic;
+ RdClockEn : in std_logic;
+ Reset : in std_logic;
+ WrClock : in std_logic;
+ WrClockEn : in std_logic;
+ Q : out std_logic_vector(31 downto 0));
+ end component RAM_DP_4096_32;
+
+ --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;
+ signal writepointer : integer range 0 to c_high_address - 1 := 0;
+ signal words_in_buffer : integer range 0 to c_high_address := 0;
+ signal read_write_pointer_offset : integer range -(c_high_address - 1) to c_high_address - 1 := 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);
+
+ signal empty_i : std_logic;
+ signal full_i : std_logic;
+ signal rd_en_i : std_logic;
+ signal wr_en_i : std_logic;
+ signal increment_wd_cnt : std_logic := '0';
+ signal decrement_wd_cnt : std_logic := '0';
+
begin
-
- memory : entity work.BlockMemory
- generic map(
- DataWidth => g_datawidth,
- AddressWidth => g_addresswidth
- )
- port map(
- clk => clk,
- reset => rst,
- 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;
- increment_wd_cnt <= '0';
- else
- if wr_en_i = '1' then
- increment_wd_cnt <= '1';
- if writepointer = c_high_address - 1 then
- writepointer <= 0;
- else
- writepointer <= writepointer + 1;
- end if;
- else
- writepointer <= writepointer;
- increment_wd_cnt <= '0';
- end if;
- end if;
- end if;
- end process write_proc;
-
- WrAddr_mem <= std_logic_vector(to_unsigned(writepointer, g_addresswidth));
- Din_mem <= data_in;
- WrEn_mem <= wr_en_i;
-
- read_write_offset_proc : process(offset, writepointer) is
- begin
- read_write_pointer_offset <= writepointer - to_integer(unsigned(offset)) after 2 ns;
- end process read_write_offset_proc;
-
- read_proc : process(clk) is
- begin
- if rising_edge(clk) then
- if rst = '1' then
- readpointer <= 0;
- decrement_wd_cnt <= '0';
- else
- if offset_en = '1' then
- if read_write_pointer_offset >= 0 then
- readpointer <= read_write_pointer_offset;
- else
- readpointer <= c_high_address + read_write_pointer_offset;
- end if;
- elsif rd_en_i = '1' then
- decrement_wd_cnt <= '1';
- if readpointer = c_high_address - 1 then
- readpointer <= 0;
- else
- readpointer <= readpointer + 1;
- end if;
- else
- decrement_wd_cnt <= '0';
- readpointer <= readpointer;
- end if;
- end if;
- end if;
- end process read_proc;
-
- ReAddr_mem <= std_logic_vector(to_unsigned(readpointer, g_addresswidth));
-
- word_counter_proc : process(clk) is
- begin
- if rising_edge(clk) then
- if rst = '1' then
- words_in_buffer <= 0;
- elsif offset_en = '1' then
- words_in_buffer <= to_integer(unsigned(offset));
- else
- words_in_buffer <= words_in_buffer;
- if increment_wd_cnt = '1' and decrement_wd_cnt = '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 increment_wd_cnt = '0' and decrement_wd_cnt = '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;
-
- 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_counter <= (others => '0');
- outword_counter <= (others => '0');
- inword_freq <= std_logic_vector(inword_counter);
- outword_freq <= std_logic_vector(outword_counter);
- else
- ticks_counter <= ticks_counter + 1;
- end if;
- end if;
- end if;
- end process throughput_proc;
-
- empty_i <= '1' when words_in_buffer = 0 else '0';
- full_i <= '1' when words_in_buffer = c_high_address else '0';
- rd_en_i <= not empty_i and rd_en;
- wr_en_i <= (wr_en and not full_i) when g_boundedbuf = true else wr_en;
-
- empty <= empty_i;
- almost_empty <= '1' when (words_in_buffer < 3) else '0';
- full <= full_i;
- almost_full <= '1' when words_in_buffer >= c_high_address - 1 else '0';
- fillcnt <= std_logic_vector(to_unsigned(words_in_buffer, g_addresswidth + 1));
- data_out <= Dout_mem;
-
+
+ RAM_DP_4096_32_1: entity work.RAM_DP_4096_32
+ port map (
+ WrAddress => WrAddr_mem,
+ RdAddress => ReAddr_mem,
+ Data => Din_mem,
+ WE => WrEn_mem,
+ RdClock => clk,
+ RdClockEn => '1',
+ Reset => rst,
+ WrClock => clk,
+ WrClockEn => '1',
+ Q => Dout_mem);
+
+ write_proc : process(clk) is
+ begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ writepointer <= 0;
+ increment_wd_cnt <= '0';
+ else
+ if wr_en_i = '1' then
+ increment_wd_cnt <= '1';
+ if writepointer = c_high_address - 1 then
+ writepointer <= 0;
+ else
+ writepointer <= writepointer + 1;
+ end if;
+ else
+ writepointer <= writepointer;
+ increment_wd_cnt <= '0';
+ end if;
+ end if;
+ end if;
+ end process write_proc;
+
+ WrAddr_mem <= std_logic_vector(to_unsigned(writepointer, g_addresswidth));
+ Din_mem <= data_in;
+ WrEn_mem <= wr_en_i;
+
+ read_write_offset_proc : process(offset, writepointer) is
+ begin
+ read_write_pointer_offset <= writepointer - to_integer(unsigned(offset)) after 2 ns;
+ end process read_write_offset_proc;
+
+ read_proc : process(clk) is
+ begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ readpointer <= 0;
+ decrement_wd_cnt <= '0';
+ else
+ if offset_en = '1' then
+ if read_write_pointer_offset >= 0 then
+ readpointer <= read_write_pointer_offset;
+ else
+ readpointer <= c_high_address + read_write_pointer_offset;
+ end if;
+ elsif rd_en_i = '1' then
+ decrement_wd_cnt <= '1';
+ if readpointer = c_high_address - 1 then
+ readpointer <= 0;
+ else
+ readpointer <= readpointer + 1;
+ end if;
+ else
+ decrement_wd_cnt <= '0';
+ readpointer <= readpointer;
+ end if;
+ end if;
+ end if;
+ end process read_proc;
+
+ ReAddr_mem <= std_logic_vector(to_unsigned(readpointer, g_addresswidth));
+
+ word_counter_proc : process(clk) is
+ begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ words_in_buffer <= 0;
+ elsif offset_en = '1' then
+ words_in_buffer <= to_integer(unsigned(offset));
+ else
+ words_in_buffer <= words_in_buffer;
+ if increment_wd_cnt = '1' and decrement_wd_cnt = '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 increment_wd_cnt = '0' and decrement_wd_cnt = '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;
+
+ 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_counter <= (others => '0');
+ outword_counter <= (others => '0');
+ inword_freq <= std_logic_vector(inword_counter);
+ outword_freq <= std_logic_vector(outword_counter);
+ else
+ ticks_counter <= ticks_counter + 1;
+ end if;
+ end if;
+ end if;
+ end process throughput_proc;
+
+ empty_i <= '1' when words_in_buffer = 0 else '0';
+ full_i <= '1' when words_in_buffer = c_high_address else '0';
+ rd_en_i <= not empty_i and rd_en;
+ wr_en_i <= (wr_en and not full_i) when g_boundedbuf = true else wr_en;
+
+ empty <= empty_i;
+ almost_empty <= '1' when (words_in_buffer < 3) else '0';
+ full <= full_i;
+ almost_full <= '1' when words_in_buffer >= c_high_address - 1 else '0';
+ fillcnt <= std_logic_vector(to_unsigned(words_in_buffer, g_addresswidth + 1));
+ data_out <= Dout_mem;
+
end architecture RTL;