actual s of formal sum must be a variable and type error - vhdl

I'm working on xilinx student labs and trying to learn VHDL but and having some trouble fixing my errors. I'm mostly focused on getting the addition part to work for now.
The errors I'm getting are as below:
[Synth 8-1560] actual s of formal sum must be a variable ["C:/Nexys 4 >Projects/lab4_1_1/lab4_1_1.srcs/sources_1/new/add_two_values_procedure.vhd":54]
[Synth 8-2778] type error near a ; expected type std_ulogic ["C:/Nexys 4 >Projects/lab4_1_1/lab4_1_1.srcs/sources_1/new/add_two_values_procedure.vhd":56]
[Synth 8-2778] type error near b ; expected type std_ulogic ["C:/Nexys 4 >Projects/lab4_1_1/lab4_1_1.srcs/sources_1/new/add_two_values_procedure.vhd":56]
For the first error I read that if I don't use the procedure in a process, then I must pass the signal to the procedure in order to assign the variable total to it. Could someone please shed some light as to how to fix this error please?
For the second and third errors I was looking in the library for std_logic_1164 and saw this line
FUNCTION "and" ( l, r : std_logic_vector ) RETURN std_logic_vector;
To my knowledge (however small it is on this subject) line 56 uses std_logic_vector on either side of the and operator/function (?) and should return a std_logic_vector. So why is it asking me to use std_ulogic.
EDIT: That line above I saw from this website http://www.csee.umbc.edu/portal/help/VHDL/packages/std_logic_1164.vhd but from my book, Designer's guide to VHDL, doesn't have that line in the package.
Below is my code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
entity add_two_values_procedure is
Port ( a : in STD_LOGIC_VECTOR (3 downto 0);
b : in STD_LOGIC_VECTOR (3 downto 0);
operand : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR (3 downto 0);
cout : out STD_LOGIC);
end add_two_values_procedure;
architecture Behavioral of add_two_values_procedure is
signal s : STD_LOGIC_VECTOR (3 downto 0);
procedure add_values (
a : in STD_LOGIC_VECTOR (3 downto 0);
b : in STD_LOGIC_VECTOR (3 downto 0);
operand : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR (3 downto 0))
is
variable total : STD_LOGIC_VECTOR (3 downto 0);
begin
case operand is
when '1' =>
total := a + b;
when '0' =>
total := a - b;
end case;
sum := total;
end procedure add_values;
begin
add_values(a, b, operand, s); 54
sum <= s;
cout <= a and b; 56
end Behavioral;

With regards to line 54:
Quoting VHDL 2008:
If the mode is inout or out, and no object class is explicitly specified, variable is assumed.
So try:
procedure add_values (
a : in STD_LOGIC_VECTOR (3 downto 0);
b : in STD_LOGIC_VECTOR (3 downto 0);
operand : in STD_LOGIC;
signal sum : out STD_LOGIC_VECTOR (3 downto 0))
is
variable total : STD_LOGIC_VECTOR (3 downto 0);
begin
case operand is
...
With regards to line 56:
Look at the type of cout.
You are assigning a std_logic_vector(3 downto 0) to a std_logic.

Related

Beginner with Spartan 6, syntax issue

I'm writing a simple program using Spartan 6 for signed numbers but this error pops up says :hdl 806"near line 12 syntax error"
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Multiplier_Top is
Port (
A : in signed (15 downto 0);
B : in signed (15 downto 0);
Sum : out signed (15 downto 0);
Overflow : out STD_LOGIC;
);
end Multiplier_Top;
architecture Behavioral of Multiplier_Top is
signal Sum_Int signed (16 downto 0) :=(others=>'0');
begin
Sum_Int <= Resize(A,17) + B;
Sum <= Sum_Int(15 downto 0);
Overflow <= Sum_Int(16) xor Sum_Int(15);
end Behavioral;
There are 2 syntax error in the design:
Line 11: Remove the ; after out STD_LOGIC; so it becomes out std_logic
Line 17: Insert a : in Sum_Int signed so it becomes Sum_Int : signed
Some other comments:
Line 17: Remove default value assign :=(others=>'0'), since that is not required when output is assigned by continuous assignment in line 21
Line 17 and others: Use VHDL attributes line 'length to avoid constants in code
The code can then look like this:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
entity Multiplier_Top is
port (
A : in signed (15 downto 0);
B : in signed (15 downto 0);
Sum : out signed (15 downto 0);
Overflow : out std_logic
);
end Multiplier_Top;
architecture Behavioral of Multiplier_Top is
signal Sum_Int : signed (A'length downto 0); -- Length one bit more than A, assuming same length as B
begin
Sum_Int <= Resize(A, Sum_Int'length) + B;
Sum <= Sum_Int(Sum'range);
Overflow <= Sum_Int(Sum_Int'left) xor Sum_Int(Sum_Int'left - 1);
end Behavioral;

error while using the resize function in vhdl

I am trying to program an FPU unit in VHDL. I am doing my first steps. I get two errors while executing this instruction:
mantissa1 <= std_logic_vector(resize(unsigned(mantissa1),mantissa1'length + d));
The errors are:
Error: C:/Modeltech_pe_edu_10.4a/examples/fpu/shifter.vhd(38): Illegal type conversion to ieee.std_logic_1164.STD_LOGIC_VECTOR (operand type is not known).
Error: C:/Modeltech_pe_edu_10.4a/examples/fpu/shifter.vhd(36): (vcom-1078) Identifier "unsigned" is not directly visible.
Here is my code
library ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_misc.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_arith.ALL;
use ieee.numeric_std.all;
entity fpu is
port (
E1,E2 : IN std_logic_vector( 30 downto 23);
M1,M2 : IN std_logic_vector( 22 downto 0);
S1,S2 : IN std_logic_vector (31 downto 31);
op : IN std_logic_vector (1 downto 0);
SUM : OUT std_logic_vector (45 downto 0);
E : OUT std_logic_vector (7 downto 0);
clk : IN std_logic
);
end entity;
architecture arch_fpu of fpu is
SIGNAL d: integer;
SIGNAL mantissa1 : std_logic_vector (22 DOWNTO 0) ;
SIGNAL mantissa2 : std_logic_vector (22 DOWNTO 0) ;
begin
process(E1,E2,M1,M2,S1,S2,clk)
BEGIN
if((op="01") or (op="00")) then
E<=E1 when E1>E2 else
E2;
d<=abs(conv_integer(E1-E2));
mantissa1 <= std_logic_vector(resize(unsigned(mantissa1),mantissa1'length + d));
end if;
END process;
end arch_fpu;
You are mixing VHDL math libraries. I suggest you use either numeric_std (my preference) or std_logic_unsigned/std_logic_arith, but not both.
There are several other issues as well. You cannot assign the larger (by 'd' bits) manitissa1 value back to manitissa1, you need a target of the appropriate size. Your subtraction of E1-E2 will need some type conversion to be legal, perhaps: signed(E1) - signed(E2)
Honestly, you probably want to rethink the whole approach to what you are trying to do, especially if you expect to synthesize this code into logic.

How do I split 16-bit data into 2 8-bit data in VHDL?

How do I split 16-bit data into 2 8-bit data?
signal part : std_logic_vector (16 downto 0);
signal part_1 : std_logic_vector (8 downto 0);
signal part_2 : std_logic_vector (8 downto 0);
The part is actually 17 bit, since 16 downto 0 is a 17 bit range, and the part_* are likewise 9 bit.
If the ranges are 15 downto 0 and 7 downto 0, then you can do the split with:
part_1 <= part( 7 downto 0);
part_2 <= part(15 downto 8);
Btw, quote by Martin Fowler / Phil Karlton:
There are two hard things in computer science:
cache invalidation, naming things, and off-by-one errors.
Why are your signals 17 bits and 9 bits long? I think they should be 16 and 8...
signal part : std_logic_vector (15 downto 0);
signal part_1 : std_logic_vector (7 downto 0);
signal part_2 : std_logic_vector (7 downto 0);
begin -- architecture begin
part_1 <= part(15 downto 8);
part_2 <= part(7 downto 0);
Pretty simple stuff... I'm surprised you didn't run across this in looking at a VHDL example.
There's also aggregate target assignment:
library ieee;
use ieee.std_logic_1164.all;
entity foo is
end entity;
architecture fum of foo is
type fie is array (natural range 0 to 1) of std_logic_vector (7 downto 0);
signal part: std_logic_vector (15 downto 0);
signal part_1: std_logic_vector (7 downto 0);
signal part_2: std_logic_vector (7 downto 0);
begin
(part_1, part_2) <= fie'(part(15 downto 8), part(7 downto 0));
end architecture;
Which is admittedly more useful for extracting elements of records in one fell swoop. What's slick here is that there's no place there's any named signal of type fie.
The reason for the aggregate on the right hand side is because the element size has to match on both sides of the assignment operator, both aggregates are treated as if they are type fie.
Doing this with records allows you to extract elements of varying sizes. Extracting fields from CPU machine instruction formats comes to mind. It allows you to use simple names without requiring aliases for element selected names. (There would be no named record).
When the element size is the same on both sides you can simply use a target aggregate:
library ieee;
use ieee.std_logic_1164.all;
entity fie is
end entity;
architecture fum of fie is
signal part: std_logic_vector (2 downto 0);
signal part_1: std_logic;
signal part_2: std_logic;
signal part_3: std_logic;
begin
(part_1, part_2, part_3) <= part;
end architecture;
These aggregates all use positional association. You can also use named association. Record aggregates require an others choice represent at least one element and all the elements have to have the same type (e.g. std_logic_vector).
Just for completeness: you can also use aliases which makes the signal assignment obsolete:
signal part : std_logic_vector (15 downto 0);
alias part_1 : std_logic_vector(7 downto 0) is part(15 downto 8);
alias part_2 : std_logic_vector(7 downto 0) is part(7 downto 0);

"template" VHDL entities

This has me bugging for quite some time, but is it possible to describe entities in VHDL similar to how templates work in C++ (or to lesser extend generics?). Simply leaving the actual port types to be only decided during synthesize/compilation?
An example would be a multiplexer, say I have a 4 input multiplexer, now I have several bus sizes I use this multiplexer for, -4,6,7,8-. Currently I wrote a different multiplexer for each different bus size; however the output is simply one of the chosen inputs forwarded, and is thus of the same type as the bus.
This seems overly redundant and error prone (choose correct multiplexer at correct times, keep them all in line, update them as I change the bus size). Is there no way to parameterize this?
non generic version below to show the idea.
entity mux_6bit_4input is
port ( input_0 : in std_logic_vector (5 downto 0);
input_1 : in std_logic_vector (5 downto 0);
input_2 : in std_logic_vector (5 downto 0);
input_3 : in std_logic_vector (5 downto 0);
sel : in std_logic_vector (1 downto 0);
output : out std_logic_vector (5 downto 0)
);
end entity mux_6bit_4input;
Maybe I misunderstood the question, but doesn't the common solution using generics solve your problem?
library ieee;
use ieee.std_logic_1164.all;
entity mux_4x1 is
generic (
DATA_WIDTH: integer := 8
);
port (
input_0: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_1: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_2: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_3: in std_logic_vector(DATA_WIDTH-1 downto 0);
sel: in std_logic_vector (1 downto 0);
output: out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end;
architecture behavior of mux_4x1 is
begin
output <=
input_0 when sel = "00" else
input_1 when sel = "01" else
input_2 when sel = "10" else
input_3;
end;
Another solution, if you want to keep things really generic, is to use the cool generic types in VHDL-2008. My simulator doesn't yet support this feature, so here's an example from the excellent book VHDL 2008: Just the New Stuff:
entity generic_mux2 is
generic (type data_type);
port (
sel: in bit;
a, b: in data_type;
z: out data_type
);
end;
architecture rtl of mux2 is
begin
z <= a when sel = '0' else b;
end;
Another option is to use unconstrained arrays:
entity mux_4input is
port (
input_0 : in std_logic_vector ;
input_1 : in std_logic_vector ;
input_2 : in std_logic_vector ;
input_3 : in std_logic_vector ;
sel : in std_logic_vector (1 downto 0);
output : out std_logic_vector
);
end entity mux_4input;
They will inherit their width (and direction) from the signals they are conencted to in the instantiating entity.
It's probably not the right thing to do in this particular case of a mux, rick's answer is what I'd go for, but unconstrained arrays don't get mentioned much, so I thought I'd offer them! In this case, you'd probably also want some asserts to ensure that everything you've wired up is the same width.

Is my VHDL sentence allowed?

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_1164_unsigned.all;
ENTITY alu IS
PORT (a: IN STD_LOGIC_VECTOR (15 DOWNTO 0);
b: IN STD_LOGIC_VECTOR (15 DOWNTO 0);
operation: IN INTEGER (1 TO 10);
result: OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
);
ARCHITECTURE arch-alu OF alu IS
SIGNAL arith, logic: STD_LOGIC_VECTOR (15 DOWNTO 0);
BEGIN
----rest of the code which give values to arith and logic----
WITH operation SELECT
result <= arith WHEN (1 TO 5),
logic WHEN (6 TO 10);
END arch-alu
My query is: Can I put a range after WHEN (as in the code), or I have to specify one by one each possibility of the signal.
Thanks!
According to http://tams-www.informatik.uni-hamburg.de/vhdl/tools/grammar/vhdl93-bnf.html the syntax you've used is permitted by VHDL '93 (the productions to look at there, in order: selected_signal_assignment, selected_waveforms, choices, choice, discrete_range, range) except that the grammar there doesn't seem to allow for the parentheses around the ranges. See also http://www.vhdl.renerta.com/source/vhd00063.htm (which again has no parens around the ranges).
You can use ranges in choices but you should omit the parentheses.
Not that your code fragment contained a lot more errors than just the superfluous parentheses. You had a missing end entity, a superfluous semicolon at the end of the port declaration, and incorrect integer port declaration,... A good VHDL IDE, such as Sigasi HDT, would help you catch these immediately.
Corrected fragment:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY alu IS
PORT (a: IN STD_LOGIC_VECTOR (15 DOWNTO 0);
b: IN STD_LOGIC_VECTOR (15 DOWNTO 0);
operation: IN INTEGER range 1 TO 10;
result: OUT STD_LOGIC_VECTOR (15 DOWNTO 0)
);
end entity;
ARCHITECTURE arch_alu OF alu IS
SIGNAL arith, logic: STD_LOGIC_VECTOR (15 DOWNTO 0);
BEGIN
--rest of the code which give values to arith and logic----
WITH operation SELECT
result <= arith WHEN 1 TO 5,
logic WHEN 6 TO 10;
END arch_alu;

Resources