Referencing entity generic inside package in VHDL? - vhdl

I am trying to define a type inside a package whose size is dependent on the component generics. Here is what I am trying to do, but synthesis is complaining:
package DcoPack is
component SinCosDco
generic
(
g_LUT_DEPTH : integer := 2**10;
g_LUT_BIT_RES : integer := 15
);
port
(
reset : in std_logic;
lClk : in std_logic;
InFreqCtrl : in std_logic_vector(31 downto 0) := X"028F5C28";
InStartPhse : in std_logic_vector(31 downto 0) := X"00000000";
OutDco : out signed((g_LUT_BIT_RES - 1) downto 0)
);
type LutSinT is array(0 to g_LUT_DEPTH - 1) of
std_logic_vector(g_LUT_BIT_RES-1 downto 0);
function f_QuantizationSgn(nbit : integer; max_abs : real; dval : real)
return std_logic_vector;
function f_InitLutSin
return LutSinT;
end package DcoPack;
package body DcoPack is
function f_QuantizationSgn(nbit : integer; max_abs : real; dval : real)
return std_logic_vector is
<function body>
end function;
function f_InitLutSin return LutSinT is
<function body>
end function;
end package body DcoPack;
and my component
library DCO_lib;
use DCO_lib.DcoPack.all;
entity Dco is
generic
(
g_LUT_DEPTH : integer := 2**10;
g_LUT_BIT_RES : integer := 15
);
port
(
reset : in std_logic;
lClk : in std_logic;
InDcoEn : in std_logic;
InFreqCtrl : in std_logic_vector(31 downto 0) := X"028F5C28";
InStartPhse : in std_logic_vector(31 downto 0) := X"00000000";
OutDco : out signed((g_LUT_BIT_RES - 1) downto 0)
);
end entity Dco;
architecture zDco of Dco is
-- want to reference LutSinT in numerous components, it varies depending
-- on generics
constant c_SinCosLut : LutSinT := f_InitLutSin;
... <rest of code is irrelevant
As the code above shows, I am trying to reference this type inside each component. However, I need to be able to easily vary the generic parameters depending on the project, so is there a way for VHDL to infer the correct array size? Or am I locked into defining the g_LUT_DEPTH/g_LUT_BIT_RES in the package or hard-coding the type inside each component?
EDIT: Added clarifying code snippets and explanation.

Yes there now is. VHDL-2008 supports package generics. So you can write
library ieee;
use ieee.numeric_std.all;
entity SinCosDco is
generic (
g_LUT_DEPTH : positive;
g_LUT_BIT_RES : positive
);
port (
OutDco : out signed((g_LUT_BIT_RES - 1) downto 0)
);
end entity;
architecture tmp of SinCosDco is
use ieee.std_logic_1164.all;
begin
OutDco <= to_signed(-1, g_LUT_BIT_RES);
end architecture;
library ieee;
package DcoPack is
generic (
g_LUT_DEPTH : positive := 2**10;
g_LUT_BIT_RES : positive := 15
);
use ieee.numeric_std.all;
component SinCosDco
generic (
g_LUT_DEPTH : positive := g_LUT_DEPTH;
g_LUT_BIT_RES : positive := g_LUT_BIT_RES
);
port (
OutDco : out signed((g_LUT_BIT_RES - 1) downto 0)
);
end component;
use ieee.std_logic_1164.all;
type LutSinT is array(0 to g_LUT_DEPTH - 1) of std_logic_vector(g_LUT_BIT_RES-1 downto 0);
end package DcoPack;
entity e is end entity;
library ieee;
architecture a of e is
constant g_LUT_DEPTH: positive := 2**7; -- remember integer is only 32 bits
constant g_LUT_BIT_RES : positive := 8;
package myDcoPack is new work.DcoPack
generic map (
g_LUT_DEPTH => g_LUT_DEPTH,
g_LUT_BIT_RES => g_LUT_BIT_RES);
-- use work.myDcoPack.all; -- optional
use ieee.numeric_std.all;
signal output : signed((g_LUT_BIT_RES - 1) downto 0);
use ieee.std_logic_1164.all;
signal lut : myDcoPack.LutSinT;
begin
comp_inst : myDcoPack.SinCosDco
port map ( OutDco => output );
lut(0) <= std_logic_vector(output);
end architecture;
However, this was not supported in Vivado 2 years ago. Don't know if it's supported now.

Related

Using generic for a type in a port entity in VHDL 93

I have a type declared in a package which I use in the port entity:
Package:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
package ports_type is
constant N: positive := 3;
type t_ports_types is array(0 to N-1) of std_logic_vector (N-1 downto 0);
end package ports_type;
Module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.ports_type.all;
entity ports is
generic (
N : positive := 3
);
port(
inp : in t_ports_types;
outp : out std_logic_vector(N-1 downto 0)
);
end ports;
architecture Behavioral of ports is
begin
process(inp)
variable result : std_logic;
begin
for y in 0 to N-1 loop
result := '0';
for x in 0 to N-1 loop
result := result or inp(x)(y);
end loop;
outp(y) <= result;
end loop;
end process;
end Behavioral;
The problem is that I have to manually change the value of Nin the package, which is a problem if I want to instantiate the ports entity in another module, like:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.ports_type.all;
entity ports_top is
generic (
N : positive := 3
);
Port (
A : in std_logic_vector(N-1 downto 0);
B : in std_logic_vector(N-1 downto 0);
C : in std_logic_vector(N-1 downto 0);
Outp : out std_logic_vector(N-1 downto 0)
);
end ports_top;
architecture Behavioral of ports_top is
signal s_ports : t_ports_types;
begin
s_ports(0) <= A;
s_ports(1) <= B;
s_ports(2) <= C;
ports_0: entity work.ports(Behavioral)
generic map (
N => N
)
port map(
inp => s_ports,
outp => Outp
);
end Behavioral;
The goal would be to only change N in the top module and not in the package as well. Is that possible with vhdl'93?
Thanks for the help.

How can i use generic array type with modelsim?

It's my first question here, I really hope you can help me
Edit 03 December 2019 :
We resolved our problem with the declaration type, but now, we have other problem
So, when I tried to run my testbench for the simulation on modelsim, we got these errors.
# Conv_rev3_run_msim_rtl_vhdl.do
# invalid command name "Conv_rev3_run_msim_rtl_vhdl.do"
Here our package for the declaration of type
-- synthesis VHDL_INPUT_VERSION VHDL_2008
library ieee;
use ieee.std_logic_1164.all;
package conv_p is
type slv_array_t is array (natural range <>) of std_logic_vector;
end package;
The entity of the main files
entity Conv_rev3 is
generic(
LEN : natural := 8; -- Bits in each input
NUM : natural := 4); -- Number of inputs
port(
clk : in std_logic;
D : in conv_p.slv_array_t(0 to NUM - 1)( LEN - 1 downto 0);
W : in conv_p.slv_array_t(0 to NUM - 1)( LEN - 1 downto 0);
z_o : out std_logic_vector(LEN*2 - 1 downto 0));
end entity;
Here a sample of our testbench :
LIBRARY IEEE;
USE ieee.std_logic_1164.all;
USE work.conv_p;
ENTITY Conv_rev3_vhd_tst IS
END Conv_rev3_vhd_tst;
ARCHITECTURE Conv_rev3_arch OF Conv_rev3_vhd_tst IS
-- constants
-- signals
SIGNAL clk : STD_LOGIC;
SIGNAL D : conv_p.slv_array_t(0 to 3)(7 downto 0);
SIGNAL W : conv_p.slv_array_t(0 to 3)(7 downto 0);
SIGNAL z_o : STD_LOGIC_VECTOR(15 DOWNTO 0);
COMPONENT Conv_rev3
PORT (
clk : IN STD_LOGIC;
D : IN conv_p.slv_array_t(0 to 3)(7 downto 0);
W : IN conv_p.slv_array_t(0 to 3)(7 downto 0);
z_o : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
);
END COMPONENT;
Best Regards
In your first problem, it is highly probable that the entity name that you have specified in your code is wrong and that is why it is unable to find that entity and shows that error. And thus it goes without saying that if it hasn't even found the entity, then it won't be able to compile it.
Now I don't think that there is need to answer the second question because there must be some error in it.

vhdl generic parameters used by other generic parameters (error: generic "parameter" is not visible here)

In Verilog, I can define a parameter and then use it to define another parameter. For example:
module stuff1 #(
parameter AW = 16,
parameter DW = 16,
parameter FW = AW + DW + 2,
) (
input wire [AW-1:0] adr,
input wire [DW-1:0] dat,
output wire [FW-1:0] fifo
);
endmodule
How can I do something similar in VHDL generic? Example:
library ieee;
use ieee.std_logic_1164.all;
entity stuff1 is
generic(
AW : integer := 15;
DW : integer := 15;
FW : integer := AW + DW + 2
);
port(
adr : in std_logic_vector(AW-1 downto 0);
dat : in std_logic_vector(DW-1 downto 0);
fifo : out std_logic_vector(FW-1 downto 0)
);
end entity;
architecture rtl of stuff1 is
begin
end architecture;
When I try to compile this code, I get the following error in VHDL:
..\..\simtools\ghdl\bin\ghdl.exe -a bus_direct_server.vhdl
stuff1.vhdl: generic "aw" is not visible here
stuff1.vhdl: generic "dw" is not visible here
I'm wondering, is this possible in VHDL to automatically calculate FW parameter from AW and DW? or was Verilog more snazzy on this one occasion?
I don't know if trick will pass synthesis, but it works in GHDL simulator. First create a package with function to calculate fw from aw and dw parameters:
library ieee;
use ieee.std_logic_1164.all;
package pkg_stuff1 is
function fw_calc (aw: natural; dw: natural) return natural;
end package;
package body bus_direct is
function fw_calc (aw: natural; dw: natural) return natural is
begin
return dw + aw + 2;
end function;
end package body;
Once we have the package setup, then its a matter of using it:
library ieee;
use ieee.std_logic_1164.all;
using work.pkg_stuff1.all;
entity stuff1 is
generic(
AW : integer := 15;
DW : integer := 15
);
port(
adr : in std_logic_vector(AW-1 downto 0);
dat : in std_logic_vector(DW-1 downto 0);
fifo : out std_logic_vector(fw_calc(aw, dw)-1 downto 0)
);
end entity;
architecture rtl of stuff1 is
begin
end architecture;
Why just you do you not do it like:
library ieee;
use ieee.std_logic_1164.all;
entity stuff1 is
generic(
AW : integer := 15;
DW : integer := 15;
);
port(
adr : in std_logic_vector(AW-1 downto 0);
dat : in std_logic_vector(DW-1 downto 0);
fifo : out std_logic_vector(AW+DW+1 downto 0)
);
end entity;
architecture rtl of stuff1 is
begin
end architecture;
I assume that there is a relationship between the input and output vectors that you want to keep. It seems like bad practice to have generic parameters with dependencies on other ones.

Error (10482): VHDL error: object "select_vector" is used but not declared

I dont know why I am getting this error (Error (10482): VHDL error at SWSelectorVHDL.vhd(11): object "select_vector" is used but not declared). Please point out what do I need to change..
Here is my code
library ieee;
use ieee.std_logic_1164.all;
entity SWSelectorVHDL is
generic(
NUM : std_logic_vector(2 downto 0) := "000"
);
port(
selector : in select_vector(7 downto 0);
rq : in std_logic_vector(7 downto 0);
own : out std_logic_vector(7 downto 0)
);
end entity SWSelectorVHDL;
architecture RTL of SWSelectorVHDL is
begin
gen_req : for i in 0 to 7 generate
requests(i) <= rq(i) when (selector(i) = NUM) else '0';
end generate;
end;
I don't think "select_vector" is a valid type for your input port "selector". I guess it should be "std_logic_vector(7 downto 0)"
or if "select_vector" is valid type then you need to include the package where you have declared the type "select_vector".

VHDL typecast signed to std_logic_vector

I am looking at this example and below answer which is a nice solution to produce two's complement:
library ieee;
use ieee.numeric_std.all;
entity twoscomplement is
generic
(
Nbits : positive := 8
);
port
(
A : in unsigned (Nbits-1 downto 0);
Y : out signed (Nbits downto 0)
);
end entity twoscomplement;
architecture a1 of twoscomplement is
begin
Y <= -signed(resize(A, Y'length));
end architecture;
I want to use the said example to have two's complement and then make a "16-bit subtractor". The code will look like the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity subtractor_16bit is
Port ( a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end subtractor_16bit;
architecture Behavioral of subtractor_16bit is
component fulladder_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end component;
component twoscomplement is
Port (
A : in unsigned (15 downto 0);
C : out signed (15 downto 0)
);
end component;
signal n1 : STD_LOGIC_VECTOR(15 downto 0);
begin
twoscomplement_1: twoscomplement port map (a => a ,c => n1); --ERROR
fulladder_16bit_1: fulladder_16bit port map (a => a, b => n1, sum => sum , cin => cin, cout => cout, over => over);
end Behavioral;
However, I am receiving an error saying:
Error: type error near a; current type std_logic_vector; expected type unsigned.
Kindly help me to solve this problem.
As nobody is answering this and nobody is down voting it, I will answer.
Look at the error
Error: type error near a; current type std_logic_vector; expected type unsigned.
Now look at entity subtractor_16bit.
[...]
entity subtractor_16bit is
Port ( a : in STD_LOGIC_VECTOR(15 downto 0);
[...]
component twoscomplement is
Port (
A : in unsigned (15 downto 0);
[...]
twoscomplement_1: twoscomplement port map (a => a ,c => n1);
[...]
What do you see? twoscomplement expects an unsigned, while a is std_logic_vector! Just like the error says.
std_logic_vector and unsigned are two separate types. As VHDL is a strongly typed language, you cannot just put the data from one type to another. You need to use type conversion.
For unrelated types, you should implement a type conversion function. Or functions, if you want bidirectional conversion. E.g.
function (input : type_a) return type_b;
But in this case, std_logic_vector and unsigned have the same underlying type, std_logic. (std_ulogic actually since VHDL-2008 I believe.)
In that case you can convert from one type to another explicitly. E.g.
signal a_u : unsigned(y downto 0);
signal a_slv : std_logic_vector(y downto 0);
begin
a_u <= unsigned(a_slv);
Next, your not instantiating the twoscomplement component properly. The entity has a generic Nbits. By default you set it to 8. But in your architecture Behavioral of subtractor_16bit, you feed it with 16 bits, without changing the generic value. That doesn't work.
Also: twoscomplement has two ports: A and Y. But in subtractor_16bit you start using A and C. That's bad coding practice.
Finally, you can drop the component declarations. Just instantiate the entities from the library. E.g.
twoscomplement_1: entity work.twoscomplement [...]
So, subtractor_16bit should look something like this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity subtractor_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end entity;
architecture structural of subtractor_16bit is
use IEEE.NUMERIC_STD.ALL;
signal n1 : signed(a'range);
begin
twoscomplement_1: entity work.twoscomplement
generic map(
NBits => a'length
)
port map (
a => unsigned(a),
y => n1
);
fulladder_16bit_1: entity work.fulladder_16bit
port map (
a => a,
b => std_logic_vector(n1),
sum => sum,
cin => cin,
cout => cout,
over => over
);
end architecture;
...
HOWEVER this will still not work.
As you see on your entity twoscomplement, port A has a size of NBits, and port Y has a size of NBits+1. That is because you seem to want to keep 16-bit value precision. So when converting unsigned to signed, you need to add a 17th bit for the sign. As a result, the rest of you code will need to be modified!
.... But this can be fixed a different way. I will learn you something about two's complement: -a = not(a) + 1.
Proof (Take 4 bits signed precision):
0 = b'0000 => -0 is not(b'0000)+1 = b'1111'+1 = b'0000'
7 = b'0111 => -7 is not(b'0111)+1 = b'1000'+1 = b'1001'
-6 = b'1010' => 6 is not(b'1010)+1 = b'0101'+1 = b'0110'
See?
So now I will solve your puzzle for you:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity subtractor_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end entity;
architecture structural of subtractor_16bit is
begin
fulladder_16bit_1: entity work.fulladder_16bit
port map (
a => a,
b => not(b),
sum => sum,
cin => '1',
cout => cout,
over => over
);
end architecture;
You will still need to change/fix the cout and over behavior...

Resources