Sum of Array elements VHDL - arrays

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;

Related

Modelsim. Length of arrays do not match

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).

VHDL weird bit errors seemingly makes no sense

I have a Micro-Nova FPGA dev board with a Xilinx Spartan-3A. I am trying to make it communicate bits over GPIO on a raspberry pi using 3 pins: REQ, ACK, DATA. The code works fine if I uncomment the bit_data assignments and comment out "bit_data := data_out(data_ofs);" and on the Pi i get a continous 10101010... etc. But if I leave the code as pasted below I get the wrong bits at random times eg. 1010110100... etc.
Any idea what could be the problem?:
VHDL on FPGA:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity xclock is
Port(CLK : in STD_LOGIC;
REQ : in STD_LOGIC;
ACK : out STD_LOGIC;
DATA : out STD_LOGIC);
end xclock;
architecture Behavioral of xclock is
begin
process(CLK)
variable data_ofs : integer range 0 to 2 := 0;
variable data_out : std_logic_vector(1 downto 0) := "01";
variable bit_data : std_logic := '0';
variable ack_data : std_logic := '0';
variable LASTREQ : std_logic := '0';
variable seconds : integer range 0 to 50000000 := 0;
variable tick : integer range 0 to 50000000 := 0;
begin
if CLK'event and CLK = '1' then
tick := tick + 1;
if tick = 49999999 then
tick := 0;
seconds := seconds + 1;
if seconds = 49999999 then
seconds := 0;
end if;
end if;
if seconds > 1 then
if REQ /= LASTREQ and REQ /= ack_data then
LASTREQ := REQ;
if REQ = '1' then
--bit_data := '1';
ack_data := '1';
else
--bit_data := '0';
ack_data := '0';
end if;
bit_data := data_out(data_ofs);
data_ofs := data_ofs + 1;
if data_ofs = 2 then
data_ofs := 0;
end if;
end if;
end if;
DATA <= bit_data;
ACK <= ack_data;
end if;
end process;
end Behavioral;
Bash script on Pi:
REQ=27
ACK=17
DATA=22
gpio -g mode $REQ out
gpio -g mode $ACK in
gpio -g mode $DATA in
gpio -g write $REQ 1
e=1
while [ 1 ]; do
while [ 1 ]; do
if [ `gpio -g read $ACK` -eq 1 ]; then
while [ 1 ]; do
d=`gpio -g read $DATA`
echo $d
if [ $d -ne $e ]; then
echo error DATA should be $e
sleep 1
else
if [ $e -eq 0 ]; then
e=1
else
e=0
fi
break
fi
done
gpio -g write $REQ 0
break;
fi
done
while [ 1 ]; do
if [ `gpio -g read $REQ` -eq 0 ]; then
while [ 1 ]; do
d=`gpio -g read $DATA`
echo $d
if [ $d -ne $e ]; then
echo error DATA should be $e
sleep 1
else
if [ $e -eq 0 ]; then
e=1
else
e=0
fi
break
fi
done
gpio -g write $REQ 1
break;
fi
sleep 1
done
done
Any help will be greatly appreciated. Pulling my hair out on this one!
I spent some time trying to figure out how your code is supposed to work (what the protocol is), but I gave up. Building off what other have suggested, you might try to make the following modifications and see if it makes any difference.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity xclock is
port(CLK : in STD_LOGIC;
REQ : in STD_LOGIC;
ACK : out STD_LOGIC;
DATA : out STD_LOGIC);
end xclock;
architecture Behavioral of xclock is
signal req_reg1, req_reg2, req_int, last_req : std_logic := '0';
signal bit_data_reg, ack_reg : std_logic;
begin
process(CLK)
variable data_ofs : integer range 0 to 2 := 0;
variable data_out : std_logic_vector(1 downto 0) := "01";
variable bit_data : std_logic := '0';
variable ack_data : std_logic := '0';
variable seconds : integer range 0 to 50000000 := 0;
variable tick : integer range 0 to 50000000 := 0;
begin
if CLK'event and CLK = '1' then
-- Input registers help prevent metastability on REQ line
-- Note that if there is significant bounce or glitching, then
-- you will also need a deglitcher.
req_reg1 <= REQ;
req_reg2 <= req_reg1;
req_int <= req_reg2;
tick := tick + 1;
if tick = 49999999 then
tick := 0;
seconds := seconds + 1;
if seconds = 49999999 then
seconds := 0;
end if;
end if;
if seconds > 1 then
-- Using the registered inputs instead of the direct REQ input.
if req_int /= last_req and req_int /= ack_data then
last_req <= req_int;
if req_int = '1' then
ack_data := '1';
else
ack_data := '0';
end if;
bit_data := data_out(data_ofs);
data_ofs := data_ofs + 1;
if data_ofs = 2 then
data_ofs := 0;
end if;
end if;
end if;
-- Register outputs to ensure consistent OREG packing, if enabled
bit_data_reg <= bit_data;
ack_reg <= ack_data;
DATA <= bit_data_reg;
ACK <= ack_reg;
end if;
end process;
end Behavioral;
The modifications to the code do two things:
Register the input REQ a couple times to reduce the probability of metastability, and then only use the registered values instead of the pin itself. (Read more)
Register the outputs (twice) to ensure that the output register can be placed in an OREG (in IOB), which ensures consistent clock-to-out timing at the output pad. At the boundaries of your device, when possible, it is nice to place a plain FF register stage which guarantees that packing into OREG is possible. Otherwise there may be a feedback path from last register stage back into your design which prevents packing.

Swap elements in an array - VHDL

I have a piece of code in VHDL:
I want to swap the signalIn(0) and signalIn(1) values.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity SwapFP is
port(clockIn:in std_logic);
end SwapFP;
architecture Behavioral of SwapFP is
signal tempOne,tempTwo,a1,a2 : STD_LOGIC_VECTOR(31 DOWNTO 0);
signal state : integer range 0 to 7 := 0;
begin
process(clockIn) is
type floatingPointArray is array(1 downto 0) of std_logic_vector(31 downto 0);
variable signalIn : floatingPointArray;
begin
signalIn(0) := X"3D52CEF8";
signalIn(1) := X"3FBC9F1A";
if rising_edge(clockIn) then
case state is
when 0 =>
tempOne <= signalIn(0);
tempTwo <= signalIn(1);
state <= 1;
when 1 =>
signalIn(1) := tempOne;
signalIn(0) := tempTwo;
state <= 2;
when 2 =>
a1 <= signalIn(0);
a2 <= signalIn(1);
state <= 3;
when others =>
end case;
end if;
end process;
end Behavioral;
In a1 and a2 signals, I am getting the original values X"3D52CEF8" and X"3FBC9F1A" respectively. Means that swapping is not happening. Why is it so?
Your variable assignments to signalIn at the top of the process happen every time the process runs. When state is 2, the values you assigned to signalIn when state equaled 1 are overwritten by this initial assignment.
You can much more easily swap two items like this:
process (clk)
begin
if (rising_edge(clk)) then
signalIn(0) <= signalIn(1);
signalIn(1) <= signalIn(0);
end if;
end process;
This works because the signal assignments using <= do not take place immediately, rather they are scheduled to take place after the process has run.

Synthesizable multidimensional arrays in VHDL

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;

VHDL error related to concatenation of variable

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;
...

Resources