Why can't I increment this `std_logic_vector`
-
21-08-2019 - |
Question
What's going on here? Why am I getting an 'operator argument type mismatch', and what can I do to fix it?
--
-- 32-bit counter with enable and async reset
--
architecture synthesis1 of counter_32bit is
signal nextvalue : std_logic_vector ( 31 downto 0 );
begin
--
-- combo
--
nextvalue <= value + 1; -- here
--
-- sequential
--
ff:process( clk, rst )
begin
if( rst = '1' ) then
value <= 0; -- and here...
elsif( clk'event and ( clk ='1' ) ) then
if( ena = '1' ) then
value <= nextvalue;
end if;
end if;
end process ff;
end synthesis1;
Thanks
Solution
you can't increment std_logic directly, you need to convert it to unsigned
and the result back to std_logic_vector
using the numeric_std
package.
use ieee.numeric_std.all
...
nextvalue <= std_logic_vector( unsigned(value) + 1 );
See How Do Perform STD_LOGIC_VECTOR Addition Using IEEE.NUMERIC_STD for example.
OTHER TIPS
Try this code:
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
...
nextvalue <= value + "1";
In my case this solution is works!
One more way is to overload the "+" in this case you can write:
function "+" ( a : std_logic_vector; b : integer ) return std_logic_vector is
variable result : unsigned(a'range);
begin
result := unsigned( a ) + 1 ;
return std_logic_vector( result ) ;
end function ;
create a package and include this function in that package and this will do the trick . One more thing do include the ieee numeric_std package because it contains the conversion functions.
In addition to what the answers already provided, you could rewrite the code, defining nextvalue
as having unsigned
data type (below). Note the use of nextvalue <= to_unsigned(0, 32);
to clear the counter, and the use of rising_edge(clk)
to trigger off of a rising edge.
-- 32-bit counter with enable and async reset
architecture synthesis1 of counter_32bit is
signal nextvalue : unsigned ( 31 downto 0 );
begin
ff:process( clk, rst )
begin
if( rst = '1' ) then
nextvalue <= to_unsigned(0, 32); -- reset the count
elsif rising_edge(clk) then
if( ena = '1' ) then
nextvalue <= nextvalue + 1; -- increment the count
end if;
end if;
end process ff;
-- Concurrent assignment statement
value <= std_logic_vector(nextvalue);
end synthesis1;
This form of concurrent assignment seems to be the preferred method of updating a counter from what I have found in books and online.
Also, if you continue to use the std_logic_vector
type for nextvalue
, the preferred method for clearing it seems to be nextvalue <= (others => '0');
rather than just nextvalue <= 0;
.
In a nutshell, STD_LOGIC_VECTOR is just that, a vector of bits. It means nothing by itself so you cannot expect vhdl to semantically assume that an increment operation will work on it. The other posts here about converting it to an unsigned should do the trick.
This will also work:
nextvalue <= value + '1';
Dont know if you are really well versed in VHDL. The following syntax ist logicaly correct if you are using std_logic_arith package