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)
Related
I want a text file to show contents in memo1 once I have selected 2 checkboxes.
How would I do this?
I tried the code below but I can't seem to get it right.
if CheckBox1.Checked and CheckBox2.Checked then
begin
memo1.lines.LoadFromFile('files\RS.txt');
end;
I also want to be able to select the checkboxes individually Like:
(pointing this out in case combining them prevents checking them individually)
Checkbox1:
procedure TForm1.CheckBox1Change(Sender: TObject);
begin
memo1.lines.LoadFromFile('files\R.txt');
end;
Checkbox2:
procedure TForm1.CheckBox2Change(Sender: TObject);
begin
memo1.lines.LoadFromFile('files\S.txt');
end;
Any suggestions/Improvements will be appreciated.
Running Lazarus IDE v1.6.4
Windows 10 x64
I'm assuming your objective is to generate a filename which depends on the
particular combination of the boolean states of the two checkboxes -
see example code below. The point of doing this is that it helps separate
the definition of what you want the file name to be from what you want to do
with it.
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.LoadFromFile(GetFileName);
end;
function TForm1.GetFileName: String;
begin
// Return empty string if neither checkbox is checked
Result := '';
if Checkbox1.Checked and Checkbox2.Checked then
Result := 'files\RS.txt'
else // if we reach here only one of the checkboxes, or neither, is checked
if Checkbox1.Checked then
Result := 'files\R.txt'
else
if Checkbox2.Checked then
Result := 'files\S.txt'
end;
I've assigned an empty string to the Result of the function at the outset to ensure that the Result is always defined.
Important You'll notice that the above does not use the Change events of the Checkboxes. The reason is that you may not get the result you need (or are expecting) if the Change events are never triggered - for example if one CheckBox is set to Checked in the IDE but the other isn't, and you want to get the right file name regardless of whether the user has actually clicked either one of them.
As far as I understood you want the following behaviour:
There are two check boxes
There is one memo field
Depending on the state of the two check boxes the text in the memo field shall change
If this understanding is correct:
I typically don't use Pascal but your problem seems to be independent of the programming language used. I would do it like this:
The two procedures TForm1.CheckBox1Change and TForm1.CheckBox2Change are called whenever the corresponding check box'es state changes.
I would write a third procedure and call this third procedure from both procedures. I would do nothing else than calling this third procedure in the other two procedures.
In the third procedure I would evaluate what to do - depending on the state of both check boxes.
A separate checkboxchange proocedure per event is automatically generated by the designer if you double click the event. However that is not a rigid decision.
If you have the initial codefragment in e.g. checkbox1change, you can simply point the onchange of checkbox2 to that existing checkbox1change by using the dropdown of the onchange of checkbox2
I was trying to make a little test program to count how many times letter 'a' appears in an text without using string type:
program PascalTest;
uses WinCrt;
var
a:integer;
ch:char;
begin
a:=0;
writeln('Input text: ');
read(ch);
while ch <>'.' do // '.' marking the end of text ("eoln" could've been used instead)//
begin
case ch of
'A','a':a:=a+1;
end;
read(ch);
end;
writeln(a);
readln;
readln; //forcing output window to stay open//
end.
I noticed that if I dont add another 'readln' statement at the end , the output window will not show results (it will flash in an instant if u will).This is happening only with this program.All the other ones require only one 'readln' so the window can stay open. Can somebody explain to me why is another 'readln' statement needed in this case?
The first readln ends the while loop. Note that you can enter many '.' without loop exit. Further note the writeln(a) is delayed until you press <Enter>. The second readln allows you to view the output.
Make a test: Uncomment both readln and see if you can end the program by entering a '.'.
WinCrt is a consoleless CRT to use in combination with unit GRAPH.
Use unit Crt for normal console output.
This is something that has puzzled me for some time and I have yet to find an answer.
I am in a situation where I am applying a standardized data cleaning process to (supposedly) similarly structured files, one file for each year. I have a statement such as the following:
replace field="Plant" if field=="Plant & Machinery"
Which was a result of the original code-writing based on the data file for year 1. Then I generalize the code to loop through the years of data. The problem becomes if in year 3, the analogous value in that variable was coded as "Plant and MachInery ", such that the code line above would not make the intended change due to the difference in the text string, but not result in an error alerting the change was not made.
What I am after is some sort of confirmation that >0 observations actually satisfied the condition each instance the code is executed in the loop, otherwise return an error. Any combination of trimming, removing spaces, and standardizing the text case are not workaround options. At the same time, I don't want to add a count if and then assert statement before every conditional replace as that becomes quite bulky.
Aside from going to the raw files to ensure the variable values are standardized, is there any way to do this validation "on the fly" as I have tried to describe? Maybe just write a custom program that combines a count if, assert and replace?
The idea has surfaced occasionally that replace should return the number of observations changed, but there are good reasons why not, notably that it is not a r-class or e-class command any way and it's quite important not to change the way it works because that could break innumerable programs and do-files.
So, I think the essence of any answer is that you have to set up your own monitoring process counting how many values have (or would be) changed.
One pattern is -- when working on a current variable:
gen was = .
foreach ... {
...
replace was = current
replace current = ...
qui count if was != current
<use the result>
}
I got some example code on generating random number in one data step or in different data steps. The seed increase 1 each time calling the ranuni function. Does any one know the performance of such kind of random numbers?
Example code:
%let seed = 12345;
data a;
do i = 1 to 100;
randnum = ranuni(&seed);
output;
end;
do i = 101 to 200;
randnum = ranuni(&seed+1);
output;
end;
run;
Documentation about providing seeds to the random number functions can be found here:
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/a001281561.htm
There's two additional issues:
1) Why would you ever want to do this? I doubt you really need to.
2) Even if we suppose that you have a legitimate and reasoned application for such a use, what you're doing right now won't work.
Or rather, that is to say, the program will run and it will output as expected, but the ranuni function does not output numbers the way you think it does, with a continually updating seed.
If you really need to do this, you need to use something like the call ranuni or call rannor routines. See the documentation that I linked to.
Your program as it exists currently will output random numbers from a stream initiated by the first call to ranuni, which in this case I believe, would be with a seed set to 12345. Again, see the documentation I linked to. It explains what it is ranuni actually does, and it also goes on to show why you probably don't want to do what it is that you're trying to do.
(edit: you can also investigate the newer RAND function).
Edit2: and if you really want to do it like you have now, you could maybe try:
%let seed = 12345;
data a;
do i = 1 to 100;
call ranuni(&seed, randnum);
output;
end;
do i = 101 to 200;
call ranuni(&seed + 1, randnum);
output;
end;
run;
I have a project that I'm going to rewrite to another language, and in order to do that - I'd like to build it. But when I try to build it, I receive "E1012: Constant expression violates subrange bounds".
I have such code:
var ForTolkResult : array[0..2000] of char;
ForTolkResult[sizeof(ForTolkResult)-1] := chr(0); // Occurs here
From my point of view everything is correct here, sizeof(ForTolkResult) = 2000 * 1, so sizeof(ForTolkResult) - 1 = 1999, that is in bounds of an array. (But I'm new to Pascal) So what's wrong here?
I'm trying to build it via Embarcadero C++ Builder. If this error is a bug in compiler, how can I turn this check off?
Does char really ocuppy one byte of memory? I mean, check whether it is an "Ansi" single-byte char and not a WideChar.
Anyway, when you need to access the last index of an array, you'd better use
ForTolkResult[High(ForTolkResult)] := chr(0);