Nic30g
Nic30g

Reputation: 659

write on invalid address to RAM in VHDL, Verilog, sim behaviour

Lets have a BRAM or any other memory under Verilog or VHDL. For example this:

module raminfr (clk, we, a, di, do);   

input clk;   
input we;   
input  [4:0] a;   
input  [3:0] di;   
output [3:0] do;   
reg    [3:0] ram [31:0]; 

  always @(posedge clk) begin   
    if (we)   
      ram[a] <= di;   
  end   
  assign do = ram[a];   
endmodule

Now lets assume that we have already write valid data to "ram".

Does simulators invavalidate all items in "ram" if address "a" will have invalid value (4'bxxxx) ("we"=1 and clk will have posedge)? Or it lets values in ram as they were?

Upvotes: 1

Views: 853

Answers (2)

user1155120
user1155120

Reputation:

For Verilog

The IEEE Std 1800-2009 SystemVerilog standard subsumed both the IEEE Std 1364-2005 Verilog standard and the IEEE Std 1800-2005 SystemVerilog standard. The IEEE Std 1800-2012 SystemVerilog standard supplanted the -2009 version.

See IEEE Std 1800-2012 7.4.6 Indexing and slicing of array:

If an index expression is out of bounds or if any bit in the index expression is x or z, then the index shall be invalid. Reading from an unpacked array of any kind with an invalid index shall return the value specified in Table 7-1. Writing to an array with an invalid index shall perform no operation, with the exceptions of writing to element [$+1] of a queue (described in 7.10.1) and creating a new element of an associative array (described in 7.8.6). Implementations may issue a warning if an invalid index occurs for a read or write operation on an array.

For VHDL

An equivalent VHDL design description might be:

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

entity raminfr is
    port (
        clk:  in  std_logic;
        we:   in  std_logic;
        a:    in  std_logic_vector(4 downto 0);
        di:   in  std_logic_vector(3 downto 0);
        do:   out std_logic_vector(3 downto 0)
    );
end entity;

architecture behave of raminfr is
    type ram_type is array (0 to 15) of std_logic_vector (3 downto 0);
    signal ram:  ram_type;
begin
    process (clk)
    begin
        if rising_edge(clk) then
            if we = '1' then
                ram(to_integer(unsigned(a))) <= di;
            end if;
        end if;
end process;
    do <= ram(to_integer(unsigned(a)));
end architecture;

Where the numeric_std package to_integer function is used to convert the array value of a to an integer index. (VHDL is a bit more flexible here, array indexes can either be integer types or enumerated types, together referred to as discrete types).

Reading the source for to_integer we see it will convert an input unsigned array value containing an 'X' to all 'X's and the 'LEFT value of that being 'X' will return a natural integer subtype value of 0 and optionally report that:

if (XARG(XARG'left) = 'X') then
      assert NO_WARNING
        report "NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0"
        severity warning;
      return 0;
    end if;

These warnings can be disabled implementation wide by changing the value of NO_WARNING which is locally static. Using to_integer (or with Synopsys package std_logic_arith and function conv_integer) the index will be 0.

Additionally VHDL implementations have the ability to stop simulation on severity warning reports.

While you could handle the result of an assignment with an index provided as an array value differently in (as in 2, 4, 8, 16 or 32 invalidated memory locations depending on the number of 'X' element values of a here), you've already compromised the integrity of your design model state and some corrective should be taken before counting on the simulation results for either a SystemVerilog or VHDL design model.

The overhead of complex fiddling doesn't seem worthwhile in general. These warnings are of a class of warnings that should be reviewed before synthesis.

These warning can occur before array values are reset when their default initial values are metavalues. You can prevent that in most FPGA designs by initializing a and any predecessors so a contains a binary representing value or simply ignoring reports at time 0 before a reset takes affect.

You can also prevent the write to address 0 by initializing we and any predecessor(s) to '0'.

Upvotes: 1

Serge
Serge

Reputation: 12354

Simulator will not invalidate anything. Instead the write will be ignored.

For reads in such a situation, it will return 'x' though.

Upvotes: 0

Related Questions