ModelSim Natural arg value is negative

Hello Folks,

Listed below is a simple NoBL SRAM model that I use to help me debug. Recently, I've been getting a ModelSim error numstd_conv_unsigned_nu Natural arg value is negative. I Googled this and found it to an issue with the to_unsigned function and the natural must be from the 'length attribute? I guess; don't know. please help.

Brad Smallridge AiVision

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity memory is

port( clk : in std_logic; mem_wr : in std_logic; -- active high memory write mem_addr : in std_logic_vector(17 downto 0); --18 bits 256K mem_wr_data : in std_logic_vector(35 downto 0); mem_rd_data : out std_logic_vector(35 downto 0) ); end memory;

architecture beh of memory is

signal mem_wr_1 : std_logic; signal mem_wr_2 : std_logic; signal mem_addr_1 : std_logic_vector(17 downto 0); signal mem_addr_2 : std_logic_vector(17 downto 0);

-- keep the size of the memory small here

-- to keep ModelSim simulation convenient constant size : integer := 127; type mem_array_type is array(0 to size) of integer; signal mem_array : mem_array_type; begin

memory_proc:process(clk) variable addr1 : integer; variable addr2 : integer; begin if(clk'event and clk='1')then mem_wr_1

Reply to
Brad Smallridge
Loading thread data ...

[snip model]

You've used an array of integers to model the memory's storage. This is a neat idea - efficient for simulation - BUT your memory is 36 bits wide, which won't fit into an integer!

The specific problem you're seeing is almost certainly that you are reading from an unwritten location. For example, on the first few clock cycles the memory will do reads from location 0 which hasn't yet been written, because the X/U values on address will be converted to zero by the numeric_std.to_integer() conversion on the address. (Did you see warnings for that, or did you suppress them?) Unwritten (uninitialised) integers in your memory array will start life at the most negative possible value.

The fix to your immediate problem is to declare the memory storage as an array of natural rather than integer, so that its contents initialise to zero. This will stop the conversion overflows, but will still leave you unable to represent more than 31 bits in each integer data word. Another possible hack is to keep the integers, and detect value

Reply to
Jonathan Bromley

Excellent! Jonathan.

I was wondering what those strange initial numbers were.

I tried to divide the memory into two parts, mem_hi and mem_lo, but got errors when mem_lo was 31 downto 0 in length. Dividing it half-half like you suggeted seems OK, but the objective was to see the memory data in its entirety.

The std_logic_vector approach works much cleaner. How inefficient is it? Does it use burn an integer for each bit of simulated memory? Or 36 to 1 inefficiency? The code is shown below.

Thanks again,

Brad Smallridge AiVision

The code:

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;

entity mem_tri is port( clk : in std_logic; mem_wr_n : in std_logic; -- active low memory write mem_addr : in std_logic_vector(17 downto 0); --18 bits 256K mem_data : inout std_logic_vector(35 downto 0) ); end mem_tri;

architecture beh of mem_tri is

signal mem_wr_1 : std_logic; signal mem_wr_2 : std_logic; signal mem_addr_1 : std_logic_vector(17 downto 0); signal mem_addr_2 : std_logic_vector(17 downto 0); signal mem_rd_data : std_logic_vector(35 downto 0);

-- keep the size of the memory small here -- to keep ModelSim simulation convenient constant size : integer := 128; type mem_array_type is array(0 to size-1) of std_logic_vector(35 downto

0); signal mem_array : mem_array_type;

begin

memory_proc:process(clk) variable addr1 : integer; variable addr2 : integer; begin if(clk'event and clk='1')then mem_wr_1

Reply to
Brad Smallridge

Then it is probably best to represent it as a vector.

On the other hand, if you represent it as a pair (or more) of integers, you will surely convert it to/from a vector on read and write, so you will get to see it "whole" at that point.

If you want to see it *whilst it's in the memory*, then consider storing it in 16-bit pieces (in integers). You can then display each location in hex, and it will look something like this in the wave and list views:

{0004 8fe7 327e}

so you can see your 36-bit value easily enough. It'll still cost you some messy conversion functions, though.

I don't know. On the face of it you'd expect the simulator to spend one byte (or, perhaps, one word) for each std_logic bit. But the std_logic and numeric_std packages have highly optimised implementations in the simulator, so I wouldn't be so sure. In any case, you are restricting the size of your memory - so its total footprint will be insignificant. If you really need lots of modelled memory, take a look at the docs on "sparse memories" - that's now implemented in at least some variants of Modelsim/Questa.

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which 
are not the views of Doulos Ltd., unless specifically stated.
Reply to
Jonathan Bromley

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.