diff --git a/hdl/ip_cores/genrams/generic_shiftreg_fifo.vhd b/hdl/ip_cores/genrams/generic_shiftreg_fifo.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8d1b7a41ea7e4dbf22720a7dcce6b0a2c4c47b64 --- /dev/null +++ b/hdl/ip_cores/genrams/generic_shiftreg_fifo.vhd @@ -0,0 +1,160 @@ +---------------------------------------------------------------------------- +---- ---- +---- ---- +---- This file is part of the srl_fifo project ---- +---- http://www.opencores.org/cores/srl_fifo ---- +---- ---- +---- Description ---- +---- Implementation of srl_fifo IP core according to ---- +---- srl_fifo IP core specification document. ---- +---- ---- +---- To Do: ---- +---- NA ---- +---- ---- +---- Author(s): ---- +---- Andrew Mulcock, amulcock@opencores.org ---- +---- ---- +---- Modified for WR Project by Tomasz Wlostowski ---- +---------------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2008 Authors and OPENCORES.ORG ---- +---- ---- +---- This source file may be used and distributed without ---- +---- restriction provided that this copyright statement is not ---- +---- removed from the file and that any derivative work contains ---- +---- the original copyright notice and the associated disclaimer. ---- +---- ---- +---- This source file is free software; you can redistribute it ---- +---- and/or modify it under the terms of the GNU Lesser General ---- +---- Public License as published by the Free Software Foundation; ---- +---- either version 2.1 of the License, or (at your option) any ---- +---- later version. ---- +---- ---- +---- This source 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 Lesser General Public License for more ---- +---- details. ---- +---- ---- +---- You should have received a copy of the GNU Lesser General ---- +---- Public License along with this source; if not, download it ---- +---- from http://www.opencores.org/lgpl.shtml ---- +---- ---- +---------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use ieee.NUMERIC_STD.all; + +use work.genram_pkg.all; + +entity generic_shiftreg_fifo is + generic ( + g_data_width : integer := 128; + g_size : integer := 32 + ); + port ( + rst_n_i : in std_logic := '1'; + clk_i : in std_logic; + + d_i : in std_logic_vector(g_data_width-1 downto 0); + we_i : in std_logic; + q_o : out std_logic_vector(g_data_width-1 downto 0); + rd_i : in std_logic; + + full_o : out std_logic; + almost_full_o : out std_logic; + q_valid_o : out std_logic + ); + +end generic_shiftreg_fifo; + +architecture rtl of generic_shiftreg_fifo is + + constant c_srl_length : integer := g_size; -- set to srl 'type' 16 or 32 bit length + + type t_srl_array is array (c_srl_length - 1 downto 0) of std_logic_vector (g_data_width - 1 downto 0); + + signal fifo_store : t_srl_array; + signal pointer : integer range 0 to c_srl_length - 1; + + signal pointer_zero : std_logic; + signal pointer_full : std_logic; + signal pointer_almost_full : std_logic; + signal empty : std_logic := '1'; + signal valid_count : std_logic; + signal do_write : std_logic; +begin + +-- Valid write, high when valid to write data to the store. + + do_write <= '1' when (rd_i = '1' and we_i = '1') + or (we_i = '1' and pointer_full = '0') else '0'; + +-- data store SRL's + p_data_srl : process(clk_i) + begin + if rising_edge(clk_i) then +-- if rst_n_i = '0'then +-- for i in 0 to c_srl_length-1 loop +-- fifo_store(i) <= (others => '0'); +-- end loop; -- i + if do_write = '1' then + fifo_store <= fifo_store(fifo_store'left - 1 downto 0) & d_i; + end if; + end if; + end process; + + q_o <= fifo_store(pointer); + + p_empty_logic : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + empty <= '1'; + elsif empty = '1' and we_i = '1' then + empty <= '0'; + elsif pointer_zero = '1' and rd_i = '1' and we_i = '0' then + empty <= '1'; + end if; + end if; + end process; + +-- W R Action +-- 0 0 pointer <= pointer +-- 0 1 pointer <= pointer - 1 Read, but no write, so less data in counter +-- 1 0 pointer <= pointer + 1 Write, but no read, so more data in fifo +-- 1 1 pointer <= pointer Read and write, so same number of words in fifo +-- + + valid_count <= '1' when ( + (we_i = '1' and rd_i = '0' and pointer_full = '0' and empty = '0') + or + (we_i = '0' and rd_i = '1' and pointer_zero = '0') + ) else '0'; + + p_gen_address : process(clk_i) + begin + if rising_edge(clk_i) then + if valid_count = '1' then + if we_i = '1' then + pointer <= pointer + 1; + else + pointer <= pointer - 1; + end if; + end if; + end if; + end process; + + -- Detect when pointer is zero and maximum + pointer_zero <= '1' when pointer = 0 else '0'; + pointer_full <= '1' when pointer = c_srl_length - 1 else '0'; + pointer_almost_full <= '1' when pointer_full = '1' or pointer = c_srl_length - 2 else '0'; + + + -- assign internal signals to outputs + full_o <= pointer_full; + almost_full_o <= pointer_almost_full; + q_valid_o <= not empty; +end rtl; diff --git a/hdl/ip_cores/genrams/genram_pkg.vhd b/hdl/ip_cores/genrams/genram_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..0c3654466d86ff4f2ccb74679c4e4515402903ff --- /dev/null +++ b/hdl/ip_cores/genrams/genram_pkg.vhd @@ -0,0 +1,201 @@ +------------------------------------------------------------------------------- +-- Title : Main package file +-- Project : Generics RAMs and FIFOs collection +------------------------------------------------------------------------------- +-- File : genram_pkg.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN BE-CO-HT +-- Created : 2011-01-25 +-- Last update: 2012-01-24 +-- Platform : +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2011 CERN +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source 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 Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-01-25 1.0 twlostow Created +------------------------------------------------------------------------------- + + +library ieee; +use ieee.std_logic_1164.all; + +package genram_pkg is + + function f_log2_size (A : natural) return natural; + function f_gen_dummy_vec (val : std_logic; size : natural) return std_logic_vector; + + type t_generic_ram_init is array (integer range <>, integer range <>) of std_logic; + + -- Generic RAM initialized with nothing. + constant c_generic_ram_nothing : t_generic_ram_init(-1 downto 0, -1 downto 0) := + (others => (others => '0')); + + -- Single-port synchronous RAM + component generic_spram + generic ( + g_data_width : natural; + g_size : natural; + g_with_byte_enable : boolean := false; + g_init_file : string := ""; + g_addr_conflict_resolution : string := "read_first") ; + port ( + rst_n_i : in std_logic; + clk_i : in std_logic; + bwe_i : in std_logic_vector((g_data_width+7)/8-1 downto 0):= f_gen_dummy_vec('1', (g_data_width+7)/8); + we_i : in std_logic; + a_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + d_i : in std_logic_vector(g_data_width-1 downto 0) := f_gen_dummy_vec('0', g_data_width); + q_o : out std_logic_vector(g_data_width-1 downto 0)); + end component; + + component generic_dpram + generic ( + g_data_width : natural; + g_size : natural; + g_with_byte_enable : boolean := false; + g_addr_conflict_resolution : string := "read_first"; + g_init_file : string := ""; + g_init_value : t_generic_ram_init := c_generic_ram_nothing; + g_dual_clock : boolean := true); + port ( + rst_n_i : in std_logic := '1'; + clka_i : in std_logic; + bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0) := f_gen_dummy_vec('1', (g_data_width+7)/8); + wea_i : in std_logic := '0'; + aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + da_i : in std_logic_vector(g_data_width-1 downto 0) := f_gen_dummy_vec('0', g_data_width); + qa_o : out std_logic_vector(g_data_width-1 downto 0); + clkb_i : in std_logic; + bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0) := f_gen_dummy_vec('1', (g_data_width+7)/8); + web_i : in std_logic := '0'; + ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + db_i : in std_logic_vector(g_data_width-1 downto 0) := f_gen_dummy_vec('0', g_data_width); + qb_o : out std_logic_vector(g_data_width-1 downto 0)); + end component; + + component generic_async_fifo + generic ( + g_data_width : natural; + g_size : natural; + g_show_ahead : boolean := false; + g_with_rd_empty : boolean := true; + g_with_rd_full : boolean := false; + g_with_rd_almost_empty : boolean := false; + g_with_rd_almost_full : boolean := false; + g_with_rd_count : boolean := false; + g_with_wr_empty : boolean := false; + g_with_wr_full : boolean := true; + g_with_wr_almost_empty : boolean := false; + g_with_wr_almost_full : boolean := false; + g_with_wr_count : boolean := false; + g_almost_empty_threshold : integer := 0; + g_almost_full_threshold : integer := 0); + port ( + rst_n_i : in std_logic := '1'; + clk_wr_i : in std_logic; + d_i : in std_logic_vector(g_data_width-1 downto 0); + we_i : in std_logic; + wr_empty_o : out std_logic; + wr_full_o : out std_logic; + wr_almost_empty_o : out std_logic; + wr_almost_full_o : out std_logic; + wr_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + clk_rd_i : in std_logic; + q_o : out std_logic_vector(g_data_width-1 downto 0); + rd_i : in std_logic; + rd_empty_o : out std_logic; + rd_full_o : out std_logic; + rd_almost_empty_o : out std_logic; + rd_almost_full_o : out std_logic; + rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)); + end component; + + + component generic_sync_fifo + generic ( + g_data_width : natural; + g_size : natural; + g_show_ahead : boolean := false; + g_with_empty : boolean := true; + g_with_full : boolean := true; + g_with_almost_empty : boolean := false; + g_with_almost_full : boolean := false; + g_with_count : boolean := false; + g_almost_empty_threshold : integer := 0; + g_almost_full_threshold : integer := 0); + port ( + rst_n_i : in std_logic := '1'; + clk_i : in std_logic; + d_i : in std_logic_vector(g_data_width-1 downto 0); + we_i : in std_logic; + q_o : out std_logic_vector(g_data_width-1 downto 0); + rd_i : in std_logic; + empty_o : out std_logic; + full_o : out std_logic; + almost_empty_o : out std_logic; + almost_full_o : out std_logic; + count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)); + end component; + + component generic_shiftreg_fifo + generic ( + g_data_width : integer; + g_size : integer); + port ( + rst_n_i : in std_logic := '1'; + clk_i : in std_logic; + d_i : in std_logic_vector(g_data_width-1 downto 0); + we_i : in std_logic; + q_o : out std_logic_vector(g_data_width-1 downto 0); + rd_i : in std_logic; + full_o : out std_logic; + almost_full_o : out std_logic; + q_valid_o : out std_logic + ); + end component; + +end genram_pkg; + +package body genram_pkg is + + function f_log2_size (A : natural) return natural is + begin + for I in 1 to 64 loop -- Works for up to 64 bits + if (2**I >= A) then + return(I); + end if; + end loop; + return(63); + end function f_log2_size; + + function f_gen_dummy_vec (val : std_logic; size : natural) return std_logic_vector is + variable tmp : std_logic_vector(size-1 downto 0); + begin + for i in 0 to size-1 loop + tmp(i) := val; + end loop; -- i + return tmp; + end f_gen_dummy_vec; + + +end genram_pkg; diff --git a/hdl/ip_cores/genrams/inferred_async_fifo.vhd b/hdl/ip_cores/genrams/inferred_async_fifo.vhd new file mode 100644 index 0000000000000000000000000000000000000000..0e4b551c5e706723c92f1f67785508331b350e24 --- /dev/null +++ b/hdl/ip_cores/genrams/inferred_async_fifo.vhd @@ -0,0 +1,276 @@ +------------------------------------------------------------------------------- +-- Title : Parametrizable asynchronous FIFO (Generic version) +-- Project : Generics RAMs and FIFOs collection +------------------------------------------------------------------------------- +-- File : generic_async_fifo.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN BE-CO-HT +-- Created : 2011-01-25 +-- Last update: 2012-07-13 +-- Platform : +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: Dual-clock asynchronous FIFO. +-- - configurable data width and size +-- - configurable full/empty/almost full/almost empty/word count signals +------------------------------------------------------------------------------- +-- Copyright (c) 2011 CERN +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-01-25 1.0 twlostow Created +------------------------------------------------------------------------------- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.genram_pkg.all; + +entity inferred_async_fifo is + + generic ( + g_data_width : natural; + g_size : natural; + g_show_ahead : boolean := false; + + -- Read-side flag selection + g_with_rd_empty : boolean := true; -- with empty flag + g_with_rd_full : boolean := false; -- with full flag + g_with_rd_almost_empty : boolean := false; + g_with_rd_almost_full : boolean := false; + g_with_rd_count : boolean := false; -- with words counter + + g_with_wr_empty : boolean := false; + g_with_wr_full : boolean := true; + g_with_wr_almost_empty : boolean := false; + g_with_wr_almost_full : boolean := false; + g_with_wr_count : boolean := false; + + g_almost_empty_threshold : integer; -- threshold for almost empty flag + g_almost_full_threshold : integer -- threshold for almost full flag + ); + + port ( + rst_n_i : in std_logic := '1'; + + + -- write port + clk_wr_i : in std_logic; + d_i : in std_logic_vector(g_data_width-1 downto 0); + we_i : in std_logic; + + wr_empty_o : out std_logic; + wr_full_o : out std_logic; + wr_almost_empty_o : out std_logic; + wr_almost_full_o : out std_logic; + wr_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + + -- read port + clk_rd_i : in std_logic; + q_o : out std_logic_vector(g_data_width-1 downto 0); + rd_i : in std_logic; + + rd_empty_o : out std_logic; + rd_full_o : out std_logic; + rd_almost_empty_o : out std_logic; + rd_almost_full_o : out std_logic; + rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0) + ); + +end inferred_async_fifo; + + +architecture syn of inferred_async_fifo is + + + + function f_bin2gray(bin : unsigned) return unsigned is + begin + return bin(bin'left) & (bin(bin'left-1 downto 0) xor bin(bin'left downto 1)); + end f_bin2gray; + + function f_gray2bin(gray : unsigned) return unsigned is + variable bin : unsigned(gray'left downto 0); + begin + -- gray to binary + for i in 0 to gray'left loop + bin(i) := '0'; + for j in i to gray'left loop + bin(i) := bin(i) xor gray(j); + end loop; -- j + end loop; -- i + return bin; + end f_gray2bin; + + subtype t_counter is unsigned(f_log2_size(g_size) downto 0); + + type t_counter_block is record + bin, bin_next, gray, gray_next : t_counter; + bin_x, gray_x, gray_xm : t_counter; + end record; + + type t_mem_type is array (0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0); + signal mem : t_mem_type; + + signal rcb, wcb : t_counter_block; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of wcb: signal is "TRUE"; + attribute ASYNC_REG of rcb: signal is "TRUE"; + + signal full_int, empty_int : std_logic; + signal almost_full_int, almost_empty_int : std_logic; + signal going_full : std_logic; + + signal wr_count, rd_count : t_counter; + signal we : std_logic; +begin -- syn + + we <= we_i and not full_int; + + p_mem_write : process(clk_wr_i) + begin + if rising_edge(clk_wr_i) then + if(we = '1') then + mem(to_integer(wcb.bin(wcb.bin'left-1 downto 0))) <= d_i; + end if; + end if; + end process; + + p_mem_read : process(clk_rd_i) + begin + if rising_edge(clk_rd_i) then + if(rd_i = '1' and empty_int = '0') then + q_o <= mem(to_integer(rcb.bin(rcb.bin'left-1 downto 0))); + end if; + end if; + end process; + + wcb.bin_next <= wcb.bin + 1; + wcb.gray_next <= f_bin2gray(wcb.bin_next); + + p_write_ptr : process(clk_wr_i, rst_n_i) + begin + if rst_n_i = '0' then + wcb.bin <= (others => '0'); + wcb.gray <= (others => '0'); + elsif rising_edge(clk_wr_i) then + if(we_i = '1' and full_int = '0') then + wcb.bin <= wcb.bin_next; + wcb.gray <= wcb.gray_next; + end if; + end if; + end process; + + rcb.bin_next <= rcb.bin + 1; + rcb.gray_next <= f_bin2gray(rcb.bin_next); + + p_read_ptr : process(clk_rd_i, rst_n_i) + begin + if rst_n_i = '0' then + rcb.bin <= (others => '0'); + rcb.gray <= (others => '0'); + elsif rising_edge(clk_rd_i) then + if(rd_i = '1' and empty_int = '0') then + rcb.bin <= rcb.bin_next; + rcb.gray <= rcb.gray_next; + end if; + end if; + end process; + + p_sync_read_ptr : process(clk_wr_i) + begin + if rising_edge(clk_wr_i) then + rcb.gray_xm <= rcb.gray; + rcb.gray_x <= rcb.gray_xm; + end if; + end process; + + + p_sync_write_ptr : process(clk_rd_i) + begin + if rising_edge(clk_rd_i) then + wcb.gray_xm <= wcb.gray; + wcb.gray_x <= wcb.gray_xm; + end if; + end process; + + wcb.bin_x <= f_gray2bin(wcb.gray_x); + rcb.bin_x <= f_gray2bin(rcb.gray_x); + + p_gen_empty : process(clk_rd_i, rst_n_i) + begin + if rst_n_i = '0' then + empty_int <= '1'; + elsif rising_edge (clk_rd_i) then + if(rcb.gray = wcb.gray_x or (rd_i = '1' and (wcb.gray_x = rcb.gray_next))) then + empty_int <= '1'; + else + empty_int <= '0'; + end if; + end if; + end process; + + p_gen_going_full : process(we_i, wcb, rcb) + begin + if ((wcb.bin (wcb.bin'left-1 downto 0) = rcb.bin_x(rcb.bin_x'left-1 downto 0)) + and (wcb.bin(wcb.bin'left) /= rcb.bin_x(wcb.bin_x'left))) then + going_full <= '1'; + elsif (we_i = '1' + and (wcb.bin_next(wcb.bin'left-1 downto 0) = rcb.bin_x(rcb.bin_x'left-1 downto 0)) + and (wcb.bin_next(wcb.bin'left) /= rcb.bin_x(rcb.bin_x'left))) then + going_full <= '1'; + else + going_full <= '0'; + end if; + end process; + + p_register_full : process(clk_wr_i, rst_n_i) + begin + if rst_n_i = '0' then + full_int <= '0'; + elsif rising_edge (clk_wr_i) then + full_int <= going_full; + end if; + end process; + + wr_full_o <= full_int; + rd_empty_o <= empty_int; + + p_reg_almost_full : process(clk_wr_i, rst_n_i) + begin + if rst_n_i = '0' then + almost_full_int <= '0'; + elsif rising_edge(clk_wr_i) then + wr_count <= wcb.bin - rcb.bin_x; + if (wr_count >= g_almost_full_threshold) then + almost_full_int <= '1'; + else + almost_full_int <= '0'; + end if; + end if; + end process; + + p_reg_almost_empty : process(clk_rd_i, rst_n_i) + begin + if rst_n_i = '0' then + almost_empty_int <= '1'; + elsif rising_edge(clk_rd_i) then + rd_count <= wcb.bin_x - rcb.bin; + if (rd_count <= g_almost_empty_threshold) then + almost_empty_int <= '1'; + else + almost_empty_int <= '0'; + end if; + end if; + end process; + + rd_almost_empty_o <= almost_empty_int; + wr_almost_full_o <= almost_full_int; + + wr_count_o <= std_logic_vector(wr_count(f_log2_size(g_size)-1 downto 0)); + rd_count_o <= std_logic_vector(rd_count(f_log2_size(g_size)-1 downto 0)); + +end syn; diff --git a/hdl/ip_cores/genrams/inferred_sync_fifo.vhd b/hdl/ip_cores/genrams/inferred_sync_fifo.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c5da4691de86e562dffc229ad29cadb8155c4b05 --- /dev/null +++ b/hdl/ip_cores/genrams/inferred_sync_fifo.vhd @@ -0,0 +1,272 @@ +------------------------------------------------------------------------------- +-- Title : Parametrizable synchronous FIFO (Generic version) +-- Project : Generics RAMs and FIFOs collection +------------------------------------------------------------------------------- +-- File : generic_sync_fifo_std.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN BE-CO-HT +-- Created : 2011-01-25 +-- Last update: 2012-09-18 +-- Platform : +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: Single-clock FIFO. +-- - configurable data width and size +-- - configurable full/empty/almost full/almost empty/word count signals +------------------------------------------------------------------------------- +-- Copyright (c) 2011 CERN +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-01-25 1.0 twlostow Created +------------------------------------------------------------------------------- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.genram_pkg.all; + +entity inferred_sync_fifo is + + generic ( + g_data_width : natural; + g_size : natural; + g_show_ahead : boolean := false; + + -- Read-side flag selection + g_with_empty : boolean := true; -- with empty flag + g_with_full : boolean := true; -- with full flag + g_with_almost_empty : boolean := false; + g_with_almost_full : boolean := false; + g_with_count : boolean := false; -- with words counter + + g_almost_empty_threshold : integer := 0; -- threshold for almost empty flag + g_almost_full_threshold : integer := 0; -- threshold for almost full flag + + g_register_flag_outputs : boolean := true + ); + + port ( + rst_n_i : in std_logic := '1'; + + clk_i : in std_logic; + d_i : in std_logic_vector(g_data_width-1 downto 0); + we_i : in std_logic; + + q_o : out std_logic_vector(g_data_width-1 downto 0); + rd_i : in std_logic; + + empty_o : out std_logic; + full_o : out std_logic; + almost_empty_o : out std_logic; + almost_full_o : out std_logic; + count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0) + ); + +end inferred_sync_fifo; + +architecture syn of inferred_sync_fifo is + + constant c_pointer_width : integer := f_log2_size(g_size); + signal rd_ptr, wr_ptr, wr_ptr_d0, rd_ptr_muxed : unsigned(c_pointer_width-1 downto 0); + signal usedw : unsigned(c_pointer_width downto 0); + signal full, empty : std_logic; + signal q_int : std_logic_vector(g_data_width-1 downto 0); + signal we : std_logic; + signal guard_bit : std_logic; + + signal q_reg, q_comb : std_logic_vector(g_data_width-1 downto 0); + +begin -- syn + + --assert g_show_ahead = false report "Show ahead mode not implemented (yet). Sorry" severity failure; + + we <= we_i and not full; + + U_FIFO_Ram : generic_dpram + generic map ( + g_data_width => g_data_width, + g_size => g_size, + g_with_byte_enable => false, + g_addr_conflict_resolution => "read_first", + g_dual_clock => false) + port map ( + rst_n_i => rst_n_i, + clka_i => clk_i, + wea_i => we, + aa_i => std_logic_vector(wr_ptr(c_pointer_width-1 downto 0)), + da_i => d_i, + clkb_i => '0', + ab_i => std_logic_vector(rd_ptr_muxed(c_pointer_width-1 downto 0)), + qb_o => q_comb); + + p_output_reg : process(clk_i) + begin + if rising_edge(clk_i) then + if rd_i = '1' then + q_reg <= q_comb; + end if; + end if; + end process; + + + process(rd_ptr, rd_i) + begin + if(rd_i = '1' and g_show_ahead) then + rd_ptr_muxed <= rd_ptr + 1; + elsif((rd_i = '1' and not g_show_ahead) or (g_show_ahead)) then + rd_ptr_muxed <= rd_ptr; + else + rd_ptr_muxed <= rd_ptr - 1; + end if; + end process; + +-- q_o <= q_comb when g_show_ahead = true else q_reg; + + q_o <= q_comb; + + p_pointers : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + wr_ptr <= (others => '0'); + rd_ptr <= (others => '0'); + else + if(we_i = '1' and full = '0') then + wr_ptr <= wr_ptr + 1; + end if; + + if(rd_i = '1' and empty = '0') then + rd_ptr <= rd_ptr + 1; + end if; + end if; + end if; + end process; + + gen_comb_flags_showahead : if(g_show_ahead = true) generate + + process(clk_i) + begin + if rising_edge(clk_i) then + if ((rd_ptr + 1 = wr_ptr and rd_i = '1') or (rd_ptr = wr_ptr)) then + empty <= '1'; + else + empty <= '0'; + end if; + end if; + end process; + full <= '1' when (wr_ptr + 1 = rd_ptr) else '0'; + + end generate gen_comb_flags_showahead; + + gen_comb_flags : if(g_register_flag_outputs = false and g_show_ahead = false) generate + empty <= '1' when (wr_ptr = rd_ptr and guard_bit = '0') else '0'; + full <= '1' when (wr_ptr = rd_ptr and guard_bit = '1') else '0'; + + p_guard_bit : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + guard_bit <= '0'; + elsif(wr_ptr + 1 = rd_ptr and we_i = '1') then + guard_bit <= '1'; + elsif(rd_i = '1') then + guard_bit <= '0'; + end if; + end if; + end process; + end generate gen_comb_flags; + + gen_registered_flags : if(g_register_flag_outputs = true and g_show_ahead = false) generate + p_reg_flags : process(clk_i) + begin + if rising_edge(clk_i) then + + if(rst_n_i = '0') then + full <= '0'; + empty <= '1'; + else + if(usedw = 1 and rd_i = '1' and we_i = '0') then + empty <= '1'; + elsif(we_i = '1' and rd_i = '0') then + empty <= '0'; + end if; + + if(usedw = g_size-2 and we_i = '1' and rd_i = '0') then + full <= '1'; + elsif(usedw = g_size-1 and rd_i = '1' and we_i = '0') then + full <= '0'; + end if; + end if; + + end if; + end process; + end generate gen_registered_flags; + + + gen_with_word_counter : if(g_with_count or g_with_almost_empty or g_with_almost_full or g_register_flag_outputs) generate + p_usedw_counter : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + usedw <= (others => '0'); + else + if(we_i = '1' and rd_i = '0' and full = '0') then + usedw <= usedw + 1; + elsif(we_i = '0' and rd_i = '1' and empty = '0') then + usedw <= usedw - 1; + end if; + end if; + end if; + end process; + + count_o <= std_logic_vector(usedw(c_pointer_width-1 downto 0)); + + end generate gen_with_word_counter; + + gen_with_almost_full : if(g_with_almost_full) generate + process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + almost_full_o <= '0'; + else + if(usedw = g_almost_full_threshold-1) then + if(we_i = '1' and rd_i = '0') then + almost_full_o <= '1'; + elsif(rd_i = '1' and we_i = '0') then + almost_full_o <= '0'; + end if; + + end if; + end if; + end if; + end process; + end generate gen_with_almost_full; + + gen_with_almost_empty : if(g_with_almost_empty) generate + process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + almost_empty_o <= '1'; + else + if(usedw = g_almost_empty_threshold+1) then + if(rd_i = '1' and we_i = '0') then + almost_empty_o <= '1'; + elsif(we_i = '1' and rd_i = '0') then + almost_empty_o <= '0'; + end if; + + end if; + end if; + end if; + end process; + end generate gen_with_almost_empty; + + full_o <= full; + empty_o <= empty; + +end syn; diff --git a/hdl/ip_cores/genrams/memory_loader_pkg.vhd b/hdl/ip_cores/genrams/memory_loader_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..36221c523a4978ff206a68acc2c6ad32abb43ad8 --- /dev/null +++ b/hdl/ip_cores/genrams/memory_loader_pkg.vhd @@ -0,0 +1,205 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library std; +use std.textio.all; + +library work; +use work.genram_pkg.all; + +package memory_loader_pkg is + + subtype t_meminit_array is t_generic_ram_init; + + function f_hexchar_to_slv (c : character) return std_logic_vector; + function f_hexstring_to_slv (s : string; n_digits : integer) return std_logic_vector; + function f_get_token(s : string; n : integer) return string; + + function f_load_mem_from_file + (file_name : string; + mem_size : integer; + mem_width : integer; + fail_if_notfound : boolean) + return t_meminit_array; + +end memory_loader_pkg; + +package body memory_loader_pkg is + + function f_hexchar_to_slv (c : character) return std_logic_vector is + variable t : std_logic_vector(3 downto 0); + begin + + case c is + when '0' => t := x"0"; + when '1' => t := x"1"; + when '2' => t := x"2"; + when '3' => t := x"3"; + when '4' => t := x"4"; + when '5' => t := x"5"; + when '6' => t := x"6"; + when '7' => t := x"7"; + when '8' => t := x"8"; + when '9' => t := x"9"; + when 'a' => t := x"a"; + when 'A' => t := x"a"; + when 'b' => t := x"b"; + when 'B' => t := x"b"; + when 'c' => t := x"c"; + when 'C' => t := x"c"; + when 'd' => t := x"d"; + when 'D' => t := x"d"; + when 'e' => t := x"e"; + when 'E' => t := x"e"; + when 'f' => t := x"f"; + when 'F' => t := x"f"; + when others => + report "f_hexchar_to_slv(): unrecognized character '" &c&" in hex text string" severity failure; + end case; + + return t; + end f_hexchar_to_slv; + + function f_hexstring_to_slv (s : string; n_digits : integer) return std_logic_vector is + variable tmp : std_logic_vector(255 downto 0) := (others => '0'); + begin + if s'length > tmp'length then + report "f_hexstring_to_slv(): string length exceeds the limit" severity failure; + end if; + + for i in 0 to s'length-1 loop + tmp(4 * (s'length - i) - 1 downto 4 * (s'length - 1 - i)) := f_hexchar_to_slv(s(i+1)); + end loop; -- i + + return tmp(n_digits * 4 - 1 downto 0); + end f_hexstring_to_slv; + + function f_get_token(s : string; n : integer) return string is + variable cur_pos : integer; + variable tmp : string (1 to 128); + variable cur_token : integer; + variable tmp_pos : integer; + begin + + cur_pos := 1; + cur_token := 1; + tmp_pos := 1; + + loop + + if(cur_pos >= s'length) then + return ""; + end if; + + while cur_pos <= s'length and (s(cur_pos) = ' ' or s(cur_pos) = character'val(9) or s(cur_pos) = character'val(0)) loop + cur_pos := cur_pos + 1; + end loop; + + if(cur_pos >= s'length) then + return ""; + end if; + + while(cur_pos <= s'length and s(cur_pos) /= ' ' and s(cur_pos) /= character'val(9) and s(cur_pos) /= character'val(0)) loop + if(cur_token = n) then + tmp(tmp_pos) := s(cur_pos); + tmp_pos := tmp_pos + 1; + end if; + + cur_pos := cur_pos + 1; + end loop; + + if(cur_token = n) then + return tmp(1 to tmp_pos-1); + end if; + + + cur_token := cur_token + 1; + + if(cur_pos >= s'length) then + return ""; + end if; + end loop; + + return ""; + end f_get_token; + + + + function f_load_mem_from_file + (file_name : string; + mem_size : integer; + mem_width : integer; + fail_if_notfound : boolean) + return t_meminit_array is + + file f_in : text; + variable l : line; + variable ls : string(1 to 128); + variable cmd : string(1 to 128); + variable line_len : integer; + variable status : file_open_status; + variable mem : t_meminit_array(0 to mem_size-1, mem_width-1 downto 0); + variable i : integer; + variable c : character; + variable good : boolean; + variable addr : integer; + variable data_tmp : unsigned(mem_width-1 downto 0); + variable data_int : integer; + begin + if(file_name = "") then + mem := (others => (others => '0')); + return mem; + end if; + + file_open(status, f_in, file_name, read_mode); + + if(status /= open_ok) then + if(fail_if_notfound) then + report "f_load_mem_from_file(): can't open file '"&file_name&"'" severity failure; + else + report "f_load_mem_from_file(): can't open file '"&file_name&"'" severity warning; + end if; + end if; + + while true loop + i := 0; + while (i < 4096) loop + -- stupid ISE restricts the loop length + readline(f_in, l); + line_len := 0; + loop + read(l, ls(line_len+1), good); + exit when good = false; + line_len := line_len + 1; + end loop; + + if(line_len /= 0 and f_get_token(ls, 1) = "write") then + addr := to_integer(unsigned(f_hexstring_to_slv(f_get_token(ls, 2), 8))); + data_tmp := resize(unsigned(f_hexstring_to_slv(f_get_token(ls, 3), 8)), mem_width); + data_int := to_integer(data_tmp); + +-- report "addr: " & integer'image(addr) & " data: " & integer'image(data_int); + + for i in 0 to mem_width-1 loop + mem(addr, i) := std_logic(data_tmp(i)); + end loop; -- i in 0 to mem_width-1 + + -- report "addr: " & integer'image(addr) & " data: " & integer'image(data_int); + end if; + + if endfile(f_in) then + file_close(f_in); + return mem; + end if; + i := i+1; + end loop; + end loop; + + + return mem; + end f_load_mem_from_file; + + + +end memory_loader_pkg;