VHDL: Error in when conditional - syntax-error

This question is very basic, but I just started learning VHDL, and I can't figure out the error.
So, I'm using Quartus Prime Lite, and getting error
Error (10500): VHDL syntax error at Package_42.vhd(30) near text "when"; expecting ";"
when compiling the following piece of code.
Any ideas what could be wrong?
Thanks!
library ieee;
use ieee.std_logic_1164.all;
package Package_42 is
subtype StepType is std_logic_vector(3 downto 0);
function Problem_42(a : in std_logic;
b : in std_logic;
j : in StepType;
k : in StepType) return StepType;
end;
package body Package_42 is
function Problem_42(a : in std_logic;
b : in std_logic;
j : in StepType;
k : in StepType) return StepType is
variable Step : StepType := "----";
begin
Step := "0100" when a = '1' and b = '0' else <-- ERROR is HERE!!!
j when a = '1' else
k when b = '1' else
"----";
return Step;
end;
end package body;

First, make sure you have turned on the VHDL-2008 switch.
If that does not work, file a bug report against your tool and re-write your code using an if statement.

Related

I'm getting an syntax error in my VHDL code near counter

I'm trying to simulate a pulse width modulate (PMW) waveform generator and getting a syntax error in ISE. Checked fuse.xmsgs and found out it's near counter. Can someone point out the syntax error, please?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
entity pwm_gen is
port
(
clock, reset : in std_logic;
width : in std_logic_vector(7 downto 0);
pwm : out std_logic);
end pwm_gen;
architecture bhv of pwm_gen is
type counter is range 0 to 255;
counter count := 0;
begin
process (clock)
begin
if (reset = '1') then
count <= 0;
elsif (clock'event and clock = '1') then
if (count <= width) then
count <= count + 1;
pwm <= '1';
else
count <= count + 1;
pwm <= '0';
end if;
end if;
end process;
end bhv;
counter count := 0;
This is illegal syntax, as you didnt declare the object class (signal, constant, variable). You need to use the format:
signal count : counter := 0
This is also illegal, as you are comparing an integer to a std_logic_vector that you havent included a package for. You need to convert the slv to an unsigned
if (count <= unsigned(width)) then
And finally, reset is missing from the sensitivity list

VHDL password program with DE2-board

Summary:
I'm trying to make a password system in VHDL with the DE2 Altera board. SW 0 to 7 is the combination lock, LEDR 0 to 7 shows the current code and signal 'code' stores the combination. When the switches match the code you have the option to change the code by holding down KEY(1).
Problem:
The code works as it should, only the starter code is not what's expected. It should be: "01010101" as shown in the signal; but it comes out as "01111111". I suspect the program enters the if-statement on startup, but I don't see how that's possible, seeing as 'code' and SW should't be equal.
What am I missing?
Here is the code:
library IEEE;
use IEEE.std_logic_1164.all;
entity pass_sys is
port(
SW : in std_logic_vector(7 downto 0);
KEY : in std_logic_vector(3 downto 0);
LEDR : out std_logic_vector(17 downto 0);
LEDG : out std_logic_vector(17 downto 0)
);
end pass_sys;
architecture func of pass_sys is
signal code : std_logic_vector(7 downto 0) := "01010101"; --start code
begin
process(SW)
begin
LEDR(7 downto 0)<=code;
if (SW = code) then
LEDG(0)<='1';
LEDG(1)<=not KEY(1);
if (KEY(1) = '0') then
code<=SW;
end if;
else
LEDG(0)<='0';
end if;
end process;
end func;
I assume your problem happens on your board, not in simulation. If I'm wrong, my answer is not the one you expect.
This initialization way is usefull only in simulation :
signal code : std_logic_vector(7 downto 0) := "01010101"; --start code
Synthesis will not consider your initialization value (That's why I discourage you to use this, except in test bench). If you want to initialize a signal, I advice to use a reset.
Notes :
You should put KEY in sensitivity list and put this line out of your process :
LEDR(7 downto 0)<=code;
Your process infers latches, it's not forbidden but you must be careful with this
EDIT : How to add a reset
library IEEE;
use IEEE.std_logic_1164.all;
entity pass_sys is
port(
RST : in std_logic;
SW : in std_logic_vector(7 downto 0);
KEY : in std_logic_vector(3 downto 0);
LEDR : out std_logic_vector(17 downto 0);
LEDG : out std_logic_vector(17 downto 0)
);
end pass_sys;
architecture func of pass_sys is
signal code : std_logic_vector(7 downto 0);
begin
LEDR(7 downto 0)<=code;
process(SW, code, KEY)
begin
if RST = '1' then
LEDG <= (others => '0');
code <= "01010101";
elsif (SW = code) then
LEDG(0)<='1';
LEDG(1)<=not KEY(1);
if (KEY(1) = '0') then
code<=SW;
end if;
else
LEDG(0)<='0';
end if;
end process;
end func;
The pin RST of your component could be connected to an analogic signal of you card (POWER_GOOD, ALIM_ON, DONE, ...) or to a pll_locked signal of a PLL if you use it.

How to use an entity inside an architecture in VHDL

My purpose is to impement a Keyboard entity which uses Button entites.
So I wrote the following VHDL code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Keyboard is
port ( ck, stop : in STD_LOGIC;
data_in : in STD_LOGIC_VECTOR (11 downto 0);
data_out : out STD_LOGIC_VECTOR (3 downto 0));
end Keyboard;
entity Button is
port ( clk : in STD_LOGIC ;
signal_in : in STD_LOGIC;
output : out STD_LOGIC);
end Button;
architecture test of Keyboard is
signal NUM : STD_LOGIC_VECTOR (11 downto 0) := (others=>'0');
component Button is
port ( clk : in STD_LOGIC ;
signal_in : in STD_LOGIC;
output : out STD_LOGIC);
end component;
begin
num_0 : entity Button port map(ck,data_in(0),NUM(0));
num_1 : entity Button port map(ck=>clk,data_in(1)=>signal_in,NUM(1)=>output);
num_2 : entity Button port map(ck=>clk,data_in(2)=>signal_in,NUM(2)=>output);
num_3 : entity Button port map(ck=>clk,data_in(3)=>signal_in,NUM(3)=>output);
num_4 : entity Button port map(ck=>clk,data_in(4)=>signal_in,NUM(4)=>output);
num_5 : entity Button port map(ck=>clk,data_in(5)=>signal_in,NUM(5)=>output);
num_6 : entity Button port map(ck=>clk,data_in(6)=>signal_in,NUM(6)=>output);
num_7 : entity Button port map(ck=>clk,data_in(7)=>signal_in,NUM(7)=>output);
num_8 : entity Button port map(ck=>clk,data_in(8)=>signal_in,NUM(8)=>output);
num_9 : entity Button port map(ck=>clk,data_in(9)=>signal_in,NUM(9)=>output);
num_on : entity Button port map(ck=>clk,data_in(10)=>signal_in,NUM(10)=>output);
num_off : entity Button port map(ck=>clk,data_in(11)=>signal_in,NUM(11)=>output);
output <= "0000" when NUM = "000000000001" else --0
"0001" when NUM = "000000000010" else --1
"0010" when NUM = "000000000100" else --2
"0011" when NUM = "000000001000" else --3
"0100" when NUM = "000000010000" else --4
"0101" when NUM = "000000100000" else --5
"0110" when NUM = "000001000000" else --6
"0111" when NUM = "000010000000" else --7
"1000" when NUM = "000100000000" else --8
"1001" when NUM = "001000000000" else --9
"1010" when NUM = "010000000000" else --ON
"1100" when NUM = "100000000000" else --OFF
"1111";
end test;
architecture EdgeDetector of Button is
signal signal_d:STD_LOGIC;
begin
process(clk)
begin
if clk= '1' and clk'event then
signal_d<=signal_in;
end if;
end process;
output<= (not signal_d) and signal_in;
end EdgeDetector;
By starting the compilation on QuartusII I face the following error:
Error (10482): VHDL error at PitAlarm.vhd(11): object "STD_LOGIC" is
used but not declared
But I can't understand what it means with "not declared" ???
Using "direct entity instantiation" you are explicitly binding an entity out of a specific library instead of using "configurations" or some default strategy to find a matching one. So, num_0 : entity Work.Button port map(...); - note the explicit library name (here, Work).
The specific error you find
std_logic not declared
comes from the visibility rules for library clauses.
Button's own entity/arch will normally be in a separate file, separately compiled before compiling the top level.
It would then have its own library/use clauses for the library where std_logic is declared.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
With more than one entity in the same file, this clause only applies to the following entity declaration (and makes it visible o the corresponding architectures).
So you need to repeat these two lines before each entity declaration in the file.

VHDL textio read file debug

I am having some trouble debugging this program. I was given an assignment to read test vectors from a text file to test a program. The program and test bench code is written below. I cannot figure out why my simulation is coming up blank. No errors, the simulation window comes up, but it is blank. Any idea what the problem may be?
Module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity PAR is
Port ( data : in STD_LOGIC_VECTOR (3 downto 0);
parity : out STD_LOGIC);
end PAR;
architecture Behavioral of PAR is
begin
proc: process
variable count: bit;
begin
for i in data'range loop
if data(i)='1' then
count:=not count;
end if;
end loop;
if count='0' then
parity<='0';
else
parity<='1';
end if;
wait;
end process;
end Behavioral;
Test Bench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE std.textio.all;
use ieee.std_logic_textio.all;
ENTITY PAR_test IS
END PAR_test;
ARCHITECTURE behavior OF PAR_test IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT PAR
PORT(
data : IN std_logic_vector(3 downto 0);
parity : OUT std_logic
);
END COMPONENT;
--Inputs
signal data : std_logic_vector(3 downto 0) := (others => '0');
--Outputs
signal parity : std_logic;
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: PAR PORT MAP (
data => data,
parity => parity
);
TB: process
file vec_file: text;
variable buf_in: line;
variable testv: std_logic_vector(0 to 4);
begin
file_open(vec_file,"PAR_file.txt,", read_mode);
while not endfile (vec_file) loop
readline (vec_file, buf_in);
read(buf_in,testv);
data(3) <= testv(0);
data(2) <= testv(1);
data(1) <= testv(2);
data(0) <= testv(3);
wait for 10 ns;
assert (parity=testv(4))
report "Test Failed" severity error;
end loop;
wait;
END process;
end;
in your "file_open.." line you have a "," that's not needed
wrong is:
file_open(vec_file,"PAR_file.txt,", read_mode);
correct is:
file_open(vec_file,"PAR_file.txt", read_mode);

"Serialize" VHDL record

Suppose I have the following type definition which relies on constants to indicate vector length of the record members:
type point_t is record
x: std_logic_vector(X_WIDTH-1 downto 0);
y: std_logic_vector(Y_WIDTH-1 downto 0);
end record;
I would like to convert these kind of records into std_logic_vectors to put them into, say, a FIFO. Currently I am using the following code:
PROCEDURE encodepoint(signal pnt: in point_t;
signal d: out std_logic_vector(POINT_ENC_WIDTH-1 downto 0)) is
variable top: integer := 0;
begin
top := X_WIDTH-1;
d(top downto 0) <= pnt.x;
top := top + Y_WIDTH;
d(top downto top-X_WIDTH+1) <= sl.y;
d(d'left downto top+1) <= (others => '0');
end;
This code is suboptimal in many ways. For example it requires me to always correctly set POINT_ENC_WIDTH to a value that is big enough to allow d to hold the whole serialized record. It relies on the programmer to do very mechanical work. For example for every member of the record, say x, X_WIDTH appears twice in the code, once in direct connection with x and once in connection with the next member, y. This get tedious quickly. If I change the definition of the record by adding additional fields, I have to update both the serializing and the (very similar) deserializing code, and I may just forget this. When I remove fields, at least the compiler complains.
Thus this leads me to my question: Is there a simple, automated or at least quasi-automated way to convert VHDL records into std_logic_vectors without having to resort to manually written serializing/unserializing code? It is not important for me to know the specific encoding, as I am using the records internally and the final output format is clearly specified and will be implemented manually.
Can't you just write this:
d <= pnt.x & pnt.y;
While there is currently no official automated way of converting records to vectors (and vice-versa), it is a very common requirement. You have 2 options:
Define your own to_vector and from_vector functions for every record type (tedious)
Autogenerate packages containing above type conversions (difficult / error prone)
Tedious and repetitive tasks that motivate you to write a script to generate code are an indication of a deficiency in the language itself. You can change this by taking an active role in the IEEE working-group and influence the next version of the VHDL standard.
I typically define conversion functions in a package along with the record.
In your case, something like:
function point2slv (pnt : point_t) return std_logic_vector is
variable slv : std_logic_vector(X_WIDTH + Y_WIDTH - 1 downto 0);
begin
slv := pnt.x & pnt.y;
return slv;
end;
function slv2point (slv : std_logic_vector) return point_t is
variable pnt : point_t;
begin
pnt.x := slv(X_WIDTH + Y_WIDTH - 1 downto Y_WIDTH);
pnt.y := slv(Y_WIDTH - 1 downto 0);
return pnt;
end;
NOTE:
Depending on what you're trying to do, you may wish to use pre-defined sizes on one side or the other, and conversion functions to pad/clip to natural lengths (ie: perhaps fit the X and Y values into 16 or 32 bit values). The unsigned type and resize function work well for this:
slv(31 downto 16):= std_logic_vector(resize(unsigned(pnt.x,16)));
slv(15 downto 0):= std_logic_vector(resize(unsigned(pnt.7,16)));
Taken from discussion here
One reasonable way to do this, with large records is to define the ranges ahead of time like this:
type t_SPI_DATA_PORT is record
Data_Size_Minus1: std_ulogic_vector(31 downto 28);
Done: std_ulogic_vector(27 downto 27);
Rx_Wait_Timeout: std_ulogic_vector(26 downto 26);
Rx_Wait_On_Miso: std_ulogic_vector(25 downto 25);
Sclk_Select: std_ulogic_vector(24 downto 24);
Reserved: std_ulogic_vector(23 downto 20);
Hold_Cs: std_ulogic_vector(19 downto 19);
Cpha: std_ulogic_vector(18 downto 17);
Cpol: std_ulogic_vector(16 downto 16);
Data: std_ulogic_vector(15 downto 0);
end record;
Then the conversion functions look like this:
function To_Std_ULogic_Vector(L : t_SPI_DATA_PORT) return
std_ulogic_vector is
variable RetVal: std_ulogic_vector(31 downto 0);
begin
RetVal := (others => '0');
RetVal(L.Data_Size_Minus1'range) := L.Data_Size_Minus1;
RetVal(L.Done'range) := L.Done;
RetVal(L.Rx_Wait_Timeout'range) := L.Rx_Wait_Timeout;
RetVal(L.Sclk_Select'range) := L.Sclk_Select;
RetVal(L.Reserved'range) := L.Reserved;
RetVal(L.Rx_Wait_On_Miso'range) := L.Rx_Wait_On_Miso;
RetVal(L.Hold_Cs'range) := L.Hold_Cs;
RetVal(L.Cpha'range) := L.Cpha;
RetVal(L.Cpol'range) := L.Cpol;
RetVal(L.Data'range) := L.Data;
return(RetVal);
end To_Std_ULogic_Vector;
function From_Std_ULogic_Vector(L : std_ulogic_vector) return
t_SPI_DATA_PORT is
variable RetVal: t_SPI_DATA_PORT;
variable Lx: std_ulogic_vector(L'length - 1 downto 0);
begin
Lx := L;
RetVal.Data_Size_Minus1 := Lx(RetVal.Data_Size_Minus1'range);
RetVal.Done := Lx(RetVal.Done'range);
RetVal.Rx_Wait_Timeout := Lx(RetVal.Rx_Wait_Timeout'range);
RetVal.Sclk_Select := Lx(RetVal.Sclk_Select'range);
RetVal.Reserved := Lx(RetVal.Reserved'range);
RetVal.Rx_Wait_On_Miso := Lx(RetVal.Rx_Wait_On_Miso'range);
RetVal.Hold_Cs := Lx(RetVal.Hold_Cs'range);
RetVal.Cpha := Lx(RetVal.Cpha'range);
RetVal.Cpol := Lx(RetVal.Cpol'range);
RetVal.Data := Lx(RetVal.Data'range);
return(RetVal);
end From_Std_ULogic_Vector;
I have prepared a script which automatically generates the VHDL package for conversions between the user defined record type and the std_logic_vector type.
The sources of this script are published as PUBLIC DOMAIN in the alt.sources group.
You can see http://groups.google.com/group/alt.sources/browse_frm/thread/53ea61208013e9d1 or look for topic "Script to generate VHDL package for conversion between the record type and std_logic_vector"
If you want to unpack the archive from the Google archive, remember to select "show original" option. Otherwise the indendation of the Python source will be damaged.
I did another try at record serialization. I believe my method is a bit more robust. You still need to create function for every record type but you do not need to mention ranges.
Lets say you need to serialize type_a using my package:
type type_a is record
a : std_logic_vector(15 downto 0);
b : std_logic_vector(31 downto 0);
c : std_logic_vector(7 downto 0);
d : std_logic_vector(7 downto 0);
end record type_a;
constant type_a_width : integer := 64;
Define two functions like this:
use work.SERIALIZE_PKG.all;
function serialize (
input : type_a)
return std_logic_vector is
variable ser : serializer_t(type_a_width-1 downto 0);
variable r : std_logic_vector(type_a_width-1 downto 0);
begin -- function serialize_detectorCacheLine_t
serialize_init(ser);
serialize(ser, input.a);
serialize(ser, input.b);
serialize(ser, input.c);
serialize(ser, input.d);
r := serialize_get(ser);
return r;
end function serialize;
function deserialize (
input : std_logic_vector)
return type_a is
variable ser : serializer_t(type_a_width-1 downto 0);
variable r : type_a;
begin -- function serialize_detectorCacheLine_t
ser := serialize_set(input);
deserialize(ser, r.a);
deserialize(ser, r.b);
deserialize(ser, r.c);
deserialize(ser, r.d);
return r;
end function deserialize;
And then you can use it in code like this:
signal type_a_ser : std_logic_vector(type_a_width-1 downto 0) := (others => '0');
signal type_a_in : type_a;
signal type_a_out : type_a;
....
type_a_ser <= serialize(type_a_in);
type_a_out <= deserialize(type_a_ser);
I posted my code and example of more complex types (nested records etc) at: https://github.com/gitmodimo/vhdl-serialize