simulating xilinx block ram with modelsim

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
hi

ich have a problem with a project in ise and modelsim. i used the core
generator to create a single port block memory and instantiated it in
my design. now i want to do a behavioral simulation to verify my
design. i followed the instructions from the core generator help file.
( i used the *.vho file to instantiate the block memory in my design
and downloaded the latest libraries from xilinx for model sim).

but whatever i do to the ports of the memory they always stay 'x'.
shouldn't at least the input port be '0' or '1' if i apply that
signal?

here is the way i instantiated it:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.all;

use work.spi_package.all;

entity spi_memory is
   PORT (     CLK                 : in      STD_LOGIC;
                Data_in             : inout  STD_LOGIC_VECTOR (31 downto 0);
                Data_out         : inout  STD_LOGIC_VECTOR (31 downto 0);
                Address             : in      STD_LOGIC_VECTOR (9 downto 0);
                WR                 : in      STD_LOGIC;
                RD                 : in      STD_LOGIC);
end spi_memory;


architecture Behavioral of spi_memory is

    component spi_mem
        port (
        clka            : IN std_logic;
        dina            : IN std_logic_VECTOR(31 downto 0);
        addra            : IN std_logic_VECTOR(9 downto 0);
        wea            : IN std_logic_VECTOR(0 downto 0);
        douta            : OUT std_logic_VECTOR(31 downto 0));
    end component;

    -- Synplicity black box declaration
--    attribute syn_black_box : boolean;
--    attribute syn_black_box of spi_mem: component is true;

    signal s_write_strobe    : std_logic;


begin

    I_spi_mem: spi_mem
        port map (
            clka => CLK,
            dina => Data_in,
            addra => Address,
            wea => vectorize(s_write_strobe),
            douta => Data_out);


    GENERATE_WRITE_STROBE: process(WR, RD, Address)
    begin

        s_write_strobe <= '0';

        if RD = '0' and WR = '1' and Address >= "0000001010" then

            s_write_strobe <= '1';

        end if;

    end process GENERATE_WRITE_STROBE;

end Behavioral;



could somebody please give me a hint here?

i also compiled the wrapper file in model sim. do i have to
instantiate it somwhere/how? (couldn't find that in the manual)
the other thing is i get a warning in model sim:


# ** Note: Block Memory Generator CORE Generator module is using a
behavioral model for simulation which will not precisely model memory
collision behavior.
#    Time: 1140 ns  Iteration: 1  Instance: /spi_interface_tb_vhd/uut/
i_spi_memory/i_spi_mem/u0


thanks
urban

Re: simulating xilinx block ram with modelsim
Quoted text here. Click to load it

Hopefully it won't be too annoying if I avoid actually answering your
question, and instead suggest that you not use core generator to
instantiate simple memories. You really should infer them. For example,
yours might look something like:

    type mem_array is array(0 to 511) of std_logic_vector(31 downto 0);
    signal ram           : mem_array;

    -- infer block RAM
    wr_p: process(CLK)
    begin
       if rising_edge(CLK) then
          if s_write_Strobe = '1' then
             ram(to_integer(Address)) <= Data_in;
          end if;
       end if;
    end process wr_p;
    rd_p: process(CLK)
    begin
       if rising_edge(CLK) then
          rd_addr_ram <= Address;
       end if;
    end process rd_p;
    Data_Out <= ram(to_integer(rd_addr_ram));

Notice that it is important to register the read address. This is
required to infer block ram. If you don't do that, you will get LUT ram.

Re: simulating xilinx block ram with modelsim
Quoted text here. Click to load it

Hm so in other words, my block RAM wont be infered correctly because I
made the process sensitive to the readaddress as below?


architecture Behavior of ram_data is

     type ram_type is array (0 to SIZE-1) of std_logic_vector (31 downto 0);
     signal ram : ram_type :=
     (   X"00000063",
         X"0000007c",
    ....
    );

     begin
       PROC_ram : process (clk, rw_addr_cp0)
       begin
         if (rst = '0') then -- optional reset
           data_out_cp0 <= (others => '0');
         elsif (clk'event and clk = '1') then
           -- memory write:
           if (ew_cp0 = '1') then
             if (unsigned(rw_addr_cp0) >= 0 and unsigned(rw_addr_cp0) <=
SIZE-1) then
               ram(conv_integer(unsigned(rw_addr_cp0))) <= data_in_cp0;
             end if;
           end if;
         end if;

         -- memory read:
         if (unsigned(rw_addr_cp0) >= 0 and unsigned(rw_addr_cp0) <=
SIZE-1) then
           data_out_cp0 <= ram(conv_integer(unsigned(rw_addr_cp0)));
         end if;
     end process PROC_ram;

end Behavior;


Re: simulating xilinx block ram with modelsim
Quoted text here. Click to load it

That's right, unless rw_addr_cp0 is registered somewhere else. And even
then, different versions of ISE can be somewhat finicky about exactly
how the code is written. Other synthesis tools may have their own
requirements, but a registered read address is universal. I consider it
clearest to keep the register at the place where I am inferring the BRAM.

Re: simulating xilinx block ram with modelsim
Quoted text here. Click to load it

thanks for the hint how to infer block ram. i will try that out!
(why istn't it a good idea to use the core generator for simple block
memory? just beauty reasons?)
i still would be curious though what's wrong the way i tried it?!? can
you give me a hint there?

thanks
urban

Re: simulating xilinx block ram with modelsim
Quoted text here. Click to load it

Beauty is one good reason. Then there is the need to fire up coregen and
and involve a bunch of Xilinx libraries, and get those all compiled
correctly. And changing a parameter, like width or depth requires
another run of coregen. And then there is the issue that the Xilinx
simulation models for the BRAMs are very slow. The inferred method
simulates much faster.

Quoted text here. Click to load it

In your original posting, you said:
Quoted text here. Click to load it

Are you saying that WR and RD are always 'x'? If so, your problem is
likely elsewhere, not with the BRAM model. That generally means you have
two or more places where WR and RD are being driven, or nowhere where
they are being driven.

Re: simulating xilinx block ram with modelsim

Quoted text here. Click to load it

Only if the testbench first does a write cycle
and then a read from the same address.
Otherwise x is probably the right answer.

        -- Mike Treseler

Re: simulating xilinx block ram with modelsim
Quoted text here. Click to load it
Xilinx BlockRAMs must have a clock to perform any operation, even a
read. This is not intuitively obvious, but it is an absolute
requirement.
Peter Alfke, Xilinx

Re: simulating xilinx block ram with modelsim
u snipped-for-privacy@yahoo.de wrote:
Quoted text here. Click to load it

well i used a clock of course..

urban

Re: simulating xilinx block ram with modelsim
[1] As others suggest, make sure that all
inputs are known ... not X.  X in results in
X out.

[2] The test bench should initialize memory
first, then read data, OR use the initialization
attributes of the BLKRAM to initialize values.
I would try the latter first, since if you are
relatively new to simulation, you can get the
READ working before the WRITE.

Take a look at your install directory
/xilinx/doc/usenglish/books/docs/lib.pdf
the section on RAMB for the syntax of initializing
the device contents in your respective language
(Verilog or VHDL).

[3] You may have to add delays to your nets for
some of your incoming signals relative to your
clk.  The unisim models perform timing checks, and
if you violate setup and hold (as you do for RTL
sims ... who cares ... we the sim model does),
the model outputs X.

[4] The suggestion to use inference of memories
is a good one.  For many years I instantiated
BLKRAMs .... my rationale was I synthesized exactly
what I wanted  ... this was based on earlier
experience of fighting tools to synthesize a
certain configuration of memory.  Anyway,
a friend let me know this was terribly inefficient
from a simulation point of view ... and I
disagreed.  So I coded up a testbench for
bench marking purposes of instantiated blkram
vs inferred memory, and the instantiated
blkram ran 5x slower.

Now if you were to pay your tool vendor for
a simulator with 5x performance improvement,
you might go bankrupt.

--

Regards,
John Retta
We've slightly trimmed the long signature. Click to see the full one.
Re: simulating xilinx block ram with modelsim
Quoted text here. Click to load it

thanks for all the replies.
well of course i checked my input signals and i applie values to them.
the rd and wr signals are good aswell as the clk and
the address signal (good meaning that they have a defined level
(either '0' of '1' applied to them)).
a strange thing is that the data_in signal has all 'U' althoug i apply
for example all '0' to it.
this is probably the reason that when i write to the memory and then
read from the same address i get all 'U' in my data_out.
any idea whats wrong here?

entity spi_memory is
   PORT (     CLK                 : in      STD_LOGIC;
                Data_in             : inout  STD_LOGIC_VECTOR (31 downto 0);
                Data_out         : inout  STD_LOGIC_VECTOR (31 downto 0);
                Address             : in      STD_LOGIC_VECTOR (9 downto 0);
                WR                 : in      STD_LOGIC;
                RD                 : in      STD_LOGIC);
end spi_memory;

architecture Behavioral of spi_memory is

    signal s_write_strobe    : std_logic;
    type mem_array is array(0 to 1023) of std_logic_vector(31 downto 0);
        signal ram           : mem_array;
    signal rd_addr_ram    : std_logic_VECTOR(9 downto 0);
begin

    wr_p: process(CLK, Data_in)
    begin
       if rising_edge(CLK) then
          if s_write_Strobe = '1' then

                 ram(to_integer( unsigned ( Address ))) <= Data_in;
          end if;
       end if;
    end process wr_p;

     rd_p: process(CLK, Address)
    begin
       if rising_edge(CLK) then
          rd_addr_ram <= Address;
       end if;
    end process rd_p;

     Data_Out <= ram(to_integer( unsigned( rd_addr_ram )));

    GENERATE_WRITE_STROBE: process(WR, RD, Address)
    begin

        s_write_strobe <= '0';
        if RD = '0' and WR = '1' and Address >= "0000001010" then

            s_write_strobe <= '1';

        end if;
    end process GENERATE_WRITE_STROBE;

end Behavioral;


i drive the data_in signal from the outside testbench..

thanks urban



Re: simulating xilinx block ram with modelsim
On Sun, 18 Nov 2007 10:34:06 -0800 (PST), "u snipped-for-privacy@yahoo.de"

Quoted text here. Click to load it




This may be the problem.

The testbench also drives any signal connected to it via an Out or InOut
or Buffer port... but with what?

If you do not explicitly drive them, .. with "U". This will override any
drivers you add outside the testbench.

You may drive any such signals with 'Z' or (others => 'Z') in the
testbench to overcome this.

But first, (assuming you are using Modelsim) try the "drivers" command
on your signal, in the console window
e.g.
drivers testbench/u1/data_in

You should get a list of all drivers connected to that signal; their
full name in the design hierarchy, and the value they are driving onto
the signal in question. Follow the "U" or "X" back top its source, and
fix the problem.

- Brian

Re: simulating xilinx block ram with modelsim
hi

well yes i'm using model sim:
the driver listing from modelsim for the data_in signal is as follows:

drivers spi_memory_tb_vhd/data_in
# Drivers for /spi_memory_tb_vhd/data_in(31:0):
#    U  : Signal /spi_memory_tb_vhd/data_in(31)
#      0 : Driver /spi_memory_tb_vhd/tb
#      U  : Element /spi_memory_tb_vhd/uut/data_in(31)
#    U  : Signal /spi_memory_tb_vhd/data_in(30)
#      0 : Driver /spi_memory_tb_vhd/tb
#      U  : Element /spi_memory_tb_vhd/uut/data_in(30)
.......
.......
#    U  : Signal /spi_memory_tb_vhd/data_in(1)
#      1 : Driver /spi_memory_tb_vhd/tb
#      U  : Element /spi_memory_tb_vhd/uut/data_in(1)
#    U  : Signal /spi_memory_tb_vhd/data_in(0)
#      1 : Driver /spi_memory_tb_vhd/tb
#      U  : Element /spi_memory_tb_vhd/uut/data_in(0)
#


for all signal in data_in (31 downto 0). so as far as i can tell the
signal data_in is only driven by the testbench (or am i wrong?)
also the singal data_in is defined as IN. so this should be ok.

another thing i tried was that i forced the signal data_in to all '0'
in modelsim. when i then did a write to an address i got a valid
response on the following read  from the same address....
i'm really running out of ideas here....

urban



Re: simulating xilinx block ram with modelsim
On Mon, 19 Nov 2007 09:12:30 -0800 (PST), "u snipped-for-privacy@yahoo.de"

Quoted text here. Click to load it

This tells you  the U is driven onto data_in by your "uut" component.
Therefore Duane's advice applies.

Why does your memory need to drive its Data_In bus?

If it doesn't; simply make Data_in an IN port.
If it does, make the UUT itself ... not the testbench... drive Data_In
with 'Z' as Duane suggested, to replace the "U"...

Either of these should solve the problem.
Having changed the design, use the Drivers command again to verify the
change.

- Brian

Re: simulating xilinx block ram with modelsim

hi

thanks for all your advices! i found the problem.
somehow the signals in the component instantiation got messd up
(although i used the testbench generated by ise).
anyway the problem was that data_in, data_out and RD, WR, CLK where in
the wrong order. the only thing im wondering is,
shouldn't ise or modelsim throw a warning?

urban

Re: simulating xilinx block ram with modelsim
On Tue, 20 Nov 2007 07:15:31 -0800 (PST), "u snipped-for-privacy@yahoo.de"

Quoted text here. Click to load it

That sounds like the real problem was the use of positional association
rather than named association in the port map, making the error hard to
find.

- Brian


Re: simulating xilinx block ram with modelsim
Quoted text here. Click to load it

I just noticed that. Could you explain why Data_in is inout? If you are
going to do that, then a driver is expected somewhere within this code.
And if you don't supply a driver, perhaps a 'U' is inferred. Normally an
inout port would be driven with a piece of code that looks something like:
   Data_in <= Data_inout when DEN = '1' else "ZZZZ...";

Site Timeline