Problems opening files from a VHDL process into an entity instantiated twice: name conflicts - vhdl

I have an entity in VHDL which has the following structure:
-- Imports...
entity myentity is
port (..specifying in and out signals..);
end myentity;
architecture beh_myentity of myentity is
begin
process(..sensitivity list..)
-- Some variables
file myfile : text open write_mode
is "myentlog.txt"; -- <== My problem is here!!!
begin
-- ..The process body..
end process;
end beh_myentity;
No problems in opening the file, everything works! I have a problem. When I create a testbench and run it I usually create one single instance of my entity. But in my case I now need to put two instances. My problem is that I will have conflicts with file name and one process will inevitably fail opening and writing the (same) log file.
I would like to solve this, so here the questions:
In my port I have signals, is it ok to append a signal value to the name of the file? I am afraid this is not the best thing to do (not even know if such a thing would work).
Is there a way to get a variable representing the instance name of the entity in the testbench?
is there a way to pass a string to the entity so that I can attach it at the end of the file name?
Thankyou

Either a signal of type string, containing the filename; or a generic (again, of type string).
The signal allows you to assign different filenames to the same entity at different times in your testbench - using VHDL-1993 or later, the architecture can call file_open() with the new filename.
The generic gives a fixed filename to each different entity.
Use whichever is simplest for your application.
Your specific questions :
1) Yes , if the signal is a string, you can either pass in the whole filename as a string or pass in a suffix. Because you are generating the string at runtime you need VHDL-93 (or later) syntax
process (...) is
file my_file;
begin
file_open(my_file, base_name & suffix & ".txt", read_mode);
...
file_close(my_file);
end process;
2) Best way is to generate the filename in the testbench and pass it in. However an out port from the entity would work! Naturally you can't synthesise this entity...
3) Of course...
entity myentity is
generic ( base_name : string := "testfile");
port (suffix : in string);
end myentity;
will pass in the strings you needed in (2).
If you must use VHDL-87 syntax, as in your example, pass the whole name in as a generic:
file myfile : text open write_mode is base_name;

Try passing the file name as a generic, instead of a port.
http://www.ics.uci.edu/~jmoorkan/vhdlref/generics.html

Related

Assign Signal names dynamically from a String in CAPL

I have a string that stores a signal name extracted from an excel file.
I want to dynamically assign the name of the signal using the string, if I have many such signals.
For example, if I have a signal called 'speed' in my dbc file, and I have a string that stores 'speed', I need to set the value of signal 'speed' as 100.
variable
{
message BCM BCM;
char signal[100]= "speed";
}
on message *
{
$signal= 100;
}
The error I get is:
Error: Identifier 'signal' does not have a signal type.
Is there a workaround to this problem, such that I can convert the string into a signal name by some means?
You are mixing the variable formats like this. The only object on which you can use $ is dbSignal type. What you would need is a function like getSignal(dbSignal name);, but with char[] parameter.
Sadly, Vector did not implement such workaround, leaving you the only option to pass your signal strings by testcase parameters (if you are using XML Test nodes).
Since, I presume you have too many, I suggest you write a script in another scripting language constructing the text of the .can file itself, filling the place of dbsignals with the strings from the excel, then use the .can file for testing/simulation.

Scripting Word from vbs

I'm trying to get Word to fill in cells in a table. The script works when run as a macro from within Word, but fails when saved as a .vbs file and double-clicked, or run with wscript. This is a part of it.
set obj = GetObject(,"Word.Application)
With obj
With .Selection
MsgBox .text
If (.Information(wdWithInTable) = True) Then
.Collapse Direction:=wdCollapseStart
tCols = .Tables(1).Columns.Count
tRow = .Information(wdStartOfRangeRowNumber)
tCol = .Information(wdStartOfRangeColumnNumber)
For I = 2 To 5
.Tables(1).Cell(tRow, I).Range.Text = "fred" & Str(I)
Next
` now make new row
For I = 1 To tCols - tCol + 1
.MoveRight unit:=wdCell
Next
End If
End With
End With
I have three problems. First, it won't compile unless I comment out the .Collapse and .MoveRight lines. Second, although the MsgBox .text displays the selected text, I get "out of range" errors if I try to access any .Information property.
I'm sure I'm missing something very simple: I usually write software for Macs, and I'd do this using AppleScript. This is my first attempt at getting anything done under Windows.
VBScript and VBA are different languages.
They are a bit similar, but not very. Moreover, VBScript is not like AppleScript; it doesn't let you easily interface with running programs.
The interfaces you'll get from VBScript can behave subtly differently in VBA and VBScript. However, I think you've got two problems here:
:= is invalid syntax in VBScript; you'll need to find an alternative way of calling the function. Try just using positional arguments.
You've no guarantee that this will open the expected file; there could be another instance of Word that it's interacting with instead.
Since your code is not running within the Word environment it would require a reference to the Word object library in order to use enumeration constants (those things that start with wd).
VBScript, however, cannot work with references, which means the only possibility is to use the long value equivalents of the enumerations. You'll find these in the Word Language References. Simplest to use is probably the Object Browser in Word's VBA Editor. (In Word: Alt+F11 to open the VBA Editor; F2 to start the Object Browser; type in the term in the "Search" box, click on the term, then look in the bottom bar.)
The code in the question uses, for example:
wdWithInTable
wdCollapseStart
wdStartOfRangeRowNumber
wdStartOfRangeColumnNumber
wdCell
The reason you get various kinds of errors depends on where these are used.
Also, VBScript can't used named parameters such as Unit:=. Any parameters must be passed in comma-delimited format, if there's more than one, in the order specified by the method or property. If there are optional parameters you don't want to use these should be left "blank":
MethodName parameter, parameter, , , parameter

Pascal I need to modify the program as the result to be write in text file maxim.out

I have a program which is counting the biggest number from 3 numbers. I need to modify the program as the result to be write in text file maxim.out (PASCAL)
You can write the value (assuming it is an integer and it has the name, say, yourValue) with:
var
maximFile: Text;
...
Assign(maximFile, 'maxim.out'); // link the name to the Text variable
Rewrite(maximFile); // open it for writing
Writeln(maximFile, yourValue); // write the value as a line of its own
Close(maximFile); // close the file
You can then read back the value later on with:
Assign(maximFile, 'maxim.out');
Reset(maximFile);
Readln(maximFile, yourValue);
Close(maximFile);
I did not add any error handling (e.g. if the file can't be found, or if it is readonly, or empty, or ...). Depending on settings, that is either done with exceptions or with IOResult values. Read the documentation on how to do that. There should be examples in the docs.
You should read about "file management in pascal". Anyway, declare a variable of type textfile:
var
outputfile : TextFile;
then assignfile() to it your name of choice (maxim.out), rewrite() the file, use writeln() to write into it, and finally closefile() it.
You can find a complete example program here: http://wiki.freepascal.org/File_Handling_In_Pascal

Lazarus(Pascal) RunError(5)

My program exits with RunError(5), which would suggest that it can't access the file, which it should be able to. I have checked and the file is used as it should be, the file isn't read-only, etc. What the program does is, it creates a .dat file if one doesn't exists and uses it for saving stuff. If I run the program and the file doesn't exist, the file is created, but after that, in the same execution, the program won't access the file. This ONLY happens if the file was created in the current execution.
This is the way in which the procedures are called(the code is quite long but I am giving you the first few lines, where the error occurs):
fileName := 'labSave.dat';
CreateFile;
assign(labyrinthFile,fileName);
writeln(CheckFileSize);
and then there is each of the procedures:
procedure Initialize;
begin
fileName := 'labSave.dat';
assign(labyrinthFile,fileName);
end;
procedure CreateFile;
begin
if not FileExists(fileName) then FileCreate(fileName);
end;
function CheckFileSize: integer;
begin
reset(labyrinthFile);
CheckFileSize := FileSize(labyrinthFile);
close(labyrinthFile);
end;
According to Lazarus forum (http://forum.lazarus.freepascal.org/index.php?topic=4936.0):
Runtime Error 5 means Access denied. The file maybe readonly and you
use the wrong (default) filemode, or you try to re-open the file with
a new filehandle without having closed it before (somewhere in the
while and repeat loops possibly you assignfile more then once, then
the reset fails?).
If I recall correctly now, the workflow should be as follows for create:
AssignFile(f, filename); Rewrite(f); CloseFile(f);
and for existing file:
AssignFile(f, filename); Reset(f); CloseFile(f);
Seeing other mistakes found in your code through questions in comments, I strongly suggest you to devote more time to debugging and when such errors happen - strip out ALL of the irrelevant code and check your code design for cases like above (assigning file before creating it, etc.).

VHDL integer'image Returns "0"

Here is my dilemma:
I'm very new to programming in VHDL, and I'm currently working on an independent study project for a university class. I've made some descent headway, but I've run into an issue I haven't been able to solve.
What I'm trying to do is to display a "register" (or registers) on an LCD monitor and have it update periodically. For the time being, these values will always be integer numbers.
I have code written which displays numbers properly on the screen if that value is passed as a variable that is never altered or as a hard-coded value. However, I want to update a variable by adding to it, then pass that to my function and display it.
Essentially what I'm trying to do is this:
Every 'x' clock ticks, increment a register's value, pass that to my update_screen function which returns a new screen, and then display that further below. However, once I increment or change through reassignment (doesn't seem to matter if it is variable or a signal), all I see is '0' on the screen.
So... The following code properly updates my display unless I uncomment the commented lines. At that point, it just shows '0'.
--currentRegVal := currentRegVal + 1;
--screenVal <= 25;
-- screen holds the values for the current screen
-- The second argument is the row on the screen to be updated
-- The third argument is the value to display there
screen := update_screen(screen, 1, currentRegVal);
screen := update_screen(screen, 0, screenVal + 25);
The problem seems to be stemming from the integer'image attribute (or more accurately, my understanding of it). When I pass in a hardcoded value or a variable that hasn't been altered, it returns what I expect. However, as soon as I modified the variable/signal in ANY way it seems to return the string "0".
Below is my update_screen function:
function update_screen(screen: screenData; reg, regVal: integer) return screenData is
-- A function may declare local variables. These do not retain their values between successive calls,
-- but are re-initialised each time. Array-type parameters may be unconstrained:
constant screenWidth: integer := screen'length(2);
constant strRegVal: string := integer'image(regVal);
constant strRegLen: integer := strRegVal'length;
variable newScreen: screenData := screen;
begin
for dex in 1 to screenWidth loop
if dex <= strRegLen then
newScreen(reg, dex-1) := strRegVal(dex);
else
newScreen(reg, dex-1) := ' ';
end if;
-- The next two ifs were my attempt to figure out what
-- was going on...
--The value itself never seems to be 0... the screen is not all 5's
if regVal = 0 then
newScreen := (others => (others => '5'));
end if;
-- But the string value is "0" if the variable/signal is ever modified...
-- 'd' shows up in the designated row.
if strRegVal = "0" then
newScreen(reg*3, 1) := 'd';
end if;
end loop;
return newScreen;
end update_screen;
A couple important points (added 2011-07-26):
I'm using the Quartus II free (web) edition to design/compile my project.
The code which is updating the variables is in a process.
At the time of the original posting, the only steps I had taken were to compile my code and program an Altera DE2 FPGA board with the result (I wasn't sure how to perform any kind of simulations).
Thanks in advance for any help and advice. Also, as I said, I'm new to VHDL programming, so if there is a much better way to do something I'm doing here, please let me know. I would also greatly appreciate useful links to any resources about the language itself.
Update (2011-07-26):
I downloaded GHDL as Martin Thompson suggested, but I have not actually used it yet because I'm not sure how to go about doing so with my current Quartus II project (or if I even can). I'll have to do some reading before it is useful to me. However, yesterday I managed to install ModelSim-Altera which works directly with Quartus II and allowed me to perform some simulation.
I did my best to set up some waveforms that would allow me to test, and I was at least able to examine the execution of the code which I believed to be failing. However, during simulation, I've verified in multiple ways that the "screen" object does contain the value I want it to contain after the *screen_update* function runs. When running on the Altera DE2, however, it still fails.
Note: I did verify that the screen actually does update by directly setting the value of a particular element on the screen to different values depending on whether or not the currentRegVal is even or odd.
I'll plan on posting some code tomorrow, but for now:
What reasons are there that simulation would provide different results? My guess is something to due with timing, but it is really just a guess. If I am correct, how can I go about trying to resolve the issue?
I guess the problem is related to the fact that you declared strRegVal as a constant. I think it should better be a variable, e.g. something like this might work:
function update_screen(screen: screenData; reg, regVal: integer) return screenData is
...
variable strRegVal: string;
variable strRegLen: integer;
...
begin
strRegVal := integer'image(regVal);
strRegLen := strRegVal'length;
...
end update_screen;
Assuming this code is in a process:
screenVal <= 25;
-... snip...
screen := update_screen(screen, 0, screenVal + 25);
screenVal won't have updated to a new value yet (unless some time passes - a wait statement between the write and the read)

Resources