Bitshifting in VHDL creates errors - vhdl

I am trying to bitshift a std_logic_vector, but no matter what I try, I always get an error.
I I have tried to use srl and also shift_right, which I read is safer to use. Both of them are not accepted by the compiler or at least I am making a syntax error, that I can't find. I also tried to cast the result to std_logic_vector.
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity EXAMPLE is
port(
VOL_LEVEL : in integer range 1 to 10; -- from AUDIO_VOL
LED_OUT : out std_logic_vector(9 downto 0)
);
end entity EXAMPLE;
architecture BEHAVIOUR of EXAMPLE is
type STATES is (S_SET_VOL);
signal STATE, NEXT_STATE : STATES;
EXAMPLE: process(VOL_LEVEL)
begin
case STATE is
when S_SET_VOL =>
LED_OUT <= ("1111111111") srl (10-VOL_LEVEL) after 2 ns;
-- Type error resolving infix expression "srl" as type ieee.std_logic_1164.STD_LOGIC_VECTOR.
LED_OUT <= shift_right(unsigned("1111111111"), 10-VOL_LEVEL) after 2 ns;
-- No feasible entries for subprogram "SHIFT_RIGHT".
LED_OUT <= std_logic_vector(shift_right(unsigned("1111111111"), 10-VOL_LEVEL)) after 2 ns;
-- Type conversion (to UNSIGNED) cannot have string literal operand.
end process EXAMPLE;
end BEHAVIOUR;

Related

VHDL enumerator relational operators

I'm currently programming a system in VHDL, and I'm using an enumerator from another package called vnir, which is defined as such:
package vnir is
type row_type_t is (ROW_NONE, ROW_NIR, ROW_BLUE, ROW_RED);
end package vnir;
I've defined my architecture as such
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vnir;
entity imaging_buffer is
port(
clock : in std_logic;
reset_n : in std_logic;
vnir_row_ready : in vnir.row_type_t
);
end entity imaging_buffer;
architecture rtl of imaging_buffer is
signal vnir_row_ready_i : vnir.row_type_t;
begin
vnir_pipeline : process (reset_n, clock) is
begin
if (reset_n = '0') then
vnir_row_ready_i <= vnir.ROW_NONE;
elsif rising_edge(clock) then
if (vnir_row_ready /= vnir.ROW_NONE) then
--do stuff
end if;
end if;
end process vnir_pipeline;
end architecture;
The internal signal vnir_row_ready_i can be assigned to no problem, however the relational operator doesn't seem to work as ModelSim throws this error when I try to compile:
# ** Error: C:/Users/nashg/Documents/iris_project/ex2_iris/vhdl/subsystems/sdram/Imaging Buffer/test.vhd(23): (vcom-1581) No feasible entries for infix operator '/='.
# ** Error: C:/Users/nashg/Documents/iris_project/ex2_iris/vhdl/subsystems/sdram/Imaging Buffer/test.vhd(23): Type error resolving infix expression "/=" as type std.STANDARD.BOOLEAN.
# ** Error: C:/Users/nashg/Documents/iris_project/ex2_iris/vhdl/subsystems/sdram/Imaging Buffer/test.vhd(28): VHDL Compiler exiting
My coworker helped me figure out how to make it work! I think that the /= operator is created in the vnir scope, but not ported over to the entity I'm working on. By writing :use work.vnir."/="; at the beginning of the file it compiles, so the full entity looks like so:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vnir;
use work.vnir."/=";
entity imaging_buffer is
port(
clock : in std_logic;
reset_n : in std_logic;
vnir_row_ready : in vnir.row_type_t
);
end entity imaging_buffer;
architecture rtl of imaging_buffer is
signal vnir_row_ready_i : vnir.row_type_t;
begin
vnir_pipeline : process (reset_n, clock) is
begin
if (reset_n = '0') then
vnir_row_ready_i <= vnir.ROW_NONE;
elsif rising_edge(clock) then
if (vnir_row_ready /= vnir.ROW_NONE) then
--do stuff
end if;
end if;
end process vnir_pipeline;
end architecture;
Alternatively it did work by including use work.vnir.all; and taking out the vnir. before the types, but that wasn't possible with the project I'm working one

Error : Library "IEEE" does not contain primary unit "numeric_std_unsigned"

I'm using Quartus prime edition v15.1 for writing a register file and I need to use the numeric_std_unsigned package. On compiling, there's an error saying
Error (10481): VHDL Use Clause error : design library "IEEE" does not contain primary unit "NUMERIC_STD_unsigned". Verify that the primary unit exists in the library and has been successfully compiled.
How doesn't the IEEE library have the numeric_std_unsigned package? I've searched a lot and found that IEEE actually supports it. And if so, how can I firstly download the package and install it to the compiler or add it to my project?
EDIT
Here's my code:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.numeric_std_unsigned.all;
entity regfile is
port( clk: in STD_LOGIC;
regwrite: in STD_LOGIC;
rs, rt, rd: in STD_LOGIC_VECTOR(1 downto 0);
data_in: in STD_LOGIC_VECTOR(15 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(15 downto 0));
end;
architecture behave of regfile is
type registerFile is array (3 downto 0) of STD_LOGIC_VECTOR(15 downto 0);
signal registers: registerFile;
begin
process(clk) begin
if rising_edge(clk) then
if regwrite='1' then
registers(to_integer(unsigned(rd))) <= data_in;
end if;
end if;
end process;
process(all)
begin
if (to_integer(rs)=0)
then rd1 <= X"0000";
else rd1 <= registers(to_integer(unsigned(rs)));
end if;
if (to_integer(rt)=0)
then rd2 <= X"0000";
else rd2 <= registers(to_integer(unsigned(rt)));
end if;
end process;
end;
When I use IEEE.numeric_std_unsigned.all the compiler reports the error I posted above.
And when I use IEEE_numeric_std.all the compiler reports
can't determine type of object at to_integer
more than one Use Clause imports a declaration of simple name unsigned -- none of the declarations are directly visible
Once you edited your question to provide a Minimal, Complete, and Verifiable example the error is clearly visible.
Remove the use clause with std_logic_arith, it's incompatible with the unsigned declaration package numeric_std_unsigned uses (referenced from a use clause invoking ieee.numeric_std.all). In it's place use
use ieee.numeric_std.all;
Some of the to_integer function calls found in your regfile architecture have a signature of [STD_ULOGIC_VECTOR return NATURAL].
(STD_ULOGIC_VECTOR is the base type for resolved subtype STD_LOGIC_VECTOR in package std_logic_1164 in VHDL -2008).
Some to_integer conversion function calls (e.g. to_integer(rs)) require package numeric_std_unsigned.
Those depending on package numeric_std (e.g. registers(to_integer(unsigned(rs))) also depend on a visible declaration for type unsigned being the same as the type declaration of the same name being visible in package numeric_std (referenced in a use clause in package numeric_std_unsigned).
In VHDL each declaration is unique even if they have the same name. Which one you are referencing is governed by visibility rules.
Before changing the use clause only the unsigned type declared in the Synopsys package was visible in your entity and architecture pair.
After switching std_logic_arith to numeric_std your code analyzes with a -2008 compliant VHDL implementation:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
-- use IEEE.std_logic_arith.all;
use ieee.numeric_std.all;
use IEEE.numeric_std_unsigned.all;
entity regfile is
port (
clk: in STD_LOGIC;
regwrite: in STD_LOGIC;
rs, rt, rd: in STD_LOGIC_VECTOR(1 downto 0);
data_in: in STD_LOGIC_VECTOR(15 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(15 downto 0)
);
end entity;
architecture behave of regfile is
type registerFile is array (3 downto 0) of STD_LOGIC_VECTOR(15 downto 0);
signal registers: registerFile;
begin
process (clk)
begin
if rising_edge(clk) then
if regwrite = '1' then
registers(to_integer(unsigned(rd))) <= data_in;
end if;
end if;
end process;
process (all)
begin
if to_integer(rs) = 0 then
rd1 <= X"0000";
else
rd1 <= registers(to_integer(unsigned(rs)));
end if;
if to_integer(rt) = 0 then
rd2 <= X"0000";
else
rd2 <= registers(to_integer(unsigned(rt)));
end if;
end process;
end architecture;
Style changes not withstanding the only change is the use clause.
You could remove the dependency on package numeric_std by changing the to_integer function calls with the signature [UNSIGNED return NATURAL] to [STD_ULOGIC_VECTOR return NATURAL]:
library ieee;
use ieee.std_logic_1164.all;
-- use IEEE.std_logic_arith.all;
-- use ieee.numeric_std.all;
use IEEE.numeric_std_unsigned.all;
entity regfile is
port (
clk: in std_logic;
regwrite: in std_logic;
rs, rt, rd: in std_logic_vector(1 downto 0);
data_in: in std_logic_vector(15 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(15 downto 0)
);
end entity;
architecture behave of regfile is
type registerFile is array (3 downto 0) of STD_LOGIC_VECTOR(15 downto 0);
signal registers: registerFile;
begin
process (clk)
begin
if rising_edge(clk) then
if regwrite = '1' then
registers(to_integer(rd)) <= data_in;
end if;
end if;
end process;
process (all)
begin
if to_integer(rs) = 0 then
rd1 <= X"0000";
else
rd1 <= registers(to_integer(rs));
end if;
if to_integer(rt) = 0 then
rd2 <= X"0000";
else
rd2 <= registers(to_integer(rt));
end if;
end process;
end architecture;
Note we've gotten rid of the use clause with package numeric_std and dropped some type conversions for generating the indexes for indexed names selecting registers elements for writes to the register file as well as both read ports.
Both these modifications to your code example analyze, elaborate and simulate telling us the indexes work correctly. The second one using only package numeric_std_unsigned enhances readability.
And of course if your VHDL tool is actually missing package numeric_std_unsigned and it isn't cured by re-installation or updating the Quartus tools you could use a -1993 compliant design description:
library ieee;
use ieee.std_logic_1164.all;
-- use IEEE.std_logic_arith.all;
use ieee.numeric_std.all;
-- use IEEE.numeric_std_unsigned.all;
entity regfile is
port (
clk: in std_logic;
regwrite: in std_logic;
rs, rt, rd: in std_logic_vector(1 downto 0);
data_in: in std_logic_vector(15 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(15 downto 0)
);
end entity;
architecture behave of regfile is
type registerFile is array (3 downto 0) of STD_LOGIC_VECTOR(15 downto 0);
signal registers: registerFile;
begin
process (clk)
begin
if rising_edge(clk) then
if regwrite = '1' then
registers(to_integer(unsigned(rd))) <= data_in;
end if;
end if;
end process;
process (rs, rt) -- (all)
begin
if to_integer(unsigned(rs)) = 0 then
rd1 <= X"0000";
else
rd1 <= registers(to_integer(unsigned(rs)));
end if;
if to_integer(unsigned(rt)) = 0 then
rd2 <= X"0000";
else
rd2 <= registers(to_integer(unsigned(rt)));
end if;
end process;
end architecture;
Where the process sensitivity list is manually specified and all to_integer calls are from package numeric_std, requiring unsigned type conversions for std_logic_vector values.
(And this analyzes, elaborates and simulates).
I assume you mean the unsigned type of the numeric_std package in the ieee library.
library ieee;
use ieee.numeric_std.all;
...
signal foo : unsigned(7 downto 0);
or
library ieee;
use ieee.numric_std;
...
signal bar : numeric_std.unsigned(7 downto 0);
The installation folder of Quartus Prime 15.1 actually contains a file called numeric_std_unsigned_vhdl2008.vhd which defines the package numeric_std_unsigned and its body. But, apparently the synthesizer does not support it.
The Quartus Prime Standard Handbook v15.1.1, Volume 1 gives in Section 16 under "VHDL Synthesis Support" -> "VHDL-2008 Support" a link to this online help page. At the time of writing this answer, the list of supported VHDL'08 features does not reference Section 16.8.5 of the VHDL'08 Standard which defines the package numeric_std_unsigned. There is also no reference to Appendix A.2.4.
The following sub-section in the Quartus manual states further:
The Quartus Prime software includes the standard IEEE libraries and several vendor-specific VHDL libraries.
The IEEE library includes the standard VHDL packages std_logic_1164, numeric_std, numeric_bit, and math_real.
Given that, you must revert back to using the numeric_std package. But, this package defines the type unsigned which is also defined in std_logic_arith. You should not use the non-standard std_logic_arith package from Synopsys anymore.
Thus, you have to use the package numeric_std instead of both numeric_std_unsigned and std_logic_arith.. Then you have to convert all std_logic_vector to unsigned first, before passing them as an argument to the function to_integer, e.g.:
to_integer(unsigned(rs))
instead of
to_integer(rs)

VHDL Parametric case

I've some problem with my synthesis tool. I'm writing a module and I'm tryng to make it parametric and scalable. In my design I've a FSM and some counters. The counters have a parametric width ( they are function of the width of the datapath ). The problem is that I'm using that counter to drive a case statements. The synthesizer gives me back this error :
2049990 ERROR - (VHDL-1544) array type case expression must be of a locally static subtype
I've also tried to use subtype, but it doesnt work. The declaration is :
constant LENGTH_COUNTER_WORD : integer := integer(ceil(log2(real(WIDTH_DATA/WIDTH_WORD))));
subtype type_counter_word is std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
signal counter_word : std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
The case :
case type_counter_word'(counter_word) is
when (others => '1') =>
do_stuff();
when others =>
do_other_stuff();
end case;
I cannot switch to VHDL-2008. I've read I can use variable, but I'd like to find a different solution, if it exists. I cannot imagine there isn't any way to give parameters to synthesizer before the synthesis.
This is fixed in VHDL-2008. You can only work around it in earlier standards by using cascaded if statements (with the attendant priority logic). Variables don't make a difference when determining if choices are locally static.
I'm not sure how complicated your do_stuff() and do_other_stuff() operations are, but if you are just doing simple signal assignments, you could look into the and_reduce() function in the ieee.std_logic_misc library.
As an example:
output <= '1' when and_reduce(type_counter_word'(counter_word)) = '1' else '0';
Otherwise, as Kevin's answer suggests, a process block using if statements might be your best option.
About the time of Kevin's good enough answer, I had written this to demonstrate:
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
entity counterword is
generic (
WIDTH_DATA: positive := 16;
WIDTH_WORD: positive := 8
);
end entity;
architecture foo of counterword is
constant LENGTH_COUNTER_WORD : integer :=
integer(ceil(log2(real(WIDTH_DATA/WIDTH_WORD))));
subtype type_counter_word is
std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
signal counter_word : std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
procedure do_stuff is
begin
end;
procedure do_other_stuff is
begin
end;
begin
UNLABELLED:
process (counter_word)
begin
-- case type_counter_word'(counter_word) is
-- when (others => '1') =>
-- do_stuff;
-- when others =>
-- do_other_stuff;
-- end case;
if counter_word = type_counter_word'(others => '1') then
do_stuff;
else
do_other_stuff;
end if;
end process;
end architecture;
Note because type_counter_word is a subtype you can provide the subtype constraints in a qualified expression for the aggregate:
if counter_word = type_counter_word'(others => '1') then
From IEEE Std 1076-2008:
9.3.5 Qualified expressions
A qualified expression is a basic operation (see 5.1) that is used to explicitly state the type, and possibly the subtype, of an operand that is an expression or an aggregate.
This example analyzes, elaborates and simulates while doing nothing in particular. It'll call the sequential procedure statement do_other_stuff, which does nothing.
(For do_stuff and do_other stuff, empty interface lists aren't allowed).

I've this error :Error (10344): VHDL expression error at REG2.vhd(18): expression has 0 elements, but must have 4 elements

I found this code which is a part of Exponentiation implementation, I believe this code is for parallel load register, the code had many mistakes, yet I tried to fix it and simplify it(simplification is to make it work), the original code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity REG is --Register entity
Port ( CLK,set,reset,In_LOAD : in std_logic;
Din_p: in std_logic_vector(m-1 to 0);
Din_s: in std_logic;
Dout: out std_logic);
end REG;
architecture behavior of REG is
signal Q_temp: std_logic_vector(m-1 down to 0);
begin
Dout<=”0”;
comb:process(In_LOAD,Din_s)
begin
if(In_LOAD=”1”) then Q_temp<=Din_p;end if;
end process comb;
state: process(CLK,set,reset)
begin
if(reset=”1”) then Q_temp<=(others=>”0”);end if;
if(set=”1”) then Q_temp<= (others=>”1”);
elsif(CLK’event and CLK=”1”) then
Q_temp:=Din_p & Q_temp(m-1 down to 1);
end if;
Dout<= Q_temp(0);
end process state;
end behavior;
while the code I modified is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity REG2 is --Register entity
generic (m: integer := 4);
Port ( CLK,In_LOAD : in std_logic;
Din_p: in std_logic_vector(m-1 to 0);
Dout: out std_logic);
end REG2;
architecture behavior of REG2 is
signal Q_temp: std_logic_vector(m-1 downto 0);
begin
Dout<='0';
process(In_LOAD, Din_p, CLK)
begin
if (CLK'event and CLK='1') then
Q_temp <=Din_p;
elsif (In_LOAD='1') then
Q_temp <= Din_p & Q_temp(m-1 downto 1);
end if;
end process;
Dout <= Q_temp(0);
end behavior;
so my questions are : 1- why I'm getting this error :(Error (10344): VHDL expression error at REG2.vhd(18): expression has 0 elements, but must have 4 elements)?
2- this is a code for parallel load register, right?
thx
Plenty of things are wrong with your code (and the original code).
use the correct quote character " for bit strings and ' for bits instead of ”
downto is one word, not down to
m is not declared; perhaps this is supposed to be a generic?
Assign to Q_temp using signal assignment <= instead of variable assignment :=
Sensitivity lists for both your processes are incomplete
As #Morten mentions: the direction of Din_p should probably downto instead of to
Bonus (pet peeve): don't use IEEE.STD_LOGIC_ARITH and IEEE.STD_LOGIC_UNSIGNED, because they are not properly standardized. Use ieee.numeric_std instead.

Comparing unsigned, including metavalues, to a bit pattern

I am writing a VHDL process that needs to compare an input value to zero. The input may contain metavalues ('U', 'X', 'L', 'H', etc.), in which case zero should not be asserted.
Unfortunately, ModelSim issues a warning with each comparison:
# ** Warning: NUMERIC_STD."=": metavalue detected, returning FALSE
# Time: 14 ns Iteration: 1 Instance: /tb/uut
Any ideas on how to code the below in order to avoid such warnings? Turning off numeric_std warnings globally is not an option.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
entity Test is
port (
clk : in std_logic;
reset : in std_logic;
i_in_data : in unsigned(31 downto 0);
o_out_zero : out std_logic
);
end Test;
architecture rtl of Test is
begin
process(clk, reset) begin
if(reset='1') then
o_out_zero <= '0';
elsif(rising_edge(clk)) then
if(i_in_data = (i_in_data'range=>'0')) then
o_out_zero <= '1';
else
o_out_zero <= '0';
end if;
end if;
end process;
end architecture;
If the output of o_out_zero doesn't matter in the presence of metavalues, then the useful function to_01 from numeric_std can be used to eliminate them in the comparison expression. See also to_01xz etc for similar purposes...
Replace
if(i_in_data = (i_in_data'range=>'0')) then
with
if to_01(i_in_data) = (i_in_data'range=>'0') then
and it should be good.
You do know that parentheses around the boolean expressions in an if-statement are unnecessary, right? The less VHDL looks like C, the better...

Resources