I would like to know if there is a way to access an entities default generic values or an entities architectures constants during synthesis.
This is out of curiosity (and I want to implement something like that).
Possible Usecases
1) generating Testbench for the default entity:
entity testme is
generic(outputs:integer:=4);
ports(output:out bit_vector(0 to outputs);
end entity;
in the testbench i need to generate a signal whcih can be connected to output, without knowing the generics value there is no way of doing so.
2) I would like to know the actual size I use when instantiating Blockram. On FPGAs there is Blockram, fixed chunks of ram one can use, if one needs more ram than is available in one block multiple blocks are combined. Varying with the technology the size of the available blockrams can change. Thus I write an entity with two generic parameters memory and technology that implements my memory with the least Blockrams possible. This might lead to the Memory being larger than requested. If I now have another entity that needs the size of the memory to fully utilitize it (i.e. circular buffer controller), I have to supply it the actual size of the memory allocated.
You have to push these things downwards from the top (ie from the testbench). It is not possible to inspect a lower-level block (although I guess you could bring a signal out and back up to the top!)
you can use unconstraint types, e.g.:
entity example
port(
i: std_logic_vector;
o: std_logic_vector
);
in the testbench you add defined vectors e.g.:
....
signal i,o: std_logic_vector(10 downto 0);
begin
uut: example
port map(
i => i,
o => o
);
Related
Is there some way to define an alias, function or subtype in a package to define syntactic sugar around constrained vector declaration?
I often declare port and signals in VHDL as std_logic_vector(N - 1 downto 0). I would like some syntactic sugar around this. something similar to this:
context work.common;
entity X is
generic(
byteSize : integer := 8
);
port(
DataIn : in logic_bus(byteSize);
DataOut : out logic_bus(byteSize)
);
end entity;
architecture X_arch of X is
signal DataSignal : logic_bus(byteSize);
begin
DataOut <= DataSignal;
DataSignal <= DataIn;
end architecture;
I would like to have this syntactic sugar defined all over my project, i.e., avoid defining a subtype in the architecture if possible. I'm very confused with the usage of open, natural range <>, the difference between type and subtype, and what kind of things functions can return.
regarding constraints inference
I would like to stress that I'm looking for a way to abstract away the definition of similar vector constraints.
The proposal to leave my vector completely unconstrained, while a clever workaround, has strings attached to it that I would like to avoid :
It is not compatible with type casting see here.
It doesn't communicate the relationship between ports (for instance it doesn't communicate that DataIn and DataOut are supposed to be the same size)
It risks to allow badly sized bus designs to pass synthesis by mistake (accidental meaning)
For this reasons, my workplace coding style has banned unconstrained types in ports in favor of generics. Thank you for your understanding.
I assume that you want logic_bus(x) to be some kind function/alias/subtype to abstract away std_logic_vector(N-1 downto 0), working around constrained vector declaration.
VHDL have a quite small user base in terms of numbers. So much of what of the language you can use is highly tool dependent. Make sure you have read up on the supported features of vhdl-2008 for your development environment. As a main user of Xilinx UG901 is my go to for Vivado. Even though a feature is supported you might sometime be required to add an keep attribute to make it not be optimized away in synthesis.
Since a few years back Vivado have a quite full support for vhdl-2008
Unbounded arrays have been supported for even longer.
Generic package have just seen the light of day and seems to be a bit different in Mentor and Xilinx interpretation, but you can make it implement.
Generic types is a part of the language, but I have never got it to work the way I needed it to. (I always try to keep to sl and slv in entity)
As I'm not sure about your environment I can only answer for mine.
Full VHDL-2008 support is assumed
Unconstrained slv
Working around constrained vector definition by avoiding it.
entity X is
port(
DataIn : in std_logic_vector;
DataOut : out std_logic_vector
);
end entity;
architecture X_arch of X is
-- guiding DataSignal with to have a relationship with some signal is usally needed
signal DataSignal : std_logic_vector(DataIn'range);
begin
assert DataIn'length = DataOut'length
report "length missmatch of input and output data"
severity ERROR;
DataOut <= DataSignal;
DataSignal <= DataIn;
end architecture;
Asserts will need to be enabled for synthesis, ether for the run or appended to the synthesis strategy. (see ug901, for Xilinx or check vendor docs)
Unconstrained vectors need to be constrained at the top level. Some times a bit flakey in multi layered component designs. Signals are usually a bit iffy about how they get inferred.
Higher dimensional data can also be unconstrained
type slv_2d is array(natural range <>) of std_logic_vector;
-- Constrain multiple dimensions at once
-- (this might still be broken in GHDL, open issue last time i checked)
-- synthesis/implementation in Vivado works
-- simulates in Modelsim/Questa works
signal test_signal : slv_2d(0 to 5)(7 downto 0);
-- constants can de inferred from assignment
constant test_signal : slv_2d := ("001", "010", "011", "100" );
subtype I usually think about as limiting a type further.
-- integer may be any value within -2147483648 to +2147483647.
-- I might have an issue or a design restriction to highlight
-- I usually don't use subtypes
subtype my_range is integer range 0 to 255;
-- Will throw error if outside of range 0 to 255.
variable cnt : my_range := 0;
I really recommend reading ug901 "Supported VHDL-2008 Features" section of the latest release, even if you don't work with Xilinx. Dolus have a few really good writeups on vhdl-2008 that might strike your fancy and will talk about related features to what you are looking for.
I'm trying to build a little game in VHDL and, therefore, I need to use two matrices of std_logic elements. Here is how I initialized my two matrices :
type matrix_type is array (0 to 7) of std_logic_vector(7 downto 0);
shared variable matrix : matrix_type := (
others => (others => '0')
);
shared variable frozen : matrix_type := (
others => (others => '0')
);
But this takes A HUGE amount of blocks of logic cell to be done. Without doing this, I am only using 75/160 logic elements, while when I am doing this, I'm using 207/160 logic elements! Quartus can't even compile this code because of the amount of logic elements that are used.
Why is this so? How is that possible that initializing such matrices needs so many logic elements? Do you have a solution to use less of them, or to initialize them another way?
Thank you!
Because probably you are using slices of the fpga to store the initial value.
The best way to do store values on a fpga is use a block ram. You can infer it with vhdl code or create the memory with the fpga vendor tool and connect it.
a real junior question with hopefully a junior answer, regarding one of the main assignments of VHDL (concurrent selective assignment) can anyone explain what a VHDL compiler would synthesise the following description into?
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY Q2 IS
PORT (a,b,c,d : IN std_logic;
EW_NS : OUT std_logic
);
END ENTITY Q2;
ARCHITECTURE hybrid OF Q2 IS
SIGNAL INPUT : std_logic_vector(3 DOWNTO 0);
SIGNAL EW_NS : std_logic;
BEGIN
INPUT <= (a & b & c & d); -- concatination
WITH (INPUT) SELECT
EW_NS <= '1' WHEN "0001"|"0010"|"0011"|"0110"|"1011",
'0' WHEN OTHERS;
END ARCHITECTURE hybrid;
Why do I ask? well I have previously gone about things the wrong way i.e. describing things on VHDL before making a block diagram of the components needed. I would envisage this been synthed as a group of and gate logic ?
Any help would be really helpful.
Thanks D
You need to look at the user guide for your target FPGA, and understand what is contained within one 'logic element' ('slice' in Xilinx terminology). In general an FPGA does not implement combinatorial logic by connecting up discrete gates like AND, OR, etc. Instead, a logic element will contain one or more 'look-up tables', with typically four (but now 6 in some newer devices) inputs. The inputs to this look up table (LUT) are the inputs to your logic function, and the output is one of the outputs of the function. The LUT is then programmed as a ROM, allowing your input signals to function as an address. There is one ROM entry for every possible combination of inputs, with the result being the intended logic function.
A function with several outputs would simply use several of these LUTs in parallel, with the same inputs, one LUT for each of the function's outputs. A function requiring more inputs than the LUT has (say, 7 inputs, where a LUT has only 4), simply combines two LUTs in parallel, using a multiplexer to choose between the output of the two LUTs. This final multiplexer uses one of the input signals as it's control, and again every possible combination of inputs is accounted for.
This may sound inefficient for creating something simple like an AND gate, but the benefit is that this simple building block (a LUT) can implement absolutely any combinatorial function. It's also worth noting that an FPGA tool chain is extremely good at optimising logic functions in order to simplify them, and to better map them into the FPGA. The LUT provides a highly generic element for these tools to target.
A logic element will also contain some dedicated resources for functions that aren't well suited to the LUT approach. These might include dedicated carry chains for adders, multiplexers for combining the output of several LUTS, registers (most designs are synchronous). LUTs can also sometimes be configured as small shift registers or RAM elements. External to the logic elements, there will be more specific blocks like large multipliers, larger memories, PLLs, etc, none of which can be as efficiently implemented using LUT resource. Again, this will all be explained in the user guide for your target FPGA.
Back in the day, your code would have been implemented as a single 74150 TTL circuit, which is a 16-to-1 mux. you have a 4-bit select (INPUT), and this selects one of 16 inputs to the chip, which is routed to a single output ('EW_NS`). The 74150 is obsolete and I can't find any datasheets, but it's easy to find diagrams of what an 8-to-1 mux looks like (here, for example). The 16->1 is identical, but everything is wider. My old TI databook shows basically exactly the diagram at this link doubled up.
But - wait. Your problem is easier, because you're not routing real inputs to the output - you're just setting fixed data values. On the '150, you do this by wiring 5 of the 16 inputs to 1, and the remaining 11 to 0. This makes the logic much easier.
The 74150 has basiscally exactly the same functionality as a 4-input look-up table (where the fixed look-up data is the same as fixed levels at the '150 inputs), so it's trivial to implement your entire circuit in a single LUT in an FPGA, as per scary_jeff's answer, rather than using a NAND-level implementation. In a proper chip, though, it would be implemented as a sum-of-products, or something similar (exactly what's in the linked diagram). In this case, draw a K-map and find a minimum solution. My 2 minutes on the back of an envelope comes up with three 3-input AND gates, driving a 3-input OR gate. I'll leave it as an exercise to you to check this :)
I need to implement a few processes which are working parallel. I'm very new to vhdl and can't figure out how to make a architecture without an entity? do I really need a entity for a architecture?
architecture architecture_test of ????? is
shared variable test: std_ulogic_vector(7 downto 0);
process1 : process is
begin
-- do something
end process process1;
process2 : process is
begin
--do something
end process process2;
process3 : process is
begin
--do something
end process process3;
end architecture architecture_test
Or is there another way to do that?
An entity is a primary unit representing the interface to a design specification implemented in an architecture, a secondary unit. An entity and it's selected architecture together implement a block, which can be instantiated by component, direct entity instantiation, or configuration.
Is it possible to simulate something without an entity? Not with a VHDL simulator. It's possible to have an empty entity:
entity foo is
end entity;
architecture fum of foo is
begin
end architecture;
(This should actually analyze, there's no requirement an architecture have any concurrent statements either.)
A testbench is generally an entity providing no interfaces (or sometimes just a generic interface), and an architecture that contains concurrent statements (and processes are concurrent statements).
So, you need an entity, it doesn't need to provide an interface. An entity declaration also provides a declarative region where you can supply declarations necessary for declarations in the architecture body's declarative region.
It's called a testbench because it has no practically value in hardware. It's only useful for testing one or more design specifications that do have interfaces (and can be synthesized) or for executing a VHDL design specification (your multiple processes in an architecture body) on a simulator.
The length of simulation time a collection of processes can run is bounded by two things. First there is no standard for how many delta simulation cycles can run without advancing simulation time.
There are simulators that can execute an unlimited number of delta cycles. Early VHDL simulators had consecutive delta cycle limits measured in hundreds. It's common to use a delta cycle limit of 5,000 (Modelsim's default).
The other limit is the duration of the Time variable, which can be expanded optionally by some simulators by setting the resolution limit and constraining the minimum size of Time physical unit appears in a design description, in effect scaling Time to run longer at a coarser granularity.
If Time advances in a simulation it will eventually run up against Time'HIGH and stop and implementing a resolution limit is optional for an implementation.
In effect trying to write the equivalent of a daemon in VHDL is guaranteed to be non-portable. VHDL isn't a general purpose parallel programming language, wiki articles stating to the contrary, aside.
It's also possible to write a VHDL design specification that memory leaks. There is no requirement for garbage collection.
I'm very new to vhdl and can't figure out how to make a architecture without an entity? do I really need a entity for a architecture?
Yes you do.
The entity describes how to interface to the architecture. The architecture describes what goes on inside the entity.
To give a C-code metaphor... given this code:
int some_func(int x, int y)
{
return x*x+y*y;
}
You are asking:
"Can I have this
{
return x*x+y*y;
}
without this:
int some_func(int x, int y)
"
As David notes, you can have an entity without any interface to hold your architecture, but you still have to have one. (In the same way as you still have to have at least void main(void) in C*.)
*(Yes I know main is supposed to return an int, but the example falls over then!)
Questions:
Is there a more appropiate "supertype" to signed and unsigned than std_logic_vector (regarding my case)?
Is it ok to define an Input as (subtype of) Integer or is it better to define it as bitvector? (Are there any Issues with the Integer approach)
When should I use resolved or unresolved logic for the Inputs/Outputs off an Entity?
Resolved for Bus drivers (because of the "high Z drivers") otherwise unresolved?
Always resolved so a bus can be driven/used as input (this seems wrong, because when would I use unresolved then?)
Actual Case:
I am declaring an entity and am wondering for the right types for the inputs and outputs.
Lets assume I am constructing a dynamic width equal. It compares the first n Bits of two Inputs for equality.
The entity definition would be:
entity comparisonDynWidth is
generic(
width : positive;
min_width : positive;
-- when the tools suport vhdl2008 enough
-- reason for both signed/unsigned => std_logic inputs
--function compareFunc (x: in std_logic_vector; y: in std_logic_vector) return std_logic
);
port (
left, right : in std_logic_vector(width-1 downto 0);
widthControl: in natural range 0 to width-min_width;
result : out std_logic / std_ulogic ??
);
I chose std_logic_vector as Input since I want it to look the ports like a generic less than comparator as well, for which signedness matters and which can have signed and unsigned inputs.
since it is easier for me to define the width as an integer I did so.
Is there a more appropiate "supertype" to signed and unsigned than
std_logic_vector (regarding my case)?
Not sure what you mean, but you have no choice - signed and unsigned are defined in the standard.
Is it ok to define an Input as (subtype of) Integer or is it better to
define it as bitvector? (Are there any Issues with the Integer
approach)
Integers will flag errors if you go outside their range. vectors (signed and unsigned) will wrap around. Which is "correct" depends on what you want and how you feel about coding explicit wrap-around if you want it with integers.
When should I use resolved or unresolved logic for the Inputs/Outputs
off an Entity?
If you stick to:
only using resolved types for the top level IO ports (i.e. the actual pins of the device)
using unresolved types internally
you will be able catch errors involving multiple drivers on a signal with a detailed error-message at elaboration-time. This can be preferable to chasing down Xs in your waveforms at simulation-time.
There are no internal tri-state buses internally to most technologies these days, so you can't have multiple drivers, so there's no need for resolved signals inside the device. IO pins (almost?) always have tri-stateble drivers, so the use of a resolved type is appropriate, and the driving of a 'Z' can be used to infer that behaviour.
std_logic_vector is a good choice in your case (and in most cases in an entity, as it represents hardware situation best... e.g. with use of 'U' and 'Z' and so on)
the use of integer in an entity is ok as long as it is not the top-level entity. in top level entities, the exclusive use of std_logic(_vector) is recommended.
most tools report multi-driver situations anyway... the use of resolved types is therefore ok.