Initializing memory from a testbench

R

rickman

Guest
I am testing a VHDL design using embedded CPU program memory which needs
to be initialized. The data to be stored in the RAM comes from an
external source and will be part of the configuration download in the
final system. During simulation, I can't seem to figure out how to
initialize it. I thought I might use the test bench to read the data
from a file, but I can't figure out how to access the memory since it
does not have an external interface. If I add logic to initialize the
memory from the test bench, this will be unused in the real chip and so
I will have a difference between my simulated chip and the real chip. I
prefer not to do that. I have been using an initial value on the memory
variable declaration, but the data changes as I work and this is very
clumsy.

I also saw an example using a shared variable with one process being the
normal memory model and the other being an init routine. But again,
this will use code that is only part of the simulation and should not be
there for the end device. I guess the code will not be synthesized, but
since it has to be in the target source and not the test bench, it will
either need to be removed or it will likely produce errors in synthesis.

Is there a way to directly access an internal signal or variable from a
test bench? I seem to recall doing this before, but it was a long time
ago and I may be getting a simulator command mixed up with VHDL.

--

Rick "rickman" Collins

rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.

Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
 
rickman wrote:

I am testing a VHDL design using embedded CPU program memory which needs
to be initialized. The data to be stored in the RAM comes from an
external source and will be part of the configuration download in the
final system. During simulation, I can't seem to figure out how to
initialize it.
You might model the data block as a vhdl constant array of vectors.

-- Mike Treseler
 
Hi,

initialize it. I thought I might use the test bench to read the data
from a file, but I can't figure out how to access the memory since it
does not have an external interface. If I add logic to initialize the
Normally simulators provide TCL commands to do this, for instance
MTI has:

mem load & mem save.

NCSIM has

memory -read
memory -dump

I believe VCSMX also has similar command(s). Which simulator do you
use?

rickman <spamgoeshere4@yahoo.com> wrote in message news:<413F93AF.393AEDF0@yahoo.com>...
memory from the test bench, this will be unused in the real chip and so

Is there a way to directly access an internal signal or variable from a
test bench? I seem to recall doing this before, but it was a long time
ago and I may be getting a simulator command mixed up with VHDL.

Again it is simulator dependent, MTI has SignalSpy, NC - NCMirror etc.
Some time ago I wrote a simple package to keep the TB code little
independent of simulator by having "probe" commands and converting
them to target simulators via a package, please see:

http://www.noveldv.com/eda/probe.zip

HTH,
Aji
http://www.noveldv.com
 
Mike Treseler wrote:
rickman wrote:

I am testing a VHDL design using embedded CPU program memory which needs
to be initialized. The data to be stored in the RAM comes from an
external source and will be part of the configuration download in the
final system. During simulation, I can't seem to figure out how to
initialize it.

You might model the data block as a vhdl constant array of vectors.
Thanks for the response, but the question is not how to declare the
signal or variable. That is not at issue. The question is how to
initialize the data in a way that does not require a recompliation of
the target code. Or better yet, no recompliation of the test bench
either, but rather reading the data from a file.

--

Rick "rickman" Collins

rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.

Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
 
"rickman" <spamgoeshere4@yahoo.com> wrote in message
news:41406314.3B163976@yahoo.com...
Mike Treseler wrote:

rickman wrote:

I am testing a VHDL design using embedded CPU program memory
which needs
to be initialized. The data to be stored in the RAM comes from
an
external source and will be part of the configuration download
in the
final system. During simulation, I can't seem to figure out how
to
initialize it.

You might model the data block as a vhdl constant array of
vectors.

Thanks for the response, but the question is not how to declare the
signal or variable. That is not at issue. The question is how to
initialize the data in a way that does not require a recompliation
of
the target code. Or better yet, no recompliation of the test bench
either, but rather reading the data from a file.

One way to do it is to write a function to read in the vectors from
a file, and then initialize a constant array of vectors to the
value of the function. E.g.

subtype wordT is std_logic_vector(15 downto 0); -- e.g.
type RomT is array (0 to 1023) of wordT;
constant MyRom : arrayT := FNFillRom("file name");

The advantage of this is that the ROM gets filled during elaboration,
and so is instantly available at time 0. The disadvantage is there's
no
direct link to synthesis - unless I suppose you write the function
to read in the file in the format that your target technology
supports.

I guess you'd also have to do some horrible translate on/off stuff,
e.g.

constant MyRom : arrayT
-- synopsys synthesis_off
:= FNFillRom("file name")
-- synopsys synthesis_on
;

Does this help?

regards
Alan

--
Alan Fitch
Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24
1AW, UK
Tel: +44 (0)1425 471223 mail:
alan.fitch@doulos.com
Fax: +44 (0)1425 471573 Web:
http://www.doulos.com

The contents of this message may contain personal views which are not
the
views of Doulos Ltd., unless specifically stated.
 
"rickman" <spamgoeshere4@yahoo.com> escribió en el mensaje
news:413F93AF.393AEDF0@yahoo.com...
I am testing a VHDL design using embedded CPU program memory which needs
to be initialized. The data to be stored in the RAM comes from an
external source and will be part of the configuration download in the
final system. During simulation, I can't seem to figure out how to
initialize it. I thought I might use the test bench to read the data
from a file, but I can't figure out how to access the memory since it
does not have an external interface. If I add logic to initialize the
memory from the test bench, this will be unused in the real chip and so
I will have a difference between my simulated chip and the real chip. I
prefer not to do that. I have been using an initial value on the memory
variable declaration, but the data changes as I work and this is very
clumsy.

I also saw an example using a shared variable with one process being the
normal memory model and the other being an init routine. But again,
this will use code that is only part of the simulation and should not be
there for the end device. I guess the code will not be synthesized, but
since it has to be in the target source and not the test bench, it will
either need to be removed or it will likely produce errors in synthesis.

Is there a way to directly access an internal signal or variable from a
test bench? I seem to recall doing this before, but it was a long time
ago and I may be getting a simulator command mixed up with VHDL.

how about enclosing the initialisation part of the RAM (i guess you use a
function that reads a file) between the pragmas "synopsys synthesis_off" and
"synopsys synthesis_on"? (if you're initialising thru a function you should
avoid synthetising it too in the same way)

and as for accessing an internal signal, i know that you can "up" hierarchy
by specifiying it's full "pathname", but i dont know if it works "down"
hierarchy, you can always try.
 
Alan wrote:

subtype wordT is std_logic_vector(15 downto 0); -- e.g.
type RomT is array (0 to 1023) of wordT;
constant MyRom : arrayT := FNFillRom("file name");

The advantage of this is that the ROM gets filled during elaboration,
and so is instantly available at time 0. The disadvantage is there's
no direct link to synthesis - unless I suppose you write the function
to read in the file in the format that your target technology
supports.
Another possible solution is to use perl or bash
to convert the external hex file to a deferred
constant package body something like:

constant MyRom : arrayT :=
(
-- begin data
x"0000",
x"0001",
x"0002",
x"0004",
x"0008",
x"0010",
x"0020",
x"0040"
-- ...
-- end data
);

This would give you synthsizable code,
but require running the script and
a "vcom myPackageBody.vhd" for
each iteration.

-- Mike Treseler
 
roller wrote:
and as for accessing an internal signal, i know that you can "up" hierarchy
by specifiying it's full "pathname", but i dont know if it works "down"
hierarchy, you can always try.
I was trying to do that, but I can't figure out the format for
specifying the heiarchy. I looked in the LRM and could not find any
references to that. What is used as separators in a "path" name?

--

Rick "rickman" Collins

rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.

Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
 
"rickman" <spamgoeshere4@yahoo.com> escribió en el mensaje
news:4140967F.2EF867B@yahoo.com...
roller wrote:

and as for accessing an internal signal, i know that you can "up"
hierarchy
by specifiying it's full "pathname", but i dont know if it works "down"
hierarchy, you can always try.

I was trying to do that, but I can't figure out the format for
specifying the heiarchy. I looked in the LRM and could not find any
references to that. What is used as separators in a "path" name?
it's the dot like in Ada (and Java, or like "use work.package.all") though
it's been a long time since i read about it (plus i havent ever used it)
maybe you can check the visibility rules or tutorials explaining that, sorry
i couldnt help you more

http://tech-www.informatik.uni-hamburg.de/vhdl/doc/faq/FAQ1.html#visibility
 
roller wrote:
"rickman" <spamgoeshere4@yahoo.com> escribió en el mensaje
news:4140967F.2EF867B@yahoo.com...
roller wrote:

and as for accessing an internal signal, i know that you can "up"
hierarchy
by specifiying it's full "pathname", but i dont know if it works "down"
hierarchy, you can always try.

I was trying to do that, but I can't figure out the format for
specifying the heiarchy. I looked in the LRM and could not find any
references to that. What is used as separators in a "path" name?


it's the dot like in Ada (and Java, or like "use work.package.all") though
it's been a long time since i read about it (plus i havent ever used it)
maybe you can check the visibility rules or tutorials explaining that, sorry
i couldnt help you more

http://tech-www.informatik.uni-hamburg.de/vhdl/doc/faq/FAQ1.html#visibility
Thanks for the info. Seems the way I am trying to access the shared
variable is called a "selected name". But that will not work outside of
the scope of the variable. So I am back to trying to find a way to make
life easy in the simulation.

At this point, the external program to generate a deferred constant
package seems like it has the best chance of working. It also may do
the job for synthesis as well as simulation. But my program memory is
not constant, it is read/write, so I may have to do an assignment
between them and hope the synthesis tool can figure that out rather than
to make two arrays and generate logic to copy them. :)

Thanks again. I will try to remember the 'dot' thing in the future.

--

Rick "rickman" Collins

rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.

Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
 
Mike Treseler wrote:
Alan wrote:

subtype wordT is std_logic_vector(15 downto 0); -- e.g.
type RomT is array (0 to 1023) of wordT;
constant MyRom : arrayT := FNFillRom("file name");

The advantage of this is that the ROM gets filled during elaboration,
and so is instantly available at time 0. The disadvantage is there's
no direct link to synthesis - unless I suppose you write the function
to read in the file in the format that your target technology
supports.

Another possible solution is to use perl or bash
to convert the external hex file to a deferred
constant package body something like:

constant MyRom : arrayT :=
(
-- begin data
x"0000",
x"0001",
x"0002",
x"0004",
x"0008",
x"0010",
x"0020",
x"0040"
-- ...
-- end data
);

This would give you synthsizable code,
but require running the script and
a "vcom myPackageBody.vhd" for
each iteration.
This just might do the job. My only concern has to do with the fact
that my program memory is actually read/write, so the ram will have to
be initialized to this constant data. I don't know if the synthesis
tool can understand that this does not require two memories. :)


--

Rick "rickman" Collins

rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.

Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
 
Mike wrote:
Another possible solution is to use perl or bash
to convert the external hex file to a deferred
constant package body something like:

I wrote one of those a few years back; I've attached the
latest version below, along with some sample files:

<test.obj> input object file
<test.vh1> generated package with constant array
<test.vh2> generated package with INITs

<ylink.pl> perl 'linker' that creates VHDL source files

The perl script reads the assembler object file and coughs up
two VHDL files, one a package with a constant array suitable
for simulation or inferred RAM, the other a package with INITs
and generics for instantiated BRAMs.

At the time I wrote this, XST didn't support indexing into a
constant array from within a generate loop; I believe the current
XST version would allow putting the INITs into an array, making
it easier to support BRAM organizations other than the currently
hardcoded 512x32 (four RAMB4_S8_S8's ).

Also, some old posts regarding how to initialize dual port variable
width BRAMs (Harvard architecture, 16 bit instruction, 32 bit data)
are at:
http://groups.yahoo.com/group/fpga-cpu/message/234
http://groups.yahoo.com/group/fpga-cpu/message/332

Other ROM generation programs:

If you download MikeJ's nifty Asteroids emulation, there's a
C++ 8 bit ROM generation utility included <romgen.cpp>.
http://home.freeuk.com/fpgaarcade/ast_main.htm

Mike Butts has a hex2init perl script (more elegant than mine) that
generates a constraints file for 16 bit memories :
http://users.easystreet.com/mbutts/xr16vx_jhdl.html

Also, I believe the newer versions of Xilinx's DATA2MEM utility
will cough up a file with INIT's for primitive simulation as well
as update an existing bitstream with new memory data.

Brian


<test.obj>
@0
opcode=0000011111110000
opcode=0000011111110000
opcode=0000010111110000
opcode=0000010111110000
opcode=0000010111110000
opcode=0000001111110000
opcode=0000001111110000
opcode=0000001111110000
@200
long=12345678
word=abcd
byte=de
byte=ad
byte=be
byte=ef

<test.vh1>
--
-- Auto-generated by ylink.pl
--
library ieee;
use ieee.std_logic_1164.all;

package mem_dat_pkg is

constant MEM_SIZE : natural := 1024;

type mem_type is array (0 to MEM_SIZE-1) of std_logic_vector (15
downto 0);

constant mem_dat : mem_type :=
(
0 => X"07F0",
1 => X"07F0",
2 => X"05F0",
3 => X"05F0",
4 => X"05F0",
5 => X"03F0",
6 => X"03F0",
7 => X"03F0",
256 => X"1234",
257 => X"5678",
258 => X"abcd",
259 => X"dead",
260 => X"beef",

others => ( others => '0')
);

end mem_dat_pkg;

<test.vh2>
--
-- Auto-generated by ylink.pl
--
library ieee;
use ieee.std_logic_1164.all;

package mem_init_pkg is

constant RAM3_INIT_00 : string :=
"0000000000000000000000000000000000000000000000000000000003050507";
constant RAM2_INIT_00 : string :=
"00000000000000000000000000000000000000000000000000000000F0F0F0F0";
constant RAM1_INIT_00 : string :=
"0000000000000000000000000000000000000000000000000000000003030507";
constant RAM0_INIT_00 : string :=
"00000000000000000000000000000000000000000000000000000000F0F0F0F0";

constant RAM3_BV_INIT_00 : bit_vector :=
X"0000000000000000000000000000000000000000000000000000000003050507";
constant RAM2_BV_INIT_00 : bit_vector :=
X"00000000000000000000000000000000000000000000000000000000F0F0F0F0";
constant RAM1_BV_INIT_00 : bit_vector :=
X"0000000000000000000000000000000000000000000000000000000003030507";
constant RAM0_BV_INIT_00 : bit_vector :=
X"00000000000000000000000000000000000000000000000000000000F0F0F0F0";

<snip>

constant RAM3_INIT_04 : string :=
"0000000000000000000000000000000000000000000000000000000000beab12";
constant RAM2_INIT_04 : string :=
"0000000000000000000000000000000000000000000000000000000000efcd34";
constant RAM1_INIT_04 : string :=
"000000000000000000000000000000000000000000000000000000000000de56";
constant RAM0_INIT_04 : string :=
"000000000000000000000000000000000000000000000000000000000000ad78";

constant RAM3_BV_INIT_04 : bit_vector :=
X"0000000000000000000000000000000000000000000000000000000000beab12";
constant RAM2_BV_INIT_04 : bit_vector :=
X"0000000000000000000000000000000000000000000000000000000000efcd34";
constant RAM1_BV_INIT_04 : bit_vector :=
X"000000000000000000000000000000000000000000000000000000000000de56";
constant RAM0_BV_INIT_04 : bit_vector :=
X"000000000000000000000000000000000000000000000000000000000000ad78";

<snip>

constant RAM3_INIT_0F : string :=
"0000000000000000000000000000000000000000000000000000000000000000";
constant RAM2_INIT_0F : string :=
"0000000000000000000000000000000000000000000000000000000000000000";
constant RAM1_INIT_0F : string :=
"0000000000000000000000000000000000000000000000000000000000000000";
constant RAM0_INIT_0F : string :=
"0000000000000000000000000000000000000000000000000000000000000000";

constant RAM3_BV_INIT_0F : bit_vector :=
X"0000000000000000000000000000000000000000000000000000000000000000";
constant RAM2_BV_INIT_0F : bit_vector :=
X"0000000000000000000000000000000000000000000000000000000000000000";
constant RAM1_BV_INIT_0F : bit_vector :=
X"0000000000000000000000000000000000000000000000000000000000000000";
constant RAM0_BV_INIT_0F : bit_vector :=
X"0000000000000000000000000000000000000000000000000000000000000000";

end mem_init_pkg;



<ylink.pl>
#! /usr/local/bin/perl5

#-------------------------------------------------------------------------------
# YARD-1 Linker v0.01
#-------------------------------------------------------------------------------


#-------------------------------------------------------------------------------
#
# ylink.pl v0.01 (C) COPYRIGHT 2001 B. Davis
#
# This program is free software; you may use, modify, and
# redistribute it without restriction provided that:
# 1) this header is preserved on all copies
# 2) any modified versions are clearly identified as such
#
# Being free software, this program comes with neither support
# nor warranty, including any implied warranty of merchantability
# or fitness for a particular purpose.
#
#-------------------------------------------------------------------------------


#-------------------------------------------------------------------------------
#
# General Notes:
#
# - reads .obj file generated by yasm.pl
# - writes VHDL file with INIT_XX constants
#
# currently, more of a memory image generator than a real linker
#
# - linker output files:
# - <file>.vh2 = VHDL file with INIT_XX constants
# - <file>.vh1 = VHDL file with constant array holding memory
data
# - <file>.cmd = YARDBUG command file to load program
#
#
#-------------------------------------------------------------------------------


#-------------------------------------------------------------------------------
#
# 'to do' list:
#
#
# - add command line args for:
# - memory image start/size
# - block RAM organization ( generate different INIT_XX records
as needed )
# - VHDL output file name and/or package name in VHDL file
#
# - add other output formats:
# - S-record or similar hex format
# - EPIC command script for editing block RAM
# - .coe for COREGEN created memories
#
#
#-------------------------------------------------------------------------------


#-------------------------------------------------------------------------------
#
# history:
#
# Nov. 2001
# - moved VHDL constant array file (.vh1) generation here from
yasm.pl
#
# Jul. 2001
# - added bit vector INIT's for simulation generics ( instead of
writing VHDL xlate function )
#
# Mar. 2001
# - changed memory image and INIT code to use byte array instead of
word array
#
# Feb. 2001
# - created
#
#
#
#-------------------------------------------------------------------------------


printf("\nYARD-1 Linker Version 0.01\n");

# should have one argument, the object file
if ($#ARGV != 0) { die ("\nError: Expecting one (and only one) object
file \n") };

$obj = $ARGV[0];
$obj =~ s/\.obj$//g;

$obj_file = $obj . '.obj';
$cmd_file = $obj . '.cmd';
$vho_file = $obj . '.vh2';
$vhc_file = $obj . '.vh1';

open (OBJ_F, "$obj_file") or die ("Can't open $obj_file: $!\n");
open (CMD_F, ">$cmd_file") or die ("Can't open $cmd_file: $!\n");
open (VHO_F, ">$vho_file") or die ("Can't open $vho_file: $!\n");
open (VHC_F, ">$vhc_file") or die ("Can't open $vhc_file: $!\n");

#
# vhdl INIT output file header/trailer
#
$vho_file_header = "--
-- Auto-generated by ylink.pl
--
library ieee;
use ieee.std_logic_1164.all;

package mem_init_pkg is

";

$vho_file_trailer = "

end mem_init_pkg;
";


#
# vhdl constant array output file header/trailer
#
$vhc_file_header = "--
-- Auto-generated by ylink.pl
--
library ieee;
use ieee.std_logic_1164.all;

package mem_dat_pkg is

constant MEM_SIZE : natural := 1024;

type mem_type is array (0 to MEM_SIZE-1) of std_logic_vector (15
downto 0);

constant mem_dat : mem_type :=
(
";

$vhc_file_trailer = "
others => ( others => '0')
);

end mem_dat_pkg;

";

# $D1 turns debug prints on/off
$D1 = 0;

#
# memory array definitions ( for INIT_XX attribute calculation )
# currently hardcoded for a 2K byte RAM starting at zero
# indexed by bytes
# values stored as two digit hex string
#
$mem_init_value = "XX";
$mem_start = 0;
$mem_size = 2048;

#
# initialize memory image array
#
$mem_data[$mem_size-1] = $mem_init_value;
for($i=0 ; $i < $mem_size; $i++ ) { $mem_data[$i] = $mem_init_value;}

# clear other flags
$error = 0;

#
# Read .obj file, build memory image
#
while ($line = <OBJ_F>)
{
chop $line;

if ($line =~ /@(.+)/)
{
$address = oct ( "0x" . $1 );
}

elsif ($line =~ /opcode=(\d{16})$/)
{
$op16 = vec(pack("B16", $1),0,16);
$dat_str = sprintf "%04X", $op16;
$mem_data[ $address - $mem_start ] =
substr($dat_str,0,2);
$mem_data[ $address - $mem_start + 1 ] =
substr($dat_str,2,2);
$address = $address + 2;
}

elsif ($line =~ /byte=(.{2})$/)
{
$mem_data[ $address - $mem_start ] = $1;
$address = $address + 1;
}

elsif($line =~ /word=(.{4})$/)
{
$mem_data[ $address - $mem_start ] = substr($1,0,2);
$mem_data[ $address - $mem_start + 1 ] = substr($1,2,2);
$address = $address + 2;
}

elsif($line =~ /long=(.{8})$/)
{
$dat_str = substr($1,0,2);
$mem_data[ $address - $mem_start ] = $dat_str;

$dat_str = substr($1,2,2);
$mem_data[ $address - $mem_start + 1 ] = $dat_str;

$dat_str = substr($1,4,2);
$mem_data[ $address - $mem_start + 2 ] = $dat_str;

$dat_str = substr($1,6,2);
$mem_data[ $address - $mem_start + 3 ] = $dat_str;

$address = $address + 4;
}

} # end while


#
# Write YARDBUG command file
#
$c_start = -1;

for($i=0 ; $i < $mem_size; $i++ )
{
if ( $c_start == -1)
{
if ( $mem_data[$i] ne "XX" )
{
$c_start = $i;
printf CMD_F ("M %08X %s ", $i,$mem_data[$i] );
}
}

else
{
if ( $mem_data[$i] ne "XX" )
{
printf CMD_F ("%s ", $mem_data[$i]);
}

if ( ( $mem_data[$i] eq "XX" ) || ( $i >= ($c_start + 15) ) )
{
$c_start = -1;
printf CMD_F ("\n" );
}
}
}

printf CMD_F ("\n" );



#
# Write VHDL constant array file
#

# create output file boilerplate
print VHC_F $vhc_file_header;

# dump memory values to VHDL word array ( dumps only word locations
being used )
for($i=0 ; $i < $mem_size; $i+=2 )
{
if ( ( $mem_data[$i] ne "XX" ) || ( $mem_data[$i+1] ne "XX" ) )
{
printf VHC_F (" %12d => X\"%s%s\", \n", $i >> 1,
$mem_data[$i], $mem_data[$i+1] );
}
}

# VHDL boilerplate to end memory array
print VHC_F $vhc_file_trailer;


#
# fill unused locations with zeroes before calculating INIT strings
#
for($i=0 ; $i < $mem_size; $i++ )
{
if ( $mem_data[$i] eq "XX" )
{
$mem_data[$i] = "00";
}
}

#
# Write VHDL blockram init file
#

# create output file boilerplate
print VHO_F $vho_file_header;

#
# spit out INIT_XX strings
# - currently hardcoded to read a 2K x 8 memory image array
# - writes INIT's for a 512 x 32 block RAM built from four
RAMB4_S8_S8's
#
$init_blks = 16;
$init_blk_size = 32;
$init_str_size = 64;

for ( $i=0 ; $i < $init_blks; $i++ ) # INIT_00 through INIT_0F
{
for ( $j=0 ; $j < $init_blk_size; $j++ ) # 32 longs (32 bit) per
INIT block
{
# two hex chars. per word for each x8 BRAM; LSB value = last
char in string
$str_index = $init_str_size - ( $j*2 ) - 1;

# byte address in memory array
$baddr = ( $i * $init_blk_size * 4 ) + ( $j * 4 );

$s3[$str_index-1] = substr($mem_data[$baddr], 0, 1);
$s3[$str_index] = substr($mem_data[$baddr], 1, 1);

$s2[$str_index-1] = substr($mem_data[$baddr+1], 0, 1);
$s2[$str_index] = substr($mem_data[$baddr+1], 1, 1);

$s1[$str_index-1] = substr($mem_data[$baddr+2], 0, 1);
$s1[$str_index] = substr($mem_data[$baddr+2], 1, 1);

$s0[$str_index-1] = substr($mem_data[$baddr+3], 0, 1);
$s0[$str_index] = substr($mem_data[$baddr+3], 1, 1);

if ($D1) { printf ("INIT: %d %d %d %d %s %s\n", $i, $j,
$str_index, $baddr, $mem_data[$baddr],$mem_data[$baddr+1] ); }
if ($D1) { printf ("INIT: %d %d %d %d %s %s\n", $i, $j,
$str_index-1, $baddr+1, $mem_data[$baddr+2], $mem_data[$baddr+3] ); }
}

printf VHO_F ("constant RAM3_INIT_%02X : string :=
\"%s\";\n", $i, join('', @s3) );
printf VHO_F ("constant RAM2_INIT_%02X : string :=
\"%s\";\n", $i, join('', @s2) );
printf VHO_F ("constant RAM1_INIT_%02X : string :=
\"%s\";\n", $i, join('', @s1) );
printf VHO_F ("constant RAM0_INIT_%02X : string :=
\"%s\";\n", $i, join('', @s0) );
printf VHO_F ("\n");
printf VHO_F ("constant RAM3_BV_INIT_%02X : bit_vector :=
X\"%s\";\n", $i, join('', @s3) );
printf VHO_F ("constant RAM2_BV_INIT_%02X : bit_vector :=
X\"%s\";\n", $i, join('', @s2) );
printf VHO_F ("constant RAM1_BV_INIT_%02X : bit_vector :=
X\"%s\";\n", $i, join('', @s1) );
printf VHO_F ("constant RAM0_BV_INIT_%02X : bit_vector :=
X\"%s\";\n", $i, join('', @s0) );
printf VHO_F ("\n");

}

# finish up output file boilerplate
print VHO_F $vho_file_trailer;


# tidy up
close OBJ_F;
close CMD_F;
close VHO_F;
close VHC_F;

printf("\nTotal Errors = %d\n", $error);
 

Welcome to EDABoard.com

Sponsor

Back
Top