Author Topic: Comparing a variable to a value in VHDL?  (Read 2302 times)

0 Members and 1 Guest are viewing this topic.

Offline betocoolTopic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: au
Comparing a variable to a value in VHDL?
« on: December 14, 2022, 01:39:30 am »
Hello all,

I'm using Quartus 20.1 (command line mostly) to synthesize, fit, assemble, etc, a project. I decided to start using the "variable" keyword to keep some values within a process:

Quote
ssome_process : process(clk_in)

    variable usec_delay : unsigned(24 downto 0) := (others => '0');
    variable pulse_cnt  : unsigned(11 downto 0) := (others => '0');

begin

So far so good. Now I'm trying to compare the "pulse_cnt" variable to a fix value:

Quote

if (usec_pulse = 1) then
  pulse_cnt := pulse_cnt + 1;
  if(pulse_cnt = d"2199") then
    pulse_cnt := (others => '0');
  end if;
end if;

But I'm getting this error when trying to synthesize:
Code: [Select]
Error (10327): VHDL error at some_hw.vhd(169): can't determine definition of operator ""="" -- found 0 possible definitions File: some_hw.vhd Line: 169

I tried to find the correct way of doing it (other to change the variable to a signal at the beginning of the architecture) but I'm clueless.

What am I missing here?

Appreciate the help.

Cheers,

Alberto
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15024
  • Country: fr
Re: Comparing a variable to a value in VHDL?
« Reply #1 on: December 14, 2022, 02:03:45 am »
The 'd' prefix with bit strings is part of VHDL-2008, so first make sure you have a tool that supports VHDL-2008 or above.

I'm not sure you can use decimal bit strings properly without specifying the bit width, which is also part of VHDL-2008.

Try:
Code: [Select]
if pulse_cnt = 12d"2199" then
instead.
Note that parentheses are not needed in if-then clauses in VHDL. People adding parentheses is usually a sign of them having used too much C and/or Verilog. VHDL is based on Ada.

If the above fails, possibly your tool doesn't fully support VHDL-2008. In which case, use the following instead:
Code: [Select]
if pulse_cnt = to_unsigned(2199, pulse_cnt'length) then
 

Offline betocoolTopic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: au
Re: Comparing a variable to a value in VHDL?
« Reply #2 on: December 14, 2022, 02:05:18 am »
I'm such a numpty... apologies to all  :palm:

It was the statement above that was failing... Once I learn to read, all will be well.

Code: [Select]
if (usec_pulse = 1) then

Was missing the inverted commas...

Everything works as expected.

Cheers,

Alberto
 

Offline Daixiwen

  • Frequent Contributor
  • **
  • Posts: 364
  • Country: no
Re: Comparing a variable to a value in VHDL?
« Reply #3 on: December 14, 2022, 11:15:47 am »
The numeric_std library defines the = operator for any combination of unsigned and natural, so you can in fact just write
Code: [Select]
if pulse_cnt = 2199 thenand it should work without having to worry to write the value as a vector of the right size.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9915
  • Country: us
Re: Comparing a variable to a value in VHDL?
« Reply #4 on: December 14, 2022, 04:39:39 pm »
Would it work, and possibly be easier on hardware, to preload 2199 and count down toward 0?
 

Offline betocoolTopic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: au
Re: Comparing a variable to a value in VHDL?
« Reply #5 on: December 14, 2022, 11:31:14 pm »
Thanks to all,

now that I fixed the statement that was actually wrong, all other suggestions work fine.

Cheers,

Alberto
 

Offline betocoolTopic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: au
Re: Comparing a variable to a value in VHDL?
« Reply #6 on: December 15, 2022, 08:29:23 am »
Slightly off topic here, but a little help would be very welcome...

I was working with variables, e.g.:

Code: [Select]
variable pulse_delay : unsigned(23 downto 0) := (others => '0');

Then I started running a simulation with Modelsim. However, I noticed a particular condition was not being activated when it happened, e.g:

Code: [Select]

pulse_cnt := pulse_cnt + 1;
               
if pulse_cnt = 2199 then
  pulse_cnt := (others => '0');
end if;


Basically it was counting upwards from 2200. I then remembered from somewhere in the depths of my head that some programs were very succeptible to having all the correct variables in the process sensitivity list:

Code: [Select]
process pulse_counter : process(clk_in, rising_edge, reset, usec_pulse)

variable pulse_delay : unsigned(23 downto 0) := (others => '0');

But I did not have "pulse_delay" in the sensitivity list, as it was defined in the process.

Later I changed "pulse_delay" to signal, outside the process, included it in the list, and suddenly it works as expected...

How sensitive (pardon the pun) are compilers to signals in the sensitivity list? I'd heard that was a thing of the past kind of...

Cheers,

Alberto
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9915
  • Country: us
Re: Comparing a variable to a value in VHDL?
« Reply #7 on: December 15, 2022, 03:58:03 pm »
How sensitive (pardon the pun) are compilers to signals in the sensitivity list? I'd heard that was a thing of the past kind of...

For simulation, the sensitivity list tells the simulator which signals to watch in terms of kicking off evaluation.

For synthesis, as I understand it, the sensitivity list is meaningless.

In VHDL, the following is legal and no actual signal names are included in the list:

Code: [Select]
process (all)
https://insights.sigasi.com/tech/wildcard_sensitivity/

Even so, some compilers whine and snivel about missing signals in the sensitivity list.  I suppose that is to help out the simulator.

 

Offline jziegler

  • Newbie
  • Posts: 9
  • Country: us
Re: Comparing a variable to a value in VHDL?
« Reply #8 on: December 15, 2022, 05:59:25 pm »
Note that process(all) is only valid in VHDL 2008, not in previous versions.

 
Slightly off topic here, but a little help would be very welcome...

I was working with variables, e.g.:

Code: [Select]
variable pulse_delay : unsigned(23 downto 0) := (others => '0');

Then I started running a simulation with Modelsim. However, I noticed a particular condition was not being activated when it happened, e.g:

Code: [Select]

pulse_cnt := pulse_cnt + 1;
               
if pulse_cnt = 2199 then
  pulse_cnt := (others => '0');
end if;


Basically it was counting upwards from 2200. I then remembered from somewhere in the depths of my head that some programs were very succeptible to having all the correct variables in the process sensitivity list:

Code: [Select]
process pulse_counter : process(clk_in, rising_edge, reset, usec_pulse)

variable pulse_delay : unsigned(23 downto 0) := (others => '0');

But I did not have "pulse_delay" in the sensitivity list, as it was defined in the process.

Later I changed "pulse_delay" to signal, outside the process, included it in the list, and suddenly it works as expected...

How sensitive (pardon the pun) are compilers to signals in the sensitivity list? I'd heard that was a thing of the past kind of...

Cheers,

Alberto

I suspect that the difference you are seeing is due to the timing differences in assigning variables and signals in VHDL.   Remember that variables change immediately while signals change based on a delta cycle.  There may be a difference caused by that.

The numeric_std library defines the = operator for any combination of unsigned and natural, so you can in fact just write
Code: [Select]
if pulse_cnt = 2199 thenand it should work without having to worry to write the value as a vector of the right size.

Be careful with the numeric_std, it is not a library defined as part of the IEEE standards, so it may not function the same way on all simulators and synthesis tools.  I also advise against these comparisons since it makes it easier to get a mismatch in types.  While using the standard conversions going through signed and unsigned is extra work, it also ensures that you don't accidentally compare values of different types.

And back to the OP, why not just use an integer for the variable/signal in the first place?  Us an integer with the same range (range 0 to 2 ** 12 - 1) so that it does not implement as a 32-bit signed value.  The only potential downside to this is that you need to deal with value wrapping differently, but when counting up that can be done with the mod operator.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15024
  • Country: fr
Re: Comparing a variable to a value in VHDL?
« Reply #9 on: December 15, 2022, 07:26:46 pm »
Slightly off topic here, but a little help would be very welcome...

I was working with variables, e.g.:

Code: [Select]
variable pulse_delay : unsigned(23 downto 0) := (others => '0');

Then I started running a simulation with Modelsim. However, I noticed a particular condition was not being activated when it happened, e.g:

Code: [Select]

pulse_cnt := pulse_cnt + 1;
               
if pulse_cnt = 2199 then
  pulse_cnt := (others => '0');
end if;


You may want to explain the link between 'pulse_delay' and 'pulse_cnt', so we don't waste yet another round.

Basically it was counting upwards from 2200. I then remembered from somewhere in the depths of my head that some programs were very succeptible to having all the correct variables in the process sensitivity list: (...)

A few points.

1. Sensitivity lists do matter for simulation, this is actually the only context (at least for usual tools) where they matter. Sensitivity lists are ignored for synthesis. This is one point to be wary of.
2. Sure there is the 'all' keyword (in VHDL-2008+) to circumvent that, but I don't particularly recommend using it. A detailed sensitivity list acts as a documentation tool for your code, so I prefer using them. Remember the code your write must be readable and understandable to humans.
3. As to variables, you have me confused here. Regular variables can't be used outside of processes, so they can't belong in sensitivity lists. To define variables at a higher level, you need to use *shared* variables. I don't really recommend shared variables though, unless you really know what your are doing and why you need them.
 

Offline betocoolTopic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: au
Re: Comparing a variable to a value in VHDL?
« Reply #10 on: December 15, 2022, 11:48:46 pm »
Thanks for the replies.

And sorry about the confusion! Both "pulse_cnt" and "pulse_delay" were variables, both were "misbehaving". Both were changed to signals.

Code: [Select]

    variable pulse_delay          : unsigned(23 downto 0) := (others => '0');
    variable pulse_cnt            : unsigned(11 downto 0) := (others => '0');

I see what you guys say about simulators and sensitivity lists. I will err on the side of caution and add them, it really isn't that big of a problem.


I suspect that the difference you are seeing is due to the timing differences in assigning variables and signals in VHDL.   Remember that variables change immediately while signals change based on a delta cycle.  There may be a difference caused by that.


I'm not sure what you mean by that? They change immediately in simulation, synthesis or both?

Cheers,

Alberto
 

Offline Daixiwen

  • Frequent Contributor
  • **
  • Posts: 364
  • Country: no
Re: Comparing a variable to a value in VHDL?
« Reply #11 on: December 20, 2022, 10:24:35 am »
Be careful with the numeric_std, it is not a library defined as part of the IEEE standards, so it may not function the same way on all simulators and synthesis tools.  I also advise against these comparisons since it makes it easier to get a mismatch in types.  While using the standard conversions going through signed and unsigned is extra work, it also ensures that you don't accidentally compare values of different types.
I think you are confusing numeric_std with std_logic_(un)signed.
numeric_std is a standard IEEE library, it is the one that defines the signed and unsigned types.
It is not recommended to use std_logic_(un)signed because is it not standard, and adds confusion by directly overloading the operators on std_logic_vector with signed/unsigned operations.
Using numeric_std on the other hand is recommended, and using the operators directly with naturals or integers doesn't create any mismatch. The operators on unsigned can also use naturals, and the operators on signed can also use integers. Those are entirely defined in the VHDL standard and work very well on all tools.

I personally find
Code: [Select]
if pulse_cnt = 2199 theneasier to read than
Code: [Select]
if pulse_cnt = to_unsigned(2199, pulse_cnt'length)or
Code: [Select]
if pulse_cnt = 12d"2199" thenIn addition the latter will cause problems if you suddenly decide to change the size of pulse_cnt. And not all tools will create a warning in case of size mismatch (or in the case of Quartus, will just bury it within 2000 other warnings)
 
The following users thanked this post: betocool


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf