Can we write to two signals from a port map statement? - vhdl

This is perhaps more of a hypothetical VHDL question as opposed to a real-life/case study question.
Say I have a component declaration as follows...
component my_comp is
port (
A : in std_logic;
--...other input/outputs
B : out std_logic_vector(9 downto 0)
);
end component my_comp;
And within the same entity containing my_comp i have the signals
signal my_comp_full_scale_output : std_logic_vector(9 downto 0);
signal my_comp_8_scale_output : std_logic_vector(7 downto 0);
Is there a way which I can assign these two signals both the value of B in the port map statement of the component instantiation? Something like this maybe...
my_comp_isnt : my_comp
port map (
A => some_signal,
-- other signal assignments
B => my_comp_full_scale_output,
B(9 downto 2) => my_comp_8_scale_output
);
Once again I stress that this is totally playing with VHDL's logic and I am not using this in any design!!! I do know that this can easily be done with an assignment of my_comp_full_scale_output to my_comp_8_scale_output outside of the component instantiation such as below and this is simply a sake of code for code's sake.
my_comp_isnt : my_comp
port map (
A => some_signal,
-- other signal assignments
B => my_comp_full_scale_output
);
my_comp_8_scale_output <= my_comp_full_scale_output(9 downto 2);

No.
1076-2008 - IEEE Standard VHDL Language Reference Manual states:
Each association element in an association list associates one
actual designator with the corresponding interface element in the
interface list of a subprogram declaration, component declaration,
entity declaration, block statement, or package.
So you can only map it once.

Related

Composite Files/ Component Instantiation

I am new(ish) to VHDL. I am trying to understand how to use different component .vhd files to build a complete structure. I am working with a Digilent PmodA7, and want to have two LEDs blink alternately.
What I have tried is Inverter.vhd and LedBlink.vhd
Inverter.vhd:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Inverter is
Port (
Inv_in : in std_logic;
Inv_out : out std_logic
);
end Inverter;
architecture Behavioral of Inverter is
begin
Inv_out <= not Inv_in;
end Behavioral;
Ledblink-1.vhd:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity LedBlink is
Port (
clk: in std_logic;
rst: in std_logic;
led_0 : out std_logic;
led_1 : out std_logic
);
end LedBlink;
architecture Behavioral of LedBlink
-- Inverter.vhd
component Inverter is
port (
Inv_in : in std_logic;
Inv_out : out std_logic
);
end component;
constant CLK_FREQ : integer := 12500000;
constant BLINK_FREQ : integer := 1;
constant CNT_MAX : integer := CLK_FREQ/BLINK_FREQ/2 - 1;
signal cnt : unsigned(24 downto 0);
signal blink_0 : std_logic := '1';
signal blink_1 : std_logic := '1';
begin
process(clk)
begin
if (rst = '1') then
blink_0 <= '0';
blink_1 <= '0';
elsif (clk='1' and clk'event ) then
if cnt = CNT_MAX then
cnt <= (others => '0');
-- blink_1 <= blink_0;
A1: Inverter
Port map ( Inv_in => blink_0, Inv_out => blink_1);
blink_0 <= not blink_0;
else
cnt <= cnt + 1;
end if;
end if;
end process;
led_0 <= blink_0;
led_1 <= blink_1;
end Behavioral;
To understand how to combine files, I want to replace the line
blink_1 <= blink_0;
with a inverter component, ie 7404, but can’t figure out how to do this. The example I am following does not use libraries, so I am most interested in that method, although how to a library to accomplish this would be helpful.
What I have is:
You haven't provided a Minimal, Complete, and Verifiable example with an error. Questions asking for programming help on stackoverflow are practical, not theoretical. This implies a specific problem here.
Analysis (compiling) won't complete o with the missing is in the architecture bodyr or component instantiation in the unlabelled process.
You can't instantiate a component (a concurrent statement) in a process (which can only contain sequential statements). Move the component instance outside the process.
The flip flop output blink_0 is inverter's input. It's output blink_1 is then assigned to blink_0 in the process instead of not blink_0.
blink_1 is only assigned in the elaborated process from the concurrent assignment statement in the architecture of inverter. Each process in a design hierarchy has a driver. The value of multiple drivers are resolved during simulation. The equivalent post synthesis is having two devices driving the same signal and would generate a synthesis error.
Analyze Inverter.vhd before elaborating LedBlink.
cnt must be reset for simulation for the increment, adding 1 to all 'U's will result in all 'U's. You don't use package std_logic_unsigned.
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity ledblink is
port (
clk: in std_logic;
rst: in std_logic;
led_0: out std_logic;
led_1: out std_logic
);
end entity ledblink;
architecture behavioral of ledblink is -- ADDED is
component inverter is
port (
inv_in: in std_logic;
inv_out: out std_logic
);
end component;
constant clk_freq: integer := 12500000;
constant blink_freq: integer := 1;
constant cnt_max: integer := clk_freq/blink_freq/2 - 1;
signal cnt: unsigned(24 downto 0);
signal blink_0: std_logic := '1';
signal blink_1: std_logic := '1';
begin
process (clk) -- contains counter cnt and flip flop blink_0
begin
if rst = '1' then
blink_0 <= '0';
-- blink_1 <= '0'; -- ONLY one driver for blink_1, the component
cnt <= (others => '0'); -- ADD cnt to reset
elsif clk = '1' and clk'event then -- OR rising_edge(clk)
if cnt = cnt_max then
cnt <= (others => '0');
-- blink_1 <= blink_0;
-- a1: inverter MOVED to architecture body
-- port map ( inv_in => blink_0, inv_out => blink_1);
-- blink_0 <= not blink_0; CHANGED
blink_0 <= blink_1;
else
cnt <= cnt + 1;
end if;
end if;
end process;
a1:
inverter -- MOVED to architecture body a place for concurrent statements
port map ( inv_in => blink_0, inv_out => blink_1);
led_0 <= blink_0;
led_1 <= blink_1;
end architecture behavioral;
After which your design analyzes and with a testbench providing clock and reset, elaborates and simulates:
Note cnt only requires a length of 23 (22 downto 0), cnt(24) and cnt(23) are always '0' with a 12.5 MHz clock (12500000).
The question notes "The example I am following does not use libraries, so I am most interested in that method, although how to a library to accomplish this would be helpful."
The first clause isn't exactly accurate. See IEEE Std 1076-2008 13.2 Design libraries:
A design library is an implementation-dependent storage facility for previously analyzed design units. A given implementation is required to support any number of design libraries.
...
There are two classes of design libraries: working libraries and resource libraries. A working library is the library into which the library unit resulting from the analysis of a design unit is placed. A resource library is a library containing library units that are referenced within the design unit being analyzed. Only one library is the working library during the analysis of any given design unit; in contrast, any number of libraries (including the working library itself) may be resource libraries during such an analysis.
Every design unit except a context declaration and package STANDARD is assumed to contain the following implicit context items as part of its context clause:
library STD, WORK; use STD.STANDARD.all;
Library logical name STD denotes the design library in which packages STANDARD, TEXTIO, and ENV reside (see Clause 16). (The use clause makes all declarations within package STANDARD directly visible within the corresponding design unit; see 12.4.) Library logical name WORK denotes the current working library during a given analysis. Library logical name IEEE denotes the design library in which the mathematical, multivalue logic and synthesis packages, and the synthesis context declarations reside (see Clause 16).
A design specification is analyzed into the working library which can be referenced by work and can be implementation dependent method redirected.
There are rules for determining the default binding indication (in lieu of a binding indication in a configuration specification as a block declarative item for a block (including an architecture body) containing a component instantiation or in a configuration declaration (not widely used by synthesis tools, if at all). See 11.7 Component instantiation and 3.4.3 Component configuration.
Without an explicit binding indication as here VHDL relies on a default binding indication (7.3.3 Default binding indication):
In certain circumstances, a default binding indication will apply in the absence of an explicit binding indication. The default binding indication consists of a default entity aspect, together with a default generic map aspect and a default port map aspect, as appropriate.
If no visible entity declaration has the same simple name as that of the instantiated component, then the default entity aspect is open. A visible entity declaration is the first entity declaration, if any, in the following list:
a) An entity declaration that has the same simple name as that of the instantiated component and that is directly visible (see 12.3),
b) An entity declaration that has the same simple name as that of the instantiated component and that would be directly visible in the absence of a directly visible (see 12.3) component declaration with the same simple name as that of the entity declaration, or
c) An entity declaration denoted by L.C, where L is the target library and C is the simple name of the instantiated component. The target library is the library logical name of the library containing the design unit in which the component C is declared.
These visibility checks are made at the point of the absent explicit binding indication that causes the default binding indication to apply.
In this case because inverter was analyzed into the same resource library (an unchanging work) following rule b). You can note that these rules are set up to be as painless as possible. There can be only one primary unit (here an entity) with the same name in a library.
Anyway the point is that there are libraries involved in the original post's code. Here without a configuration specification inverter is expected to be found in library work, regardless of what resource library it references in an implementation defined manor.
It's out of the scope of the vhdl tag and the original post does not identify a particular tool implementation, and VHDL tools are varied in methods for associating working and resource libraries with library logical names.
For a resource library made visible by a library clause a use clause of the form 'use library_logical_name.all;' can make all named entities in a resource library directly visible (See 12.4 Use Clauses, 12.3 Visibility, 12.5 The context of overload resolution). Otherwise a selected name for an instantiated entity can be used (8.3 Selected names).

VHDL: How to handle unconstrained arrays returned by functions as inputs to entity ports?

I'm trying to write some fairly generic VHDL code but I'm running into
a situation where I don't understand the standard well enough. (I'm
using VHDL-2008.)
I have written a function that operates on unconstrained
std_logic_vector(s) and returns an unconstrained
std_logic_vector. However, it seems as if I am unable to use this
function as an input to a port in my entity if I pass two
(constrained) std_logic_vectors to it (see instantiation of test_2 in
my example program). However, for some reason it seems to work ok if I
pass bit string literals to it (see instantiation of test_1).
Can someone explain why the I am not allowed to use the concatenate()
function as an input in the instantiation of test_2 while I am allowed
to use a very similar construct in the instantiation of test_1?
To try the code with ModelSim I compiled it with vcom -2008 unconstrained_example.vhd
-- test entity/architecture
library ieee;
use ieee.std_logic_1164.all;
entity test is
port (value : in std_logic_vector);
end entity;
architecture a of test is
begin
-- Intentionally empty
end architecture;
library ieee;
use ieee.std_logic_1164.all;
-- Test instantiation
entity testit is
end entity;
architecture a of testit is
signal my_constrained_slv1 : std_logic_vector(5 downto 0);
signal my_constrained_slv2 : std_logic_vector(9 downto 0);
function concatenate(value1 : std_logic_vector; value2 : std_logic_vector) return std_logic_vector is
begin
return value1 & value2;
end function;
begin
process begin
-- Using the function in this context seems to work ok
report "Value is " & to_string(concatenate(my_constrained_slv1, my_constrained_slv2));
wait;
end process;
-- This instantiation seems to work
test_1: entity work.test
port map (
value => concatenate("000000", "1111111111"));
-- For this entity instantiation I'm getting an error from ModelSim:
-- ** Error: unconstrained_example.vhd(43): (vcom-1383) Implicit signal in port map for port "value" is not fully constrained.
test_2: entity work.test
port map (
value => concatenate(my_constrained_slv1, my_constrained_slv2));
end architecture;
Your function call is not a conversion function and also does not fulfill the requirements to spare an implicit signal declaration.
VHDL-2008 allows such complex expressions in a port association. The language says, that in such cases, an implicit signal will be created:
If the actual part of a given association element for a formal signal port of a block is the reserved word inertial followed by an expression, or is an expression that is not globally static, then the given association element
is equivalent to association of the port with an anonymous signal implicitly declared in the declarative region that immediately encloses the block. The signal has the same subtype as the formal signal port and is the target of an implicit concurrent signal assignment statement of the form:
anonymous <= E;
where E is the expression in the actual part of the given association element. The concurrent signal assignment statement occurs in the same statement part as the block.
Source: IEEE-1076-2017 Draft 5a
signal temp : std_logic_vector; -- derived from the formal in the port association list
temp <= concatenate(my_constrained_slv1, my_constrained_slv2);
test_2: entity work.test
port map (
value => temp
);
end block;
The problem is, that VHDL needs to infer the type for the implicit signal temp from the formal in the port association list (value : std_logic_vector). It knows, that it is a std_logic_vector, but no constraints are known, due to the unconstrained port.
So if port value in entity test is constrained, it should work:
entity test is
port (
value : in std_logic_vector(15 downto 0)
);
end entity;
I came up with the following workaround which is quite ugly but
fulfills my main criteria that I should not have to manually specify
any widths or repeat any information. By hiding away the call to concatenate in a function I can
reuse the function to get the range further down. A short experiment indicates that Vivado 2015.4 accepts this construct as well.
test_2_helper : block
impure function test_2_help_func return std_logic_vector is
begin
-- This is the only place I have to change in case the assignment has to
-- change in some way. (E.g. use other variables or become more complicated, etc.)
return concatenate(my_constrained_slv1, my_constrained_slv2);
end function;
signal test_2_helper_sig : std_logic_vector(test_2_help_func'range);
begin
test_2: entity work.test
port map (
-- It seems to be syntactically legal to use test_2_help_func(test_2_help_func'range)
-- here. Unfortunately this does not work in simulation. Probably because the
-- test_2_help_func does not have any explicit arguments and this may cause issues
-- with the event driven simulation. As a work around the test_2_helper_sig signal
-- is assigned every clock cycle below instead.
value => test_2_helper_sig);
process
begin
-- Note: If you remove the wait for the clock edge and instead use process(all)
-- test_2_helper_sig does not seem to change during simulation, at least in
-- Modelsim 10.6 where I tested this.
wait until rising_edge(clk);
test_2_helper_sig <= test_2_help_func;
end process;
end block;
Note: This is inspired by the following answer: VHDL - Why does using the length attribute directly on a function produce a warning?

how to have the vdhl code add text to itself

While trying to see if I could come up with a way to make the number of outputs variable by setting a "generic" I came up with the following thought. The idea would be to have a routine in the VHDL code inside the "port" declaration such that the routine would add the text "output(X) : out std_logic_vector(bits-1 downto 0); inside the "port" declaration. Please note that (X) represents the number of the output ports, i.e. output1, output2, etc. The idea being that when the VHDL parser reads the code it would see the required number of outputs when compiled. Is this something that can be done?
If I understood you correctly, you want to do meta-programming and have a generic number of ports. That's not possible in VHDL. However, you can just use a multidimensional array for that:
-- declare array type VHDL-2008-style
-- put this in a package
type slv_array is array(natural range<>) of std_logic_vector;
entity test is
generic (
-- number of outputs, at least one output
num_outputs : positive := 1
);
port (
my_inputs : in std_logic_vector(1 downto 0);
my_outputs : out slv_array(num_outputs - 1 downto 0)(1 downto 0)
);
end entity test;
You would then be able to use the component like this:
comp0 : component test
generic map (
num_outputs => 1
)
port map (
my_inputs => "10",
my_outputs(0) => my_output0
);
comp1 : component test
generic map (
num_outputs => 2
)
port map (
my_inputs => "00",
my_outputs(0) => my_output1
my_outputs(1) => my_output2
);

VHDL - How to Define Port Map of a component with a package in its entity?

I am trying to use packages to shift block of data within different components via top level entity.
I have defined a package with array as
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package my_array_pkg is
type my_array is array ( 0 to 9) of std_logic_vector(3 downto 0);
end my_array_pkg;
Then in top level entity I have declared my components as,
COMPONENT Array_Count is
Port ( C_1Hz : in std_logic;
reset : in std_logic;
digit : out my_array
);
end COMPONENT;
Now can someone help me about how to declare this "digit : out my_array" in the port map.
C2 : Array_Count
PORT MAP ( CLK1HZ, RESET, ????);
The array package needed to be updated in other component.
Thanks.
You need to "use" the package before the entity declaration :
use work.my_array_pkg.all;
or
library my_library;
use my_library.my_array_pkg.all;
to make the package contents visible.
Then you need to declare a signal of that type before you instantiate the component, for example:
signal my_digit : my_array;
and now connect the port to that signal
C2 : Array_Count
PORT MAP (
C_1Hz => CLK1HZ,
reset => RESET,
digit => my_digit);

I don't understand what's wrong with this VHDL code?

I have the following code:
entity wave_select is
port( address:in std_logic_vector(6 downto 0);
ws1: in std_logic;
ws0: in std_logic;
wave_out: out std_logic_vector(6 downto 0));
end wave_select;
architecture choose_arch of wave_select is
signal internal_sine:std_logic_vector(6 downto 0);
signal internal_tri:std_logic_vector(6 downto 0);
signal internal_sqr:std_logic_vector(6 downto 0);
begin
U0: entity sine_tbl port map(addr=>address, sine_val=>internal_sine);
U1: entity triangle_tbl port map(addr=>address, tri_val=>internal_tri);
U2: entity square_tbl port map(addr=>address, square_val=>internal_sqr);
process (std_logic_vector'(ws1, ws0))
begin
case ws_combo is
when "01" => wave_out<=internal_sine;
when "10" => wave_out<=internal_tri;
when "11" => wave_out<=internal_sqr;
when others =>wave_out<=(others => '-');
end case;
end process;
end choose_arch;`
Whenever I try to compile this, I get the following errors:
Identifier/keyword expected (for the process line)
Keyword end expected (for the when "10" line)
Design unit declaration expected (for the same line as keyword error)
FIXED THE QUESTION
As it stands right now, this has a number of problems, mostly with fairly basic syntax.
Although it seems likely you mean the combination of ws0 and ws1 to be treated as ws_combo, you haven't done anything to tell the synthesizer that, so it treats ws_combo as simply undefined.
At least as far as I know, you can't combine signals in the process sensitivity list like you've done. The sensitivity list is to tell what external signals this process responds to, not much else.
You don't have a definition of wave_out (unless it's also in your entity declaration).
You don't have definitions of internal_sine, internal_tri, or internal_sqr. Hard to guess what type they should be without knowing the type of wave_out.
As an interim idea of how this might turn out, I've fixed some of the syntax errors, added an entity declaration that declares ws0, ws1 and wave_out, then sets wave_out to values suitable to the type I've given it (in this case, just took binary input and produced Grey code output).
entity controller1 is
port (
ws1 : in std_logic;
ws0 : in std_logic;
wave_out : out std_logic_vector(1 downto 0)
);
end;
architecture whatever of controller1 is
begin
impl: process(ws0, ws1)
begin
case std_logic_vector'(ws1,ws0) is
when "01" => wave_out<="01";
when "10" => wave_out<="11";
when "11" => wave_out<="10";
when others =>wave_out<=(others => '-');
end case;
end process;
end whatever;
Of course, this also needs the typical library and using to get declarations for std_logic and std_logic_vector, but with those added the synthesizer seems to accept it. Of course, some other synthesizer (I'm checked it with Synplify) might find a problem I missed, but I think that probably covers at least most of the obvious problems.
What are you attempting to achieve with the std_logic_vector' in this line?
process (std_logic_vector'(ws1, ws0))
If you just change that for the more conventional
process (ws1, ws0)
I imagine it will help.
But I assume ws_combo is a signal like
ws_combo = ws1&ws0;
so
process (ws_combo)
would be better still.

Resources