Set a variable if it's unitialized - vhdl

I'm writing a small VHDL process block and I wanted to assign a value to a variable if it hasn't been set yet. The input has no value at first, so I was wondering if there was something that could set new_ace to '0' if ace is still uninitialized or unknown.
entity rules is
port(
ace : in std_logic := '0'; --Tried setting 0 as default
ace_out : out std_logic
);
end rules;
architecture behavior of gA6_rules is
begin
cards: process(ace)
variable new_ace : std_logic := '0'; --Tried setting 0 as default
begin
if ace = 'U' or ace = 'X' then --Tried checking for unitialized
new_ace := '0';
else
new_ace := ace;
end if;
ace_out <= new_ace; --Next input will be this output
end process;
end behavior;
The problem is that when I simulate my design, it shows that ace_out is still undefined, even if I try setting it with := '0' or if I use the if statement.

Related

VHDL - Register for Push Button

I'm trying to create a simple push button in VHDL that turns on after an input switch or pb goes from 0 to 1 to 0 using a clock and a process. However, my code seems to be giving me undefined output. Here's what I have so far.
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Entity captureInput is port
(
CLK : in std_logic := '0';
RESET_n : in std_logic := '0';
buttonState : in std_logic := '0';
buttonOut : out std_logic := '0'
);
end Entity;
ARCHITECTURE one of captureInput is
signal lastButtonState: std_logic := '0';
signal btnState : std_logic := '0';
BEGIN
process (CLK, RESET_n) is
begin
if (RESET_n = '0') then
lastButtonState <= '0';
elsif (rising_edge(CLK)) then
if (buttonState ='0' and lastButtonState = '1') then
btnState <= '1';
end if;
lastButtonState <= buttonState;
end if;
end process;
buttonOut <= btnState
end;
Try to initialize your btnState in the reset branch of your register and also have an else statement where you set your btnState back to 0, under some condition. I would bet that your undefined output comes from the fact that you do not define your btnState anywhere else outside your if conditions. It's good practice to not rely on the initial value of your declaration: Synthesis tools ignore it and some simulators will as well. Also, remember that the clocked body of the if will generate a register for every signal that gets assigned a value inside it, and that signals will keep the last value assigned to them inside a process.
You are also missing the Library ieee; statement at the top and a semicolon after buttonOut <= btnState.
Reading a button do need a debouncer.
Please take a look at:
VHDLWhiz generate statement
or
VHDLWhiz How to read a button in VHDL
Even though I see that you have already accepted Dimitris' answer, I can add that your code is almost right, you just need to toggle on the falling edge of of the latch instead of setting it to '1' as you do.
Try
if(rising_edge(CLK)) then
lastButtonState <= buttonState;
if(buttonState='0' and lastButtonState='1') then
btnState <= not btnState;
end if;
end if;
buttonOut <= btnState -- etc...
You don't need to initialize anything to '0' but you DEFINITELY need a switch debouncer as lukipedio said otherwise your toggle will not be consistent.
If you think about it, what you're doing is putting a "clock divider" on your lastButtonState register by toggling in order to set the btnState register at half the "frequency" of lastButtonState, which is what you want.
BTW, if you switch your toggling condition to
(buttonState='1' and lastButtonState='0')
then it will toggle on the rising edge of lastButtonState, in other words it will be toggle-on-press instead of toggle-on-release.

Error: VHDL compiler exiting

I am using modelsim. I wrote simple code but i am getting error.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity clk_counter is
port(output : out bit;
clk : in bit
);
end clk_counter;
architecture rtl of clk_counter_arch is
signal clock_counter_output_flag: bit;
constant clock_max_count : integer := 20000;
begin
process (clock_counter_output_flag, clk,CLK'event )
variable clock_count : integer := 0;
--constant clock_max_count : integer := 20000;
variable clock_out : bit := 0;
-- wait until CLK'event and CLK='1';
begin
if (CLK'event and CLK='1') then
clock_count := clock_count+1;
if (clock_count = clock_max_count) then
clock_out := 1;
else
clock_out := 0;
end if
end if
clock_counter_output_flag <= clock_out;
end process;
END Architecture;
Error messege:
# ** Error: (vcom-11) Could not find work.clk_counter_arch.
#
# ** Error: C:/Modeltech_pe_edu_10.4a/examples/work/src/clk_counter(13): VHDL Compiler exiting
Your entity name is clk_counter and you have defined architecture rtl of clk_counter_arch. Hence, you are getting error. Change clk_counter_arch to clk_counter.
Second, you should end architecture as end rtl.
Also, why are you using two additional variables clock_out and clock_counter_output_flag ? If you want that values as output of your code, you should simply write
if (CLK'event and CLK='1') then
clock_count := clock_count+1;
if (clock_count = clock_max_count) then
output<='1';
else
output <='0';
end if;
end if;

VHDL syntax issue

I'm getting an error during CheckSyntax for the following code I've tried. The error says:
"Line 48. parse error, unexpected VARIABLE Line 53. Undefined symbol 'InOutDetector'.
Line 57. InOutDetector: Undefined symbol (last report in this block)".
Can you let me know how should I fix this?
Here is an image of my code, as I could not paste it.
https://www.dropbox.com/s/ay8pjq4ojoep6ry/RoomLightController.png?dl=0
entity Room_Light_Controller is
port (
clk, sA, sB: IN STD_LOGIC;
sL: OUT STD_LOGIC
);
end Room_Light_Controller;
architecture Behavioral of Room_Light_Controller is
-- assuming sensors are variables sA and sB, and lights switch is sL
SIGNAL People : INTEGER:=0;
SIGNAL AllowNextCount : BIT:='0';
--unsigned int People=0; -- counter for people inside the room
--char AllowNextCount=0; -- boolean indicating if allowing next count or not
--short int InOutDetector; -- 1 = entering; -1 = exiting
begin
variable InOutDetectorDetector: integer;
process (clk)
begin
if ((sA = '0') and (sB = '1')) then
-- entering
InOutDetector := 1;
end if;
if ((sA = '1') and (sb = '0')) then
-- exiting
InOutDetector := -1;
end if;
if ((sA ='1') and (sB = '1') and (AllowNextCount = '1')) then
-- only when both sensors are touched validate the people counter
People := People+InOutDetector;
-- count once then block counting until the same person has finished entering/exiting
AllowNextCount <= '0';
end if;
if ((sA = '0') and (sB = '0')) then
-- it gets 0;0 only when someone has finished entering/exiting
-- pr at turn on; so now allow to counting again
AllowNextCount <= '1';
end if;
if (People > 0) then
sL <= '1'; -- Turn/keep lights on as long as People greater than 0
else
sL <= '0'; -- otherwise, turn them off
end if;
end process;
end Behavioral;
In addition to the error Amir notes that there is a name mismatch and the variable is declared in the wrong place, there is an additional error with the assignment to People:
library ieee;
use ieee.std_logic_1164.all;
entity Room_Light_Controller is
port (
clk, sA, sB: in std_logic;
sL: out std_logic
);
end entity Room_Light_Controller;
architecture Behavioral of Room_Light_Controller is
-- assuming sensors are variables sA and sB, and lights switch is sL
signal people: integer := 0;
signal allownextcount: bit := '0';
--unsigned int People=0; -- counter for people inside the room
--char AllowNextCount=0; -- boolean indicating if allowing next count or not
--short int InOutDetector; -- 1 = entering; -1 = exiting
begin
-- variable InOutDetectorDetector: integer;
process (clk)
variable InOutDetector: integer; -- as per Amir
begin
if sA = '0' and sB = '1' then
-- entering
InOutDetector := 1;
end if;
if sA = '1' and sb = '0' then
-- exiting
InOutDetector := -1;
end if;
if sA ='1' and sB = '1' and AllowNextCount = '1' then
-- only when both sensors are touched validate the people counter
People <= People + InOutDetector; -- was :=, signal assignment
-- count once then block counting until the same person has finished entering/exiting
AllowNextCount <= '0';
end if;
if sA = '0' and sB = '0' then
-- it gets 0;0 only when someone has finished entering/exiting
-- pr at turn on; so now allow to counting again
AllowNextCount <= '1';
end if;
if People > 0 then
sL <= '1'; -- Turn/keep lights on as long as People greater than 0
else
sL <= '0'; -- otherwise, turn them off
end if;
end process;
end architecture Behavioral;
People is a signal and requires the signal assignment symbol (<=) not the variable assignment symbol (:=).
After the two changes the VHDL design specification analyzes and elaborates.
Notice a context clause has been added to make your code a Minimal, Verifiable and Complete example.
Also note in the Help Center web page on Minimal, Complete, and Verifiable example the section Minimal and readable,
..Use consistent naming and indentation, and include comments if needed to explain portions of the code.
If this code were intended to be synthesize you might likely need to constrain the integers.
For execution efficiency all the independent if statements could be consolidated using elsif. That's hardly an issue in a small design, but the binary patterns described for sA and sB are mutually exclusive (while not exhaustive for type std_logic).
You neglected to provide the complete error messages, which appear to be output from XST. Historically the recommended design flow includes simulation, which if for no other purpose provides better syntax error messages from VHDL analysis.
XST historically assumes you are handing it a design description that is syntax error free, and is other wise quite sparse in providing adequate error messages.
The error message prefix (e.g. ERROR:HDLParsers:1209) can tell you how to find the problem via Xilinx's support site and/or documentation.
Declare the variable inside the process and rename it to (InOutDetector). You used (InOutDetector) inside the process.
Then if you want to run the process on clk rising edge, complete your process such as the following code :
process(clk)
variable InOutDetector : integer;
begin
if clk = '1' and clk'event then
-- your code
end if;
end process;
However if you don't want to use the clk rising edge, just complete the sensitivity list with parameters that you read or check it inside the process (sA,sB,AllowNextCount,People) and remove clk from the process sensitivity list.
Also be careful about incomplete if statements. Latches may be generated from incomplete case or if statements.

Record fields assigned from different processes

There is something strange going on when I assign different members of a record from different processes. What is the reason for this?
type t_collection is record
A : std_logic;
B : std_logic;
end record;
signal collection : t_collection ;
begin
collection.A <= '1';
process(Clk) is
begin
if rising_edge(Clk) then
collection.B <= '1';
end if;
end process;
In the simulator, collection.A resolves to 'X', and collection.B to '1'.
I agree with #fru1bat, unless there is more code in the assignment to "collection.B", it looks like you may have a bug in your simulator.
For Testbench applications, you can give the signal an initial value of all 'Z':
signal collection : t_collection := (A => 'Z', B => 'Z') ;
For RTL, I doubt the synthesis tools will like this.

xilinx VHDL error 827 : Signal <name> cannot be synthesized

I am beginner in VHDL programming and I am trying to synthesize the following vhdl code (software denouncing for a push button) using ISE project navigator 13.1
entity PBdebouncer is
Port ( PB : in STD_LOGIC;
CLK : in STD_LOGIC;
reset : in STD_LOGIC;
PBdebounced : out STD_LOGIC);
end PBdebouncer;
architecture Behavioral of PBdebouncer is
begin
p1: process(CLK , PB , reset)
variable enable,count : integer range 0 to 100000 := 0;
begin
if(reset = '1') then
count := 0;
enable :=0;
elsif(CLK' event and CLK = '1' ) then
if (enable = 1) then
count := count + 1;
end if;
if(count = 99999 ) then
if(PB = '0') then
PBdebounced <= '0';
else
PBdebounced <= '0';
end if;
count := 0;
enable := 0;
end if;
count := count;
else
enable := 1;
end if;
end process;
end Behavioral;
but unfortunately I am bumped with the following error:
ERROR:Xst:827 - ".../digital lab II 110/PBdebouncer/PBdebouncer.vhd" line 43: Signal enable cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
So could you please explain this error for me ?
Try it without the space between Clk' and event...
A few other questions :
why does "enable" have a range of 0 to 100000 when you only use two of those values? why not just use a boolean or std_logic?
is "pbdebounced" ever supposed to be set to anything other than '0'?
why the parentheses around the boolean expressions?
why is PB in the sensitivity list?
did it work as expected in simulation?
these will probably do for now...
EDIT : the bad formatting hid the problem:
begin
if reset = '1' then
count := 0;
enable :=0;
elsif rising_edge(clk) then
if enable = 1 then
count := count + 1;
end if;
if count = 99999 then
-- do stuff
end if;
count:= count;
-- else
-- enable := 1;
-- THE TWO LINES ABOVE are the problem
-- They are outside both the CLK and RESET clauses.
end if;
end process;
Just a small advice: Avoid variables as beginner.
They seem to work like in a software program, but they map sometimes to nasty things in hardware.
The cause of the problem seems to have been identified by Brians answer - but I'll just add a tip for these cases:
In Xilinx ISE you can view a number of language templates (select Edit -> Language templates), which can help you when implementing various styles of flip-flops (synchronous / asynchronous resets, rising / falling edge triggered and so on) and other constructs.
These can be really helpful - especially when getting error-messages like this, which are typically due to syntactically correct VHDL code that describes hardware that can't be synthesized in the selected device.

Resources