I am designing a project on Modelsim VHDL where I use two components. Depending on a control input I'll choose which component to use:
If control=0 then the inputs will be ported to the first component.
If control=1 the inputs will be ported to the second component.
However, a compilation error appeared when I wrote "U1: port map..." in an if statement
(can't put an structural statement inside a sequential architecture).
Any ideas how to solve my problem?
There are two possible interpretations to your question:
Situation #1: Your design uses only one of two possible components at a time. The decision of which component to use is done at compile time, i.e., it is written in your code and is impossible to change after the circuit is synthesized.
Situation #2: Your design uses the two components concurrently, and you use a signal to select dynamically one of the possible outputs.
Each situation has a different solution.
Solution for situation #1: Use a generic in your entity, and an if-generate statement in your architecture body. Here is an example:
entity component_selection_at_compile_time is
generic (
-- change this value to choose which component gets instantiated:
COMPONENT_SELECT: in integer range 1 to 2 := 1
);
port (
input: in integer;
output: out integer
);
end;
architecture rtl of component_selection_at_compile_time is
component comp1 is port(input: in integer; output: out integer); end component;
component comp2 is port(input: in integer; output: out integer); end component;
signal comp1_output, comp2_output: integer;
begin
c1: if COMPONENT_SELECT = 1 generate
u1: comp1 port map (input, output);
end generate;
c2: if COMPONENT_SELECT = 2 generate
u2: comp2 port map (input, output);
end generate;
end;
Solution for situation #2: Create a third component. This component will be a wrapper, and will instantiate both of your original components. In certain cases, you can even assign the same inputs to both components. Then use a select signal to chose which output will be forwarded to outside the wrapper.
entity wrapper is
port (
wrapper_input: in integer;
wrapper_output: out integer;
component_select: in integer range 1 to 2
);
end;
architecture rtl of wrapper is
component comp1 is port(input: in integer; output: out integer); end component;
component comp2 is port(input: in integer; output: out integer); end component;
signal comp1_output, comp2_output: integer;
begin
u1: comp1 port map (wrapper_input, comp1_output);
u2: comp2 port map (wrapper_input, comp2_output);
wrapper_output <= comp1_output when component_select = 1 else comp2_output;
end;
The answer to this question depends on the nature of the control input. If the control input is a way of configuring your design at compile time, the desired functionality can be achieved using generics and generate statements. Otherwise....
Based on the way you have worded your question, I am going to assume that this is not the case. I will assume that your design must support both at different times, with the same compiled design. In that case, you must instantiate both components, and route data to both components and somehow indicate to those components when the data is valid and must be processed. For example:
en1 <= not control;
en2 <= control;
U1 : entity work.design1
port map (
data => data,
en => en1
);
U2 : entity work.design2
port map (
data => data,
en => en2
);
In this example, we have created 2 new signals, en1 and en2 which are '1' to enable each of the components at the appropriate time. In each of the instantiated entities, you need to look at the en input to determine when the input data is valid.
Note: Your design may already have a signal similar to en1 or en2. For example, you may have a generic "bus" which has a valid signal, indicating when data on the bus is valid. In that case, you can add something like this, gating the enable signal with bus_valid:
en1 <= not control and bus_valid;
en2 <= control and bus_valid;
Related
That's my code:
-- Insert library and use clauses
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY Questao1 IS
-- Begin port declaration
PORT (
-- Declare data inputs "dataa" and "datab"
dataa, datab : in STD_LOGIC_VECTOR (15 DOWNTO 0);
-- Declare data output "sum"
sum : out STD_LOGIC_VECTOR (15 DOWNTO 0)
);
-- End entity
END ENTITY Questao1;
-- Begin architecture
ARCHITECTURE logic OF Questao1 IS
BEGIN
sum <= x"000A" WHEN dataa = x"0001" ELSE x"000B" WHEN datab = x"0001" ELSE x"000C";
dataa <= x"0001", x"0000" AFTER 20 NS, x"000A" AFTER 30 NS;
datab <= x"0000", x"0001" AFTER 20 NS, x"0005" AFTER 30 NS;
-- End architecture
END ARCHITECTURE logic;
That's my error:
Error (10568): VHDL error at Questao1.vhd(44): can't write to interface object "dataa" of mode IN
Someone can help? I'm beginning in VHDL
It seems you were a given a task to write a testbench to test your code.
Generally speaking a vhdl code for a design represents how the design should behave. If you wish to test it if it really does, what it is supposed to do, you need to 'wrap' it in a bigger device, to be able to send signals to your 'device under test'.
This is often done with the use of testbenches - a vhdl code that uses your entity as a component and sends signals to it.
Next thing to note is that any time specific commands (like 'AFTER' in your case) are not synthesizable. However you can simulate behaviour of your design using software tools, like modelsim.
Another thing is that you cannot assign values to input. Input ports receive data from 'outside world', you cannot alter the data your entity receives from within the entity itself.
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).
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?
In my design I have several modules. the code snippet of the top module is coming as follows.
There's one problem which confuses me. let's assume the below scenario:
Step1:
The Calc1_module works from t1 to t2 and it should send it's output to the input of the memory module to be stored there. (Calc1_out is mapped to Aggregation_Signal)
Step2:
The Calc2_module works from t3 to t4 and it should send it's output to the input of the memory module to be stored there. (Calc2_out is mapped to Aggregation_Signal).
The Memory_Moduel_in is mapped to Aggregation_Signal.
Since there are multiple drivers for one signal, it has all the time an unknown value.
It's worth mentioning that all controls occur within FSM to decide when it goes after Calc1 and when Calc2.
How I can selectively interleave different data from different sources on one wire (signal) on at a time -in the top module of the design- without pushing that wire into an unknown state?
In other words, how is it possible to aggregate:
value1 for signal1 (e.g. coming from Calc2 in t1 to t2)
value2 from signal2 (e.g. coming from Calc1 in t2 to t3)
all in one Aggregation_Signal without driving it into unknown state.
entity TOP is
port (...);
end entity;
architecture Behav_TOP of TOP is
component FSM is
port(...);
end component;
component Calc1_Module is
port
( ...
Calc1_Module_out
... );
end component;
component Calc2_Module is
port
( ...
Calc2_Module_out
... );
end component;
component Memory_Module is
port
( ...
Memory_Module_in
... );
end component;
Signal Aggregation_Signal;
begin
U_FSM : FSM
port map(...);
U_Calc1_Module : Calc1_Module
port map
( ...
Calc1_Module_out => Aggregation_Signal,
... );
U_Calc2_Module : Calc2_Module
port map
( ...
Calc2_Module_out => Aggregation_Signal,
... );
U_Memory_Module : Memory_Module
port map
( ...
Memory_Module_in => Aggregation_Signal,
... );
end Behav_TOP;
The clue is in your term "selectively interleave".
How do you make that selection? Presumably you know when you want to see Calc1, when you want to see Calc2, etc. So encode that information onto a signal, let's call it Selector.
Then bring each unit's output onto its own signal, Calc1_output etc and use Selector to select between them onto Aggregation_Signal.
Aggregation_Signal <= Calc1_output when Selector = Calc1
else Calc2_output when Selector = Calc2
else (others => '0';
The Selector signal can be an enumeration with one value per Calc unit, or a Natural or a std_logic_vector with constants named Calc1, Calc2 etc.
Since you say the calculation is driven by a state machine, it is logical for the state machine to drive Selector with the correct value whenever you need a value on Aggregation_Signal.
I'm using QuestaSim, which is supposedly the same thing as ModelSim but 64-bit. I'm trying to run a test bench for an assignment due in class tomorrow. The assignment is done and all I need is the test bench, but QuestaSim is being annoying as usual.
For some reason, the test bench file just WILL NOT compile. I cannot for the life of me figure out why, though I recall it working on ModelSim the last time I tried this.
Here's the code for the test bench.
library ieee;
use ieee.std_logic_1164.all;
entity test_bench is
end entity test_bench;
architecture lab1atest of test_bench is
signal X, Y, M: std_logic_vector (7 downto 0);
signal s: std_logic;
begin
dut : entity lab1a
port map ( X=>X, Y=>Y, s=>s, M=>M);
stimulus : process is
begin
X <= "10101010"; Y <= "01010101"; s <= '0'; wait for 20 ns;
s <= '1'; wait for 20 ns;
X <= "11110000"; wait for 20 ns;
s <= '0'; wait for 20 ns;
Y <= "00001111";
wait;
end process stimulus;
end architecture lab1atest;
The code for lab1a.vhd I can't post because it's to be submitted for an assignment and I don't want to get nailed for plagiarizing myself, but know that the entity "lab1a" most certainly exists in that file and I am making sure to compile that file first (though I have tried the other way around, just in case).
In addition to the standard selecting of the files and hitting compile, I've also tried the following:
vlib work;
vmap work work;
vcom lab1a.vhd;
vcom lab1atest.vhdl;
vsim work.lab1atest;
Both produce the same error.
If any of you have any idea why I am getting the error highlighted in the title, please let me know. I feel like this is an incredibly simple fix and I am currently cursing the designers of said product for making it so unintuitive.
I genned a dummy entity/architecture for lab1a that does nothing but has proper connectivity.
The immediate issue why it won't 'analyze' is that the entity lab1a isn't made visible to test_bench.
dut : entity lab1a
port map ( X=>X, Y=>Y, s=>s, M=>M);
should be
dut: entity work.lab1a
port map ( ...
or you should make the contents of your working directory visible in your context clause by adding a use clause:
use work.all; -- or some variant form
After implementing the selected name (work.lab1a, an expanded name is a form of selected name, see IEEE Std 1076-2008, 8.3 Selected names, paragraph 7) the code analyzed with a previously analyzed lab1a:
library ieee;
use ieee.std_logic_1164.all;
entity lab1a is
port (
X: in std_logic_vector (7 downto 0);
Y: in std_logic_vector (7 downto 0);
s: in std_logic;
M: out std_logic_vector (7 downto 0)
);
end entity;
architecture foo of lab1a is
begin
end architecture;
And why the dummy lab1a works is because an architecture isn't required to contain concurrent statements:
architecture_body ::=
architecture identifier of entity_name is
architecture_declarative_part
begin
architecture_statement_part
end [ architecture ] [ architecture_simple_name ] ;
architecture_statement_part ::=
{ concurrent_statement }
IEEE Std 1076-2008. 1.3.2 Synaptic description, f):
Braces enclose a repeated item or items on the right-hand side of a
production. The items may appear zero or more times; the repetitions
occur from left to right as with an equivalent left-recursive rule.
Extended Backus-Naur Form text found in the numbered clauses of the standard is normative.
And there's another solution, the use of a component declaration and component instantiation instead of direct entity instantiation.
This would count on default binding indication to find a previously analyzed lab1a during elaboration. (7.3.3 Default binding indication).