Why the procedure doesn't see the variable? - variables

I'm using Xilinx ISE to create a VHDL project.
I'm trying to add values to an integer variable.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity vending2_mod is
Port ( button1 : in STD_LOGIC;
button2 : in STD_LOGIC;
button3 : in STD_LOGIC;
button4 : in STD_LOGIC;
coin : in integer;
disp : out string(1 to 16);
prodOut : out integer);
shared variable credits : integer := 0;
procedure addCredits ( c : in integer ) is
begin
credits := credits + c; -- Signal is not defined : 'credits'.
end addCredits;
-- additional code
end vending2_mod;
architecture Behavioral of vending2_mod is
begin
acceptCredit: process (coin)
begin
addCredits(coin);
end process;
end Behavioral;
Yet when I try to Synthesize (XST) the project, I'm getting an error to the line I've written it as a comment. The credits is not a signal, it is a variable; what gives the error?
Saving gives no errors, since the syntax seems to be correct.

Entity-statements must be -passive statements, that is, they must not
assign values to any signals.
Don't use shared variables.
In simulation, variables update immediately upon assignment, as opposed to signals, which are updated only at the end of a simulation cycle. In combinational code, signals immediately take the value of their assignment. In sequential code, signals are used to create flip-flops, which inherently do not immediately take the value of their assignment.
it is better to use signal+clock instead.
Try this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity vending2_mod is
port(
Clock: in std_logic;
Reset: in std_logic;
coin : in integer;
prod_out : out integer
);
end vending2_mod;
architecture Behavioral of vending2_mod is
signal credits : integer := 0;
begin
process(Clock,Reset)
begin
if Reset='1' then
credits <= 0;
elsif(rising_edge(Clock)) then
credits <= credits + coin;
end if;
end process;
prod_out <= credits;
end Behavioral;
See elaborated design:
Don't try this (synthesis OK, note: You need clock):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity vending2_mod is
Port (
coin : in integer;
prod_out : out integer);
end vending2_mod;
architecture Behavioral of vending2_mod is
signal credits : integer := 0;
begin
credits <= credits + coin;
prod_out <= credits;
end Behavioral;
See elaborated design:

Related

Undefined relational operator for two objects of the same type - VHDL

I currently have a project in VHDL to make a simple vending machine. I have a std_logic signal to determine if the cash in is greater than or equal to the price of the item. The cost is an unsigned constant and the cash is an unsigned signal, but despite them both being unsigned numbers of equal bit length, it tells me the >= operator is undefined. I've looked in multiple reference guides, and all I can find is that the two arguments must be the same type (which they are...) so I'm not sure why it's throwing this error
I have included the proper numeric_std library.
type STATE_TYPE is (RDY, CLCT, VND);
signal state : STATE_TYPE;
signal next_state : STATE_TYPE;
signal cash : unsigned (7 downto 0);
signal cashnew : unsigned (7 downto 0);
signal candy : std_logic;
signal candy_vend : std_logic;
constant cost_candy : unsigned := to_unsigned(60, 8);
signal chips : std_logic;
signal chips_vend : std_logic;
constant cost_chips : unsigned := to_unsigned(50, 8);
begin
candy <= candy1 or candy2 or candy3;
chips <= chip1 or chip2;
candy_vend <= candy and (cash >= cost_candy);
chips_vend <= chips and (cash >= cost_chips);
As in other languages, VHDL has a boolean type. It is a integral type and provided in package std.standard. Thus this type is always visible, because this package is referenced by default.
Also like in other languages, a relational operator results in a boolean value. Neither the integral type bit nor the digital logic type std_logic is a boolean. Boolean has values true and false, where as bit has 0 and 1. The std_logic type supports 9 values (9-valued logic, including e.g. error values).
Most operators are defined to accept the right and left operands of the same type, while returning that type again.
So you need to convert your expression at some point back to std_logic, because candy_vend is expecting that type.
Solution 1:
candy_vend <= candy and ('1' when (cash >= cost_candy) else '0');
Solution 2:
candy_vend <= '1' when ((candy = '1') and (cash >= cost_candy)) else '0';
Solution 3:
function to_sl(value : boolean) return std_logic is
begin
if value then
return '1';
else
return '0';
end if;
end function;
Usage:
candy_vend <= candy and to_sl(cash >= cost_candy);
candy_vend <= to_sl((candy = '1') and (cash >= cost_candy));

Crossing clock domain for rarly changing data

I need to connect a configuration module (running at slower clock) to a worker which runs at higher speed. Standard answer seems to be a FIFO but I thought I come up with a simpler solution which consumes less resources - with drawback of having much higher latency. Benefit for me is that I don't need to regenerate FIFO IP for each possible size of data. In RTL simulation it seems to work (I run into troubles using post-synthesis one unrelated to question).
Am I missing something or is the following code correct:
module fifo_int#( // This is bad name. I haven't come up with better yet
parameter type DATA = logic [31:0]
)(
input logic rst,
input logic clk_in,
input DATA din,
input logic clk_out,
output DATA dout
);
DATA dreg;
enum logic [1:0] {
IN,
STABLE,
WAIT_OUT
} in_state;
enum logic [1:0] {
WAIT_IN,
WRITE,
INV
} out_state;
logic in_output[3], out_output[3];
initial begin
in_state <= IN;
out_state <= WAIT_IN;
for (int i = 0; i < 3; i++) begin
in_output[i] <= 0;
out_output[i] <= 0;
end
end
always #(posedge clk_in)
begin
case (in_state)
IN: begin
dreg <= din;
in_state <= STABLE;
end
STABLE: begin
in_state <= WAIT_OUT;
in_output[0] <= ~in_output[0];
end
WAIT_OUT: begin
in_state <= (in_output[0] == out_output[2]) ? IN : WAIT_OUT;
end
endcase
out_output[1] <= out_output[0];
out_output[2] <= out_output[1];
end
always #(posedge clk_out)
begin
case (out_state)
WAIT_IN: begin
out_state <= (in_output[2] == out_output[0]) ? WAIT_IN : WRITE;
end
WRITE: begin
dout <= dreg;
out_state <= INV;
end
INV: begin
out_output[0] <= ~out_output[0];
out_state <= WAIT_IN;
end
endcase
in_output[1] <= in_output[0];
in_output[2] <= in_output[1];
end
endmodule
If your clocks are asynchronous, you're going to need synchronization.
For synchronous clocks, since your slow side is the one producing the data, you don't need any buffering. Data is anyway held stable for multiple (fast) clock cycles, so you don't really need any logic between the domains.

Counter inside FSM in VHDL

I have got a small problem with my finite state machine which I have
written in VHDL recently. I tried to create "intelligent" counter
triggered by clock with frequency 2 Hz.
This counter is built in one state of FSM and is started by pushing a
button on DE2 board.
Firstly, whole system is in IDLE state and if I push this button, state is
changed to COUNTING and counter begin to be incremented and his current
value is shown on LED display. After it reach value of modulo, the state
COUNTING is left back to IDLE and the counter is set up to zero.
My problem is that the counter doesn´t work correctly - the counting
value was too great. So I tried to solve it with this construction: if
(clk_tick´event and clk_tick = 1) then.... , there are some errors by
synthesis:
Error (10822): HDL error at Citac_FSM.vhd(57): couldn't implement
registers for assignments on this clock edge
Error (10821): HDL error at Citac_FSM.vhd(62): can't infer register for
"AUTOMAT:flg" because its behavior does not match any supported register
model
Please, does somebody have an idea to solve it? And what is it correct way
to write clock triggered FSM with two (or more) clock sources?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
ENTITY Counter_FSM IS
GENERIC (
REGSIZE : integer := 8; -- range of counter
MODULO : natural := 50 -- modulo value
);
PORT (
CLK : IN STD_LOGIC; -- puls 50 MHz
CLK_tick : IN STD_LOGIC; -- puls 2 Hz
RESET : IN STD_LOGIC; -- reset
READY : OUT STD_LOGIC; -- counter is ready to start
START_C : IN STD_LOGIC; -- start of counting
DOUT : OUT STD_LOGIC_VECTOR(REGSIZE - 1 downto 0) --out
);
END Counter_FSM;
ARCHITECTURE Behavior OF Counter_FSM is
type counterState is (IDLE, COUNTING); -- states of FSM
signal currCounterState : counterState; -- current state
signal nextCounterState : counterState; -- next state
signal cnt : std_logic_vector(REGSIZE - 1 downto 0); -- counter
begin
UPDATE: process(RESET, CLK)
begin
if (RESET = '0') then
currCounterState <= IDLE;
elsif (CLK'event and CLK = '1') then
currCounterState <= nextCounterState;
end if;
end process;
COMBI: process (clk_tick, start_c, currCounterState)
variable flg : std_logic := '0';
begin
if (clk_tick'event and clk_tick = '1') then
flg := '1';
end if;
case currCounterState is
when IDLE =>
cnt <= (others => '0'); -- counter value = zero
READY <= '1'; -- we can start
if (start_c = '1') then -- if button is pushed
nextCounterState <= COUNTING; -- go to COUNTING
end if;
when COUNTING =>
READY <= '0';
if (flg = '1') then -- Was there impuls of 2 Hz?
cnt <= cnt + 1; -- yes -> incrementing
flg := '0';
if (cnt = MODULO) then -- if cnt = MODULO
cnt <= (others => '0'); -- then cnt = zero
nextCounterState <= IDLE;
end if;
end if;
when others =>
nextCounterState <= IDLE;
end case;
-- OUTPUT
douT <= cnt;
end process;
end Behavior;
Thank you very much.
Mirek
P.S.: I am sorry my English is not so good.
First of all you should not use clk_tick as a second clock signal.
What you should do is to save the previous value of clk_tick, then compare the current value of clk_tick to the previous value to detect a rinsing edge. Depending on how clk_tick is generated you might need to synchronize clk_tick to the clock domain of CLK.
You could write something like this:
when COUNTING =>
nextCounterState <= COUNTING;
READY <= '0';
if (prev_clk_tick = '0' and clk_tick = '1') then
next_cnt <= cnt + 1; -- yes -> incrementing
if (cnt = MODULO) then
next_cnt <= (others => '0');
nextCounterState <= IDLE;
end if;
end if;
I will leave it to you to add the extra registers.
I have already solved my problem :-). I have moved the counter into separate process and then attached witch signals to FSM. So, it works very well.
By reading of button I am using two D flip-flops to synchronize it at the moment.
I have to make an observation on style of VHDL programming - it is too different to "normal" programming like C language :-D
Nice day!

Variable structure for database results

A lot of times when we query the database, we just need one column with varchar.
So I've made a nice function for querying the database and putting the results in a stringlist:
function Getdatatostringlist(sqlcomponent, sqlquery: string): TStringlist;
What I'm looking for now is basically the same function but for results with multiple columns where you don't know in advance what type the data is, be it varchar, int, datetime.
What kind of datastructure would be good to use here.
The reason I want this is that I try not to work on open datasets. I like much more to fetch all results into a temporary structure, close the dataset and work on the results.
After Kobiks reply about using in Memory datasets I came up with the following, it's fast put together to test the concept:
procedure TForm1.Button2Click(Sender: TObject);
var
MyDataSet : TAdoDataSet;
begin
MyDataSet := GetDataToDataSet('SELECT naam FROM user WHERE userid = 1', ADOConnection1);
try
Form1.Caption := MyDataSet.FieldByName('naam').AsString;
finally
MyDataSet.free;
end;
end;
function TForm1.GetDataToDataSet(sSql: string; AdoConnection: TADOConnection): TAdoDataSet;
begin
Result := TAdoDataSet.Create(nil);
Result.LockType := ltBatchOptimistic;
Result.Connection := AdoConnection;
Result.CommandText := sSql;
Result.Open;
Result.Connection := nil;
end;
I think this is something to build on.
You should use any disconnected in-memory TDataSet descendant, such as TClientDataSet.
Do not attempt to re-invent the wheel by storing a record-set in some new "Variant" structure. A TClientDataSet already contains all features you need to manipulate a "temporary" data structure.
Here is how you create a TClientDataSet structure:
cds.FieldDefs.Add('id', ftInteger);
cds.FieldDefs.Add('name', ftString, 100);
// ...
// create it
cds.CreateDataSet;
// add some data records
cds.AppendRecord([1, 'Foo']);
cds.AppendRecord([2, 'Bar']);
Many TDataSets has an ability to be used as an in-memory (client) datasets depending on the provider and LockType, for example a TADODataSet with LockType=ltBatchOptimistic could fetch results-set from the server, and then remain disconnected.
For exchanging Data with Excel this structure is usefull, might be useful for other purposes.
Function GetDatasetasDynArray(Ads: TDataset; WithHeader: Boolean = true): Variant;
// 20130118 by Thomas Wassermann
var
i, x, y: Integer;
Fields: Array of Integer;
begin
x := 0;
y := Ads.RecordCount;
if WithHeader then
inc(y);
SetLength(Fields, Ads.FieldCount);
for i := 0 to Ads.FieldCount - 1 do
if Ads.Fields[i].Visible then
begin
Fields[x] := i;
inc(x);
end;
SetLength(Fields, x);
Result := VarArrayCreate([0, y - 1 , 0, length(Fields) - 1], VarVariant);
y := 0;
if WithHeader then
begin
for i := Low(Fields) to High(Fields) do
begin
Result[y, i] := Ads.Fields[Fields[i]].DisplayLabel;
end;
inc(y);
end;
try
Ads.DisableControls;
Ads.First;
while not Ads.EOF do
begin
for i := Low(Fields) to High(Fields) do
begin
Result[y, i] := Ads.Fields[Fields[i]].Value;
end;
Ads.Next;
inc(y);
end;
finally
Ads.EnableControls;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
DynArray:Variant;
begin
DynArray := GetDatasetasDynArray(Adodataset1,true);
//DynArray[0,x] Header or First row
//DynArray[1,x] First row or SecondRow
Excel.Range.Value := DynArray;
end;
Why don't you like working with open datasets? They usually do not block the server. Copying the data from the dataset to whatever you want is extra overhead which is most likely not necessary.
A dataset provides exactly the functionality you want: A matrix with variable columns and rows.
EDIT: However, if you have iterate through the dataset often, you should consider creating a class holding the relevant information and then copy the data into a generic list, dictionary, tree or whatever you need as fast lookup structure.
Of course you could think of building something smart which can be as flexible as a dataset but: The more general things get, the poorer the performance (usually).

Signals and Variables in VHDL

I want to ask about the signals and variables in VHDL, I know the difference between them, but I want to see the difference at simulation.
I used this simple program in Quartus Tool to see the difference between them:
ENTITY test IS PORT (
a : IN bit;
y : OUT bit);
END test;
ARCHITECTURE beh OF test IS
SIGNAL x : BIT;
BEGIN
PROCESS (a)
BEGIN
x <= '1';
IF x = '1' THEN y <= '0' AFTER 8 ns;
ELSE y <= '1' AFTER 5 ns;
END IF;
END PROCESS;
END BEH;
for signals and this for variables:
entity test1 is port (
a : IN bit;
y : OUT bit);
end test1;
architecture beh of test1 is
begin
process (a)
variable x : bit;
begin
x := '1';
if x = '1' then y <= '0' after 8 ns;
else y <= '1' after 5 ns;
end if;
end process;
end beh;
the i created waveform to see the difference in the first program (y)value should be set to 1 at 5ns,but it doesn't change..Why?
Thank you in advance.
You don't see the difference in waveforms, as the waveform viewer only shows the values of variables at the end of a delta cycle (ie when some real time passes). If you single-step the code, or add report statements mid process, you can see intermediate values on a variable:
signal s:integer := 0;
process
variable v:integer := 0;
begin
report "Signal="&integer'image(s)&" variable="&integer'image(v);
s <= 1; v := 1;
report "Signal="&integer'image(s)&" variable="&integer'image(v);
wait for 0 ps; -- end the delta cycle, even 0ps counts as "time passing"
report "Signal="&integer'image(s)&" variable="&integer'image(v);
wait;
end process;
You put signal "a" on sensitive list then it lead to a "latch".
For update y, you should put "x" on sensitive list or change "a" like a trigger signal.
In your case, signal and variable is similar because you fixed it as a constant.
For addition, you should upload your testbench with behaviour of signal "a".
Edit: I'm wrong about put "x" in sensitive list. Thanks to #damage
This piece of code should illustrate the difference b/w signals and variables.
I inserted the processes directly into the testbench, so the code can be directly simulated with a HDL simulator of your choice.
After 10 ns the start event is fired and both processes are evaluated.
You should then see the expected result, namely sig_outgoing high after another 20 ns, whereas var_out should be high after only 10 ns.
library ieee;
use ieee.std_logic_1164.all;
entity sigvartest is
end entity sigvartest;
architecture behav of sigvartest is
signal start : std_logic := '0'; -- event to start simulation
signal x_sig : std_logic := '0'; -- signal tested in SIGPROCESS
signal sig_out : std_logic := '0'; -- output of SIGPROCESS
signal var_out : std_logic := '0'; -- output of VARPROCESS
begin
start <= '0', '1' after 10 ns; -- pretty self-explanatory, start goes high after 10 ns
SIGPROCESS:
process(start) is
begin
if(rising_edge(start)) then
x_sig <= '1'; -- signal is scheduled to be assigned its new value, no immediate change!
if(x_sig = '1') then
sig_out <= '1' after 10 ns;
else
sig_out <= '1' after 20 ns; -- this part will execute
end if;
end if;
end process;
VARPROCESS:
process(start) is
variable x_var : std_logic := '0';
begin
if(rising_edge(start)) then
x_var := '1'; -- variable is assigned immediately
if(x_var = '1') then
var_out <= '1' after 10 ns; -- this part will execute
else
var_out <= '1' after 20 ns;
end if;
end if;
end process;
end architecture;