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
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?
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:
"rickman" escribió en el mensaje news: snipped-for-privacy@yahoo.com...
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.
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
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
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
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
I wrote one of those a few years back; I've attached the latest version below, along with some sample files:
input object file generated package with constant array generated package with INITs 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:
formatting link
formatting link
Other ROM generation programs:
If you download MikeJ's nifty Asteroids emulation, there's a C++ 8 bit ROM generation utility included .
formatting link
Mike Butts has a hex2init perl script (more elegant than mine) that generates a constraints file for 16 bit memories :
formatting link
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.
#------------------------------------------------------------------------------- # # 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: # - .vh2 = VHDL file with INIT_XX constants # - .vh1 = VHDL file with constant array holding memory data # - .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") };
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");
# # 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;
# # 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;
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.