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.
Related
Is it posible to make array of unconstrained array in vhdl? I am using XCELIUM 18.03-s001.
This is how I declare signal type in pkg_test.vhd:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package pkg_test is
type t_data_bus_array is array(natural range <>) of std_logic_vector;
end pkg_test;
This is entity test_entity.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.pkg_test.all;
entity test_entity is
generic (
DATA_WIDTH : natural := 9; -- Data width of single input
NUMBER_OF_INPUTS : natural := 4 -- Number of inputs
);
port
(
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0);
po_data : out t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0)
);
end test_entity;
architecture test_entity_behav of test_entity is
begin
po_data <= pi_data;
end test_entity_behav;
And this is my error.
[saka#serbia workspace]$ xrun -top test_entity -f filelist -elaborate -clean -sv -access +rwc -v200x
xrun: 18.03-s001: (c) Copyright 1995-2018 Cadence Design Systems, Inc.
xrun: *N,CLEAN: Removing existing directory ./xcelium.d.
pkg_test.vhd:
errors: 0, warnings: 0
test_entity.vhd:
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0);
|
xmvhdl_p: *E,MISRPN (test_entity.vhd,42|73): expecting a right parenthesis (')') [1.1.1].
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0);
|
xmvhdl_p: *E,MISCOL (test_entity.vhd,42|84): expecting a colon (':') 87[4.3.3] 93[4.3.2].
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0);
|
xmvhdl_p: *E,EXPEND (test_entity.vhd,42|98): expecting the reserved word 'END' [1.1].
end test_entity;
|
xmvhdl_p: *E,EXPACE (test_entity.vhd,47|0): expecting a library unit [11.1].
architecture test_entity_behav of test_entity is
|
xmvhdl_p: *E,ENNOFN (test_entity.vhd,49|44): Intermediate file for entity 'TEST_ENTITY' could not be loaded, entity may require re-analysis.
errors: 5, warnings: 0
xrun: *E,VHLERR: Error during parsing VHDL file (status 1), exiting.
It is obviously, that I make some mistake
If I use this declaration
type t_data_bus_array is array(natural range <>) of std_logic_vector(DATA_WIDTH-1 downto 0);
and in entity like this
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0);
There is no error.
If you are not using the VHDL2008 the unconstrained arrays of std_logic_vector are not supported.
You could define a vector array of std_logic type like this:
type SlVectorArray is array (natural range<>, natural range<>) of std_logic;
I'm trying to model a RAM chip in VHDL with generic parameters for the address and data bus widths and for the base address where the RAM is placed in the address space. My problem is that I cannot figure out how to get a slice of an generic unconstrained array parameter to compare it against a std_logic_vector signal.
This the reduced code that is intended to compute the "chip select" signal:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity e is
generic (
BASE_ADDR :std_logic_vector := x"C000";
CELL_ADDR_WIDTH :integer := 4
);
port (
address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
);
end;
architecture behavioral of e is
constant ADDR_WIDTH :integer := BASE_ADDR'length;
signal cs :std_logic;
begin
cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';
end behavioral;
The Lattice ispLEVER VHDL compiler reports the following error:
23:64:23:110|Slice range direction does not match argument range
The message is caused by the expression BASE_ADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH).
How is a slice of the generic unconstrained array BASE_ADDR accessed correctly in VHDL?
Both solutions suggested by #Paebbels and #user1155120 resolve the VHDL compilation error. I quote the suggestions here with the code updated accordingly.
#Paebbels: Use to in slice
Your unconstrained array defaults to a "to" range because the index type of std_logic_vector is integer and integer in turn is defined with a to range :). So use the to keyword in your slice.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity e is
generic (
BASE_ADDR :std_logic_vector := x"C000";
CELL_ADDR_WIDTH :integer := 4
);
port (
address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
);
end;
architecture behavioral of e is
constant ADDR_WIDTH :integer := BASE_ADDR'length;
signal cs :std_logic;
begin
cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR(ADDR_WIDTH-1 to CELL_ADDR_WIDTH) else '0';
end behavioral;
#user1155120: Declare an alias to define a direction
You'll could also add an alias to your architecture declarative region - alias BASEADDR: std_logic_vector(BASE_ADDR'LENGTH - 1 downto 0) is BASE_ADDR; to define a direction and use that - cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASEADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';
I used a more prominent name for the alias:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity e is
generic (
BASE_ADDR :std_logic_vector := x"C000";
CELL_ADDR_WIDTH :integer := 4
);
port (
address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
);
end;
architecture behavioral of e is
constant ADDR_WIDTH :integer := BASE_ADDR'length;
signal cs :std_logic;
alias BASE_ADDR_ALIAS: std_logic_vector(BASE_ADDR'LENGTH - 1 downto 0) is BASE_ADDR;
begin
cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR_ALIAS(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';
end behavioral;
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 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;
...
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;