VHDL : Array of records with variable field length size - vhdl

I am trying to implement a generic std_logic_vector data logger for a testbench. This component would generate an output signal for each signal logged.
Each signal should be of the type t_probe
type t_probe is record:
min_delay : time;
max_delay : time;
num_exp_words : integer;
trig_lvl : std_logic;
data: std_logic_vector;
done : std_logic;
end record;
Would like to have a probe array record type:
type t_probe_array is array(0 to c_n_probes - 1) of t_probe;
Now , I have the problem of declaring a st_probe signal type which has the "data" field constrained:
signal coarse_probe : t_probe
Will obviously crash when launching simulation. Can anyone indicate how to define and initialize such an array?
thanks!

It is assumed that this is required for simulation only?
Then you could work with variables and access types (probably the workaround #Tricky was mentioning above?).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tst014 is
end entity tst014;
architecture sim of tst014 is
type pstring is access string;
type rec is record
ps : pstring;
end record;
type rec_array is array(natural range <>) of rec;
begin
p : process
variable recs : rec_array(1 to 3);
begin
recs(1) := (ps => new string'("Hello"));
recs(2) := (ps => new string'("World!"));
report "recs(1).ps.all = " & recs(1).ps.all severity note;
report "recs(2).ps.all = " & recs(2).ps.all severity note;
end process p;
end architecture sim;

Related

Type of identifier does not agree with its usage as "boolean" type - VHDL in Quartus

I'm developing a simple buffering system in VHDL. I get the error I mentioned in the title for "empty" whenever I try to compile. I don't know why it won't let me invert a std_logic type. I've also been getting errors about the comparisons. For some reason, it doesn't recognize the ">" and "<" operators on status_as_int and the thresholds.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY Buffer_Controller is
port (
empty : in std_logic;
full : in std_logic;
filling_status : in std_logic_vector(14 downto 0);
read_thresh : in integer;
write_thresh : in integer;
read_now : out std_logic;
write_now : out std_logic
);
END ENTITY;
ARCHITECTURE ctrl of Buffer_Controller is
signal status_as_int : integer;
BEGIN
status_as_int <= to_integer(unsigned(filling_status));
read_now <= '1' when (NOT(empty) AND status_as_int > read_thresh) else
'0';
write_now <= '1' when (NOT(full) AND status_as_int < write_thresh) else
'0';
END ARCHITECTURE;
empty and full are not booleans. They're std_logic, which is a user defined type (defined in the ieee.std_logic_1164 library). That's not a boolean.
Yes, you can invert them, but the result will still be std_logic. (The overloaded implementation of NOT for std_logic is also defined in the ieee.std_logic_1164 library).
To convert to boolean, You need to compare them to something that can be interpreted as std_logic, e.g.
read_now <= '1' when
empty = '0' AND
status_as_int > read_thresh
else '0';

Passing generic to generic package to set port in VHDL

I’m looking at a generic package example in eda playground (https://www.edaplayground.com/x/6Mpm) and I’m trying to do something similar. I’m trying to get an integer from the top level through the generic field in the entity, and then pass the generic value on to the generic package to set the size of a part of a record. This record type is then to be used in the port of the entity where the generic came from.
Is this possible or do I have to hard code the number in the package declaration as in the example? Trying to declare the package in the entity gives me error proclaiming that the port can’t see the record type. Declaring the package normally as in the example mean that the package can’t see the generics in the entity.
I have been meaning to use a constant package to circumvent the “problem”, but I’m wondering if it is possible to do this using generics and a generic package without hard coding the numbers. This is so that I don’t have to remember to change the constant package when I’m reusing the module.
Package:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- pps_control_generic_pkg
package pps_control_generic_pkg is
generic(
-- Size of register. Max 32. Default 32
g_reg_size : integer := 32
);
type t_apb3_pif2core is record
rw_config : std_logic_vector(g_register_size-1 downto 0);
rw_config_we : std_logic;
end record;
type t_apb3_core2pif is record
rw_config : std_logic_vector(g_register_size-1 downto 0);
end record;
end package pps_control_generic_pkg;
Code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- Trying to declare this correctly
-----------------------------------------------------------
package pps_control_pkg is new work.pps_control_generic_pkg
generic map(
g_reg_size => g_reg_size
);
use work.pps_control_pkg.all;
-----------------------------------------------------------
entity pps_control_core is
generic(
-- Size of register. Default 32
g_register_size : integer := 32;
);
port(
csi_sys_clk : in std_logic;
rsi_sys_reset : in std_logic;
-- Interface to access register
p2c : in t_apb3_pif2core;
c2p : out t_apb3_core2pif;
pps_in : in std_logic;
pps_out : out std_logic;
pps_en_n : out std_logic
);
end entity;
architecture rtl of pps_control_core is
...
begin
...
end rtl;
An unconstrained composite element of a record type provided with a record constraint works. Credit goes to Tricky for mentioning the solution and user1155120 for typing it out.
library ieee;
use ieee.std_logic_1164.all;
package pps_control_generic_pkg is
type t_apb3_pif2core is record
rw_config : std_logic_vector;
rw_config_we : std_logic;
end record;
type t_apb3_core2pif is record
rw_config : std_logic_vector;
end record;
end package pps_control_generic_pkg;
library ieee;
use ieee.std_logic_1164.all;
use work.pps_control_pkg.all;
entity pps_control_core is
generic(
g_register_size : integer := 32;
);
port(
csi_sys_clk : in std_logic;
rsi_sys_reset : in std_logic;
p2c : in t_apb3_pif2core
(arw_config(g_register_size-1 downto 0));
c2p : out t_apb3_core2pif
(aro_config(g_register_size-1 downto 0));
pps_in : in std_logic; --! External pps signal
pps_out : out std_logic; --! Outputted pulse
pps_en_n : out std_logic --! Enable pps signal to instrument
);
end entity;

VHDL-2008 hierarchical signal access to array

I am trying to access an array via VHDL-2008 hierarchical names. I am able to access the whole array, but when I try to access individual array elements, I get the compilation error:
ACOM: Error: COMP96_0015: tb.vhd : (13, 43): ':' expected.
Is it possible to access individual array elements? What is the correct syntax?
Here's my code:
DUT
library ieee;
use ieee.std_logic_1164.all;
entity dut is
end entity dut;
architecture rtl of dut is
type t_data is array (natural range <>) of std_logic_vector(7 downto 0);
signal s_data : t_data(0 to 15) := (others=>(others=>'1'));
begin
--don't care
end architecture rtl;
TB
library ieee;
use ieee.std_logic_1164.all;
entity tb is
end entity tb;
architecture sim of tb is
signal s_data_0 : std_logic_vector(7 downto 0);
begin
s_data_0 <= << signal i_dut.s_data(0) : std_logic_vector(7 downto 0) >>;
i_dut : entity work.dut;
end architecture sim;
The error message from another simulator explains the problem:
** Error: external_index.vhd(23): (vcom-1307) External name must denote an entire object, not a slice or indexed name of an object.

Passing Generics to Record Port Types

I did recently start to use records for my port definitions, especially if I want to group signals that belong to a certain interface. However, the problem I'm facing here is that I cannot pass, say the width of a std_logic_vector, to the entity by means of a generic. So what I basically want to do is the following:
library ieee;
use ieee.std_logic_1164.all;
use work.math_pkg.all;
package fifo_pkg is
type fifo_in_type is record
data_in : std_logic_vector(DATA_WIDTH_??- 1 downto 0);
rd : std_logic;
wr : std_logic;
end record;
type fifo_out_type is record
data_out : std_logic_vector(DATA_WIDTH_?? - 1 downto 0);
empty : std_logic;
full : std_logic;
end record;
component fifo is
generic
(
MIN_DEPTH : integer;
DATA_WIDTH : integer
);
port
(
clk : in std_logic;
res_n : in std_logic;
i : in fifo_in_type;
o : out fifo_out_type
);
end component fifo;
end fifo_pkg;
So the ideal solutions would be when i can use the same generic in my record as i did in the entity. (So that DATA_WIDTH is the same as DATA_WIDTH_??). I know that this should work somehow with vhdl 2008, however my quartus II 11sp1 does not support generics in records.
Is there an elegant way to achieve that kind of "generic passing" that is synthesizable? I know that one could just store a constant in the package, but then I cannot use the same fifo package to instantiate several fifo's with different widths.
Thanks a million,
T
Can you use type generics with Quartus?
Then you leave the type completely unspecified, so that you can create a FIFO of integers or any other data type:
package fifo_pkg is
generic (type element_type);
type fifo_in_type is record
data_in : element_type;
rd : std_logic;
wr : std_logic;
end record;
type fifo_out_type is record
data_out : element_type;
empty : std_logic;
full : std_logic;
end record;
component fifo is
generic
(
MIN_DEPTH : integer;
DATA_WIDTH : integer
);
port
(
clk : in std_logic;
res_n : in std_logic;
i : in fifo_in_type;
o : out fifo_out_type
);
end component fifo;
end fifo_pkg;
Then when you want to use it:
package wide_fifo_pkg is new fifo_pkg
generic map (type => std_logic_vector(31 downto 0));
and then you can use fifo_in_type and fifo_out_type:
signal i : fifo_in_type;
If you have more than one FIFO in a design unit you can create several versions of the package and use the package prefix to get the right type:
package narrow_fifo_pkg is new fifo_pkg
generic map (type => std_logic_vector(3 downto 0));
signal i32 : wide_fifo_pkg.fifo_in_type;
signal i4 : narrow_fifo_pkg.fifo_in_type;
Another VHDL 2008 option: you can have an unconstrained record type:
type fifo_in_type is record
data_in : std_logic_vector;
rd : std_logic;
wr : std_logic;
end record;
which you can then create subtypes of for your various uses:
subtype fifo1_data_type is fifo_in_type(data_in(31 downto 0));
subtype fifo2_data_type is fifo_in_type(data_in(15 downto 0));
No idea if Quartus supports either of those options - please let us know!
Generics in packages is supported in Xilinx's Vivado toolset currently. Ref their document UG901, the section titled "Generics in Packages" for details and a code sample. Need to make sure the source code properties are set up for VHDL-2008, as explained elsewhere in the same document.

Use a generic to determine (de)mux size in VHDL?

I want to use a generic 'p' to define how many outputs a demux will have. Input and all outputs are 1 bit. The outputs, control, and input can be something simple like:
signal control : std_logic_vector(log 2 p downto 0); -- I can use a generic for the log2..
signal input : std_logic;
signal outputs : std_logic_vector(p-1 downto 0);
But what would the mux implementation code be? Is it even possible?
No generics required:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity demux is
port(
control : in unsigned;
input : in std_logic;
outputs : out std_logic_vector
);
end entity demux;
architecture rtl of demux is
-- Check size of input vectors
assert 2**control'length = outputs'length
report "outputs length must be 2**control length"
severity failure;
-- actually do the demuxing - this will cause feedback latches to be inferred
outputs(to_integer(unsigned(control)) <= input;
end architecture;
(Untested, just typed in off the top of my head...)
This will infer latches though - is that what you want?
You need to feed log_p as generic and compute p as you go.
library ieee;
use ieee.std_logic_1164.all;
entity demux is
generic (
log_p: integer);
port(
control : in std_logic_vector(log_p downto 0);
input :in std_logic;
outputs : out std_logic_vector(2**log_p - 1 downto 0)
);
end entity demux;
You need to pass both the number of outputs and the size of the control array as generics, unless you are always using powers of two.
Outside of your (de)mux module (ie: when you instantiate), you can use code to calculate the number of bits for the control bus. I have a function in a common package I use to initialize various configuration constants and generics that get passed to code similar to your (de)mux application:
-- Calculate the number of bits required to represent a given value
function NumBits(val : integer) return integer is
variable result : integer;
begin
if val=0 then
result := 0;
else
result := natural(ceil(log2(real(val))));
end if;
return result;
end;
...which allows you to do things like:
constant NumOut : integer := 17;
signal CtrlBus : std_logic_vector(NumBits(NumOut)-1 downto 0);
my_mux : demux
generic map (
NumOut => NumOut,
NumCtrl => NumBits(NumOut) )
port map (
control => CtrlBus,
...
...

Resources