# Using VHDL integer_vector for a block ram type, how to restrict the integer range?

Trying to simply infer block rams in a design with varying depths and widths. I'd like to have one ram definition since it is going to use a vendor specific attribute and it seems like a good idea to keep it confined to one module.

Using integer_vector for the array type it is simple enough to set the range of the array index. Setting the range of the integers in the array is not so clear. Is it possible to set the integer range in the signal declaration rather than a type declaration?

I need both the depth and width of the memory to be set by generics where it is instantiated. Will I need to use a vector type instead of the integer type to be able to do this?

• Looking at "standard.vhdl" (2008 version) I see type integer_vector is array (natural range <>) of integer;. So I would suggest declaring your own subtype of integer and declare my_int_vector along the same lines, and see how far you get. All uses of integer_vector I've seen so far have been in verification, not synthesis, so you may hit corner cases, but there's no fundamental reason AFAIK why it shouldn't work. Oct 25 '20 at 13:17
• Point is I don't want the integer range to be defined in the array type definition. Otherwise I will need a memory entity for every data width. If the output of the memory is assigned to a vector of fixed size, the unused RAM bits are optimized away, right? just realized that's what the code does! Simulation runs correctly although the values of the memory array are expressed as full 32 bit values, the module synthesizes to one BRAM as it should. LOL I had declared the memory type in the entity. Looking at moving it to a common file I didn't realize it was already being truncated. Oct 25 '20 at 22:32
• Got a bit ahead of myself. I had it working well when using the local type definition. type BRAM_t is array (integer range <>) of natural range 0 to 2**DataWidth-1; Using integer_vector makes the initial value neg-max and the to_unsigned barfs. Then more issues with Active-HDL and simple aggregates. lather, rinse, repeat. Anyway, it works with integer_vector and no type definition at all (big plus... I think). The Gowin synthesis tool is giving me a single block RAM as hoped. Schematic tool shows all 2048 internal FF 32 wide banks, so won't be much use on real designs. Oct 25 '20 at 23:26

Here is the final code, well final as of this moment.

-- VHDL created by Arius, Inc  copyright 2020
--------------------------------------------------------------------------------
-- Company: Arius, Inc
-- Engineer: Rick Collins
--
-- Create Date:   2020/10/25 03:23z
-- Design Name:   Alarm
-- Module Name:   Blk_mem
-- Project Name:  OVB_Alarm
--
-- Revision:
-- Revision 0.01 - File Created
--
--
-- Notes:  -  SYNTHESIZABLE CODE ONLY
-- Blk_mem - Memory block, variable data width and depth
--
-- Notes:  -  NOT ASSURED TO BE SYNTHESIZABLE CODE
-- VHDL_test_mem - Write and read memory to verify functionality
--
--------------------------------------------------------------------------------
-- Test synthesis of memory, semi-dual port
library ieee;
use ieee.NUMERIC_STD.all;
use ieee.std_logic_1164.all;
-- use work.Common.all;
use work.all;

entity Blk_mem is
generic(
DataWidth : positive := 9
);
port(
Clk     : in    std_logic := '1';
Wr_Data : in    unsigned(DataWidth-1 downto 0);
Wr_CE   : in    std_logic;
Rd_Data : out   unsigned(DataWidth-1 downto 0);
Rd_CE   : in    std_logic
);
end Blk_mem;

architecture behav of Blk_mem is
-- type BRAM_t is array (integer range <>) of
--                                    natural range 0 to 2**DataWidth-1;
signal BRAM_mem : integer_vector (0 to 2**AddrWidth-1);
-- attribute syn_ramstyle:string;
-- attribute syn_ramstyle of BRAM_mem : signal is "block_ram";
begin

BRAM_proc: process (Clk) is
variable Rd_Mem : natural range 0 to 2**DataWidth-1;
begin
if (rising_edge(Clk)) then
if (Wr_CE) then
end if;
if (Rd_CE) then
Rd_Data <= to_unsigned(Rd_Mem, Rd_Data'length);
end if;
end if;
end process BRAM_proc;

END behav;  -- Blk_mem

-- synthesis translate_off
library ieee;
use ieee.NUMERIC_STD.all;
use ieee.std_logic_1164.all;
--use work.Common.all;
use work.all;

entity VHDL_test_mem is
generic(
CLK_HZ : REAL := 33.554432E6;
DataWidth : positive := 9
);
--   port(
--   );
end VHDL_test_mem;

architecture TB_ARCH of VHDL_test_mem is
constant Clock_Half_Period : time := 500 ms / CLK_HZ;  -- 14901 ps; --
signal Clk        : std_logic := '1';
signal Wr_Data    : unsigned(DataWidth-1 downto 0) := (others => '1');
signal Wr_CE      : std_logic := '1';
signal Rd_Data    : unsigned(DataWidth-1 downto 0) := (others => '0');
signal Rd_CE      : std_logic := '1';
signal Wr_Data_d  : unsigned(DataWidth-1 downto 0) := (others => '1');
signal Wr_Data_dd : unsigned(DataWidth-1 downto 0);
begin
Clk_gen: Clk <= not Clk after Clock_Half_Period;

stimulus: process (Clk)
begin
if (rising_edge(Clk)) then
Wr_Data <= RESIZE(not (Wr_Addr + 1), Wr_Data'length);
Wr_Data_d <= Wr_Data;
Wr_Data_dd <= Wr_Data_d;
assert Rd_Data = Wr_Data_dd
report "Error in memory verification, Wr_Data = " &
to_hstring(Wr_Data_dd) & ", Rd_Data = " & to_hstring(Rd_Data)
severity warning;
end if;
end process;

-- ^[ \t]+([_a-zA-Z0-9\-]+[ \t]+:) [a-zA-Z]+[ \t]+(.+;?$) -- signal \1 \2 -- ^([ \t]+)([_a-zA-Z0-9]+)([ \t]+=>[ \t])[^;]*(;?)$

Mem_Test: entity Blk_mem
generic map (
DataWidth => DataWidth
)
port map (
Clk       => Clk,
Wr_Data   => Wr_Data,
$$$$
`