I am writing VHDL code in which I have used tempx and tempz as variables and tried to concatenate them, but I am having some errors on the line annotated below. Suggestions on what to do please?
The errors are:
Error (10500): VHDL syntax error at ArrayDivider.vhd(53) near text ":="; expecting "(", or "'", or ".",
Error (10500): VHDL syntax error at ArrayDivider.vhd(53) near text "&"; expecting "(", or "'", or "."
Code:
------- Array Divider --------
library ieee;
use ieee.std_logic_1164.all;
----- Entity -----
entity ArrayDivider is
generic
(
---- For x/y
Nx : integer := 8; --- Number of bits in x
Ny : integer := 4 --- Number of bits in y
);
port
(
ipx : in std_logic_vector(Nx-1 downto 0); -- Input x --- (Nx-1 downto 0)
ipy : in std_logic_vector(Ny-1 downto 0); -- Input y --- (Ny-1 downto 0)
opd : out std_logic_vector(Nx-Ny downto 0); -- Quotient --- (Nx-Ny downto 0)
opr : out std_logic_vector(Ny-1 downto 0) -- Remainder --- (Ny-1 downto 0)
);
end ArrayDivider;
----- Architecture -----
Architecture Div of ArrayDivider is
--- This component will compare ipy with parts of ipx of given bits and ---
--- generate bits of divident as well as partial subtraction results ---
--- x = parts of ipx (tempx), y = ipy, op = opd(x) and final z = opr ---
component Cmp is
generic
(
N : integer := 4
);
port
(
x : in std_logic_vector(N-1 downto 0); --- N-1 downto 0
y : in std_logic_vector(N-1 downto 0); --- N-1 downto 0
z : out std_logic_vector(N-1 downto 0); --- N-1 downto 0
op : out std_logic
);
end Component;
variable tempx : std_logic_vector(Ny-1 downto 0) := ipx(Nx-1 downto Nx-Ny); --- (Ny-1 downto 0) (Nx-1 downto Nx-Ny)
variable tempz : std_logic_vector(Ny-1 downto 0); --- (Ny-1 downto 0)
begin
lup:
for a in Nx-Ny downto 0 generate --- Nx-Ny downto 0
begin
Cmpa: Cmp generic map(Ny) port map(tempx, ipy, tempz, opd(a)); --- (Ny)
grea:
if(a > 0) generate
tempx := tempz(Ny-2 downto 0) & ipx(a-1); --- (Ny-2 downto 0)
end generate grea;
zero:
if(a = 0) generate
opr <= tempz;
end generate zero;
end generate lup;
end Div;
as you are not using a process, you should use signals instead of variables for tempx and tempz. your line 53 must then look as follows:
tempx <= tempz(Ny-2 downto 0) & ipx(a-1);
however, probably the use of a process makes more sense. then you have to implement your cmp component as a procedure (not done in example below). the process could look as follows:
...
end Component;
begin
div_proc: process(ipy, ipx)
variable tempx : std_logic_vector(Ny-1 downto 0) ;
variable tempz : std_logic_vector(Ny-1 downto 0);
begin
lup:
for a in 1 downto 0 loop
-- Cmpa: Cmp generic map(Ny) port map(tempx, ipy, tempz, opd(a));
grea:
if(a > 0) then
tempx := tempz(Ny-2 downto 0) & ipx(a-1);
end if;
zero:
if(a = 0) then
opr <= tempz;
end if;
end loop;
end process div_proc;
...
Related
I'm new to VHDL and I have a problem I don't know how to resolve.
The problem appears when I'm doing the simulation, but the code compiles correctly.
Here is the problem :
entity fir is
port ( clock : in STD_LOGIC;
reset : in STD_LOGIC;
X : in STD_LOGIC_VECTOR (7 downto 0); -- X = X(n)
Y : out STD_LOGIC_VECTOR (16 downto 0)); -- Y = Y(n)
end fir;
architecture Behavioral of fir is
signal X_s, XZ1, XZ2, XZ3, XZ4, XZ5, XZ6, XZ7 : signed (7 downto 0); -- XZi = X(n-i)
signal Y_s : signed (16 downto 0);
constant A : signed(7 downto 0) := "00001011"; -- A=11
(constant B,C,D,E,F,G,H similary to A)
begin
process (clock, reset)
begin
X_s <= signed(X);
if (rising_edge(clock)) then
if (reset = '1') then
X_s <= (others => '0');
Y_s <= (others => '0');
XZ1, XZ2,XZ3...XZ7 <= (others => '0'); <= (others => '0');
else
XZ1 <= X_s;
XZ2 <= XZ1;
XZ3 <= XZ2;
XZ4 <= XZ3;
XZ5 <= XZ4;
XZ6 <= XZ5;
XZ7 <= XZ6;
end if;
end if;
end process;
Y_s <= (X_s*A) + (XZ1*B) + (XZ2*C) + (XZ3*D) + (XZ4*E) + (XZ5*F) + (XZ6*G) + (XZ7*H);
Y <= std_logic_vector(Y_s);
end Behavioral;
This line :
Y_s <= (X_s*A) + (XZ1*B) + (XZ2*C) + (XZ3*D) + (XZ4*E) + (XZ5*F) + (XZ6*G) + (XZ7*H);
returns this error : "array shape mismatch - no matching element"
I firstly think it was because of its size, but the problem is still there even if I replace this line :
Y_s <= (X_s*A) + (XZ1*B) + (XZ2*C) + (XZ3*D) + (XZ4*E) + (XZ5*F) + (XZ6*G) + (XZ7*H);
by this one :
Y_s <= (X_s*A);
However, it works with this line : (just to see if the rest of the code is correct) :
Y_s <= (others => '0');
What could I do ?
Thanks a lot.
Your simple case:
Y_s <= (X_s*A);
Y_s - 17 wires (16 downto 0). X_s - 8 wires (7 downto 0). A - 8 wires (7 downto 0). 8 + 8 != 17.
Complex sum:
Y_s <= (X_s*A) + (XZ1*B) + (XZ2*C) + (XZ3*D) + (XZ4*E) + (XZ5*F) + (XZ6*G) + (XZ7*H);
Result sizes for addition and multiplication:
| Operation | Size of result |
+------------+------------------------------+
| Y <= A + B | Maximum (A'Length, B'Length) |
| V <= A * B | A'Length + B'Length |
Therefore your whole sum has size 16: Maximum(8+8,8+8,8+8,8+8,8+8,8+8,8+8,8+8).
Section "“Signed”/“Unsigned” Addition without Overflow" on this page explains how to solve this.
Properly sizing Y_s should solve your problem.
You also should move the assignment X_s <= signed(x) outside the process statement and remove X_s<= (others => '0') assignment inside the reset condition.
I have written a program in modelsim that add to numbers and put the result in Ra/Sum. I have used a tristate buffer, but I get this: Fatal: (vsim-3420) Array lengths do not match. Left is 16 (15 downto 0). Right is 8 (7 downto 0). I understand that this is because they have different lengths. But they cant have the same length either, because then I get an error when adding add1 and add2 and putting them in Sum. So what can I do to make this work?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
entity MAC is
generic (width: integer := 8);
port(
clk, reset : in STD_LOGIC;
MLS_select : in STD_LOGIC;
Rn, Rm, Ra : in STD_LOGIC_VECTOR(width-1 downto 0);
Rd : out STD_LOGIC_VECTOR(width-1 downto 0)
);
end;
architecture behavioral of MAC is
signal mul1, mul2, add1 : UNSIGNED(width-1 downto 0);
signal add2, sum : UNSIGNED(width*2-1 downto 0);
begin
process(clk, reset)
begin
if reset = '1' then Rd <= (others => '0');
elsif rising_edge(clk) then
Rd <= STD_LOGIC_VECTOR(sum(width-1 downto 0));
end if;
end process;
mul1 <= UNSIGNED(Rn);
mul2 <= UNSIGNED(Rm);
add1 <= UNSIGNED(Ra);
add2 <= mul1*mul2;
sum <= add2 when clk = '1' else add2;
sum <= add1+add2;
end architecture;
At first, ... when clk = '1' else ... will create a latch, but no flip-flop.
You need to use ... when rising_edge(clk);.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity MAC is
generic (width: integer := 8);
port(
clk, reset : in STD_LOGIC;
MLS_select : in std_logic;
Rn, Rm, Ra : in std_logic_vector(width - 1 downto 0);
Rd : out std_logic_vector(width - 1 downto 0) := (others => '0')
);
end entity;
architecture rtl of MAC is
signal mul1, mul2, add1 : unsigned(width - 1 downto 0);
signal add2, sum : unsigned(width * 2 - 1 downto 0);
begin
process(clk, reset)
begin
if (reset = '1') then
Rd <= (others => '0');
elsif rising_edge(clk) then
Rd <= std_logic_vector(sum(Rd'range));
end if;
end process;
mul1 <= unsigned(Rn);
mul2 <= unsigned(Rm);
add1 <= unsigned(Ra);
add2 <= (mul1 * mul2) when rising_edge(clk);
sum <= resize(add1, add'length) + add2;
end architecture;
Signal MLS_select is unused. There is no need to calculate the sum with so many bits. I suggest to truncate add2 before the addition, to reduce the number of unused bits (and warnings generated by them).
How can i write this if statement condition in better way?
if ((data_in(8 downto 1)=x"70") or (data_in(8 downto 1)=x"69") or
(data_in(8 downto 1)=x"72") or (data_in(8 downto 1)=x"7A") or
(data_in(8 downto 1)=x"6B") or (data_in(8 downto 1)=x"73") or
(data_in(8 downto 1)=x"74") or (data_in(8 downto 1)=x"6C") or
(data_in(8 downto 1)=x"75") or (data_in(8 downto 1)=x"7D")) then
data_make_code <= data_in (8 downto 1); -- enter key to buffer
wrong_data <='0';
cnt_bit :=0;
-- if valid key then
current_state <= break_code_receive;
elsif
...
end if;
A case statement can be used to compare with multiple values, and the others part of the case can then be used as "else", like:
case data_in(8 downto 1) is
when x"70" | x"69" | x"72" | x"7A" | x"6B" |
x"73" | x"74" | x"6C" | x"75" | x"7D" =>
... -- if part of code
when others =>
... -- else part of code
end case;
An alternative method is to use an array of std_logic_vector with the values, and then make a function that can determine if the data_in value equals either of the values in the array. The type and function declarations can then either be in the architecture or process declaration section. The code in VHDL-2008 can then look like:
type slv_array is array (natural range <>) of std_logic_vector;
function in_array(val : std_logic_vector; set : slv_array) return boolean is
begin
for idx in set'range loop
if val = set(idx) then
return TRUE;
end if;
end loop;
return FALSE;
end function;
...
if in_array(data_in, (x"70", x"69", x"72", x"7A", x"6B",
x"73", x"74", x"6C", x"75", x"7D")) then
... -- if part of code
else
... -- else part of code
end if;
The alternative method requires a few declarations, but is more general applicable.
I need to use multidimensional arrays to represent matrices in my design. I have tried the two available options:
Declaring array of arrays
type t11 is array (0 to c1_r2) of std_logic_vector(31 downto 0);
type t1 is array (0 to r1) of t11; --r1*c1_r2 matrix
Multidimensional arrays.
type matrix is array (natural range <>, natural range <>)
of std_logic_vector(31 downto 0);
However, in both the cases my post synthesis simulation in xilinx gives me the error "Sliced name is allowed only on single-dimensional arrays".
What is the correct way of using multidimensional arrays in synthesizable vhdl design? Any inputs would be welcome.
I am using the XST Synthesizer that comes with Xilinx ISE.
I am indexing both i and j, as my matrix dimension is m * n * 32.
My net a_in in the entity
a_in: in matrix (0 to size - 1, 0 to size - 1);
got modified to
a_in : in STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 );
In my program, I access values from the matrix inside two generate statements for k and m as:
add_instx: add
port map (
a => a_in(k,m),
b => b_in(k,m),
clk => clk,
sclr => clr,
ce => start,
result => temp_out(k,m),
rdy => add_over(k,m)
);
My test bench input for a_in is given as
a_in <= (("00111111100000000000000000000000", "00000000000000000000000000000000"),("00000000000000000000000000000000", "00111111100000000000000000000000"));
My synthesis generated warnings of the type: Xst:387 - The KEEP property attached to the net may hinder timing optimization. You may achieve better results by removing this property. However, I have not set any keep property and I am not sure where to look for this property. Please help! Thanks a lot.
I apologize for not adding the complete code. Please find below the code and package.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.mat_pak.all;
entity newproj is
generic ( size: natural := 2 );
port (
clk: in std_logic;
clr: in std_logic;
start: in std_logic;
a_in: in matrix (0 to size - 1, 0 to size - 1);
b_in: in matrix (0 to size - 1, 0 to size - 1);
aplusb: out matrix (0 to size - 1, 0 to size - 1);
parallel_add_done: out std_logic);
end newproj;
architecture Behavioral of newproj is
COMPONENT add --This is a 32 bit floating point add IP core
PORT (
a : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
b : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
clk : IN STD_LOGIC;
sclr : IN STD_LOGIC;
ce : IN STD_LOGIC;
result : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
rdy: OUT STD_LOGIC
);
END COMPONENT;
signal temp_out: matrix (0 to size - 1, 0 to size - 1) := (others => (others => (others => '0')));
signal add_over: bmatrix (0 to size - 1, 0 to size - 1) := (others => (others => '0'));
begin
g0:
for k in 0 to mat_dim generate
g0x:
for m in 0 to mat_dim generate
add_instx: add
port map (
a => a_in(k,m),
b => b_in(k,m),
clk => clk,
sclr => clr,
ce => start,
result => temp_out(k,m),
rdy => add_over(k,m)
);
end generate;
end generate;
aplusb <= temp_out;
p1_add:
process (add_over)
variable check_all_done: std_logic;
begin
check_all_done := '1';
for k in 0 to mat_dim loop
for m in 0 to mat_dim loop
check_all_done := check_all_done and add_over(k)(m);
end loop;
end loop;
parallel_add_done <= check_all_done;
end process;
end Behavioral;
The package used here is:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;
package mat_pak is
CONSTANT mat_dim : natural := 2;
type matrix is array (natural range <>, natural range <>)
of std_logic_vector(31 downto 0);
type bmatrix is array (natural range <>, natural range <>)
of std_logic;
end mat_pak;
The post synthesis simulation model file modified the entity in terms of ordering and data type, on its own. The entity looks as below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;
use UNISIM.VPKG.ALL;
entity newproj is
port (
clk : in STD_LOGIC := 'X';
clr : in STD_LOGIC := 'X';
start : in STD_LOGIC := 'X';
parallel_add_done : out STD_LOGIC;
a_in : in STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 );
b_in : in STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 );
aplusb : out STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 )
);
end newproj;
Your first array is not a multi dimensional array, it's a 2-times nested 1 dimensional array.
Your example:
type t11 is array (0 to c1_r2) of std_logic_vector(31 downto 0);
type t1 is array (0 to r1) of t11;
This definition is more clear:
subtype t_dim1 is std_logic_vector(31 downto 0);
type t_dim1_vector is array(natural range <>) of t_dim1;
subtype t_dim2 is t_dim1_vector(0 to c1_r2);
type t_dim3_vector is array(natural range <>) of t_dim2;
subtype t_dim3 is t_dim3_vector(0 to r1);
You can access this structure by indexing each dimension:
signal matrix3 : t_dim3;
signal matrix2 : t_dim2;
signal matrix1 : t_dim1;
signal slv : std_logic_vector(31 downto 0);
signal sl : std_logic;
matrix2 <= matrix3(i);
matrix1 <= matrix2(j);
matrix1 <= matrix3(i)(j);
slv <= matrix3(i)(j);
sl <= matrix3(i)(j)(k);
You can also slice each dimension:
signal matrix3 : t_dim3;
signal slice3 : t_dim3_vector(0 to 3);
signal slice2 : t_dim2_vector(0 to 3);
signal slv : std_logic_vector(7 downto 0);
slice3 <= matrix3(4 to 7);
slice2 <= matrix3(i)(2 to 5);
slice2 <= slice3(i)(2 to 5);
slv <= matrix3(i)(j)(15 downto 8);
Your second example:
type matrix is array (natural range <>, natural range <>) of std_logic_vector(31 downto 0);
This is a 2-dimensional array with a nested 1-dimensional array. This structure can be accessed as follows:
signal mat : matrix(0 to r1, p to c1_r2);
signal slv : std_logic_vector(31 downto 0);
signal sl : std_logic;
slv <= mat(i, j);
sl <= mat(i, j)(k);
Since VHDL-2008 slicing is also allowed in multi dimensional array. Before VHDL-2008 you have to employ functions for this job.
Have a look into my PoC.vectors package to see ways on how you can handle 1- and multi dimensional arrays.
In the mean time Xilinx has added some information in it's [Vivado synthesis user guide (UG901)](xilinx website offline at time of writing)
For example:
-- 3-D Ram Inference Example (Single port)
-- Compile this file in VHDL2008 mode
-- File:rams_sp_3d.vhd
library ieee;
use ieee.std_logic_1164.all;
package mypack is
type myarray_t is array(integer range<>) of std_logic_vector;
type mem_t is array(integer range<>) of myarray_t;
end package;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.mypack.all;
entity rams_sp_3d is
generic (
NUM_RAMS : integer := 2;
A_WID : integer := 10;
D_WID : integer := 32
);
port (
clk : in std_logic;
we : in std_logic_vector(NUM_RAMS-1 downto 0);
ena : in std_logic_vector(NUM_RAMS-1 downto 0);
addr : in myarray_t(NUM_RAMS-1 downto 0)(A_WID-1 downto 0);
din : in myarray_t(NUM_RAMS-1 downto 0)(D_WID-1 downto 0);
dout : out myarray_t(NUM_RAMS-1 downto 0)(D_WID-1 downto 0)
);
end rams_sp_3d;
architecture arch of rams_sp_3d is
signal mem : mem_t(NUM_RAMS-1 downto 0)(2**A_WID-1 downto 0)(D_WID-1 downto 0);
begin
process(clk)
begin
if(clk’event and clk=’1’) then
for i in 0 to NUM_RAMS-1 loop
if(ena(i) = ‘1’) then
if(we(i) = ‘1’) then
mem(i)(to_integer(unsigned(addr(i)))) <= din(i);
end if;
dout(i) <= mem(i)(to_integer(unsigned(addr(i))));
end if;
end loop;
end if;
end process;
end arch;
I am new to VHDL and I searched all of the internet and i didnt find anything that would help me !
I am trying to add the elements of an array (32 Elements !), so i cant just write
for example s <= s(0) + s(1) + s(3) ... s(5) + ....s(32)
how can i generalise such a calculation ??
or what am i doing wrong ?
My Code (that didnt work in the simulation) is ..
(just for 5 elemets ....)
library IEEE;
library work;
library std;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use ieee.std_logic_arith.all;
entity main is Port (
EIN : in std_logic;
AUS_1 : out std_logic_vector(3 downto 0));
end main;
architecture Behaviour of main is
type Cosinus is array (0 to 4) of std_logic_vector(3 downto 0);
type Sinus is array (0 to 4) of std_logic_vector(3 downto 0);
Signal SumSin :std_logic_vector(3 downto 0);
begin
main : process(Ein)
variable Cos : Cosinus;
variable Sin : Sinus;
begin
if( Ein='1' ) then
sin(0) := "0011";
sin(1) := "0001";
sin(2) := "1010";
sin(3) := "1111";
sin(4) := "1110";
for n in 0 to 4 loop
SumSin <= SumSin + Sin(n);
end loop;
else
sin(0) := "1011";
sin(1) := "0101";
sin(2) := "1000";
sin(3) := "1001";
sin(4) := "1100";
for n in 0 to 4 loop
SumSin <= SumSin + Sin(n);
end loop;
end if;
end process;
Aus_1 <= SumSin;
end Behaviour;
I would be thanksfull
First... Don't use std_logic_arith.
Then, Use a variable for the running sum and assign is to a signal afterwards:
...
main : process(Ein)
variable Cos : Cosinus;
variable Sin : Sinus;
variable SumSin : signed(3 downto 0);
begin
sumsin := (others => '0');
....
for n in Sin'range loop
SumSin := SumSin + Sin(n);
end loop;
end if;
Aus_1 <= SumSin;
end process;