Is there a way in VHDL to make a series of components? - vhdl

Simply put, I have a component " X " and I want to connect 24 of them in a row; obviously means that the output of one is the input of the next one; I could just write them myself with copypaste and link them but I wonder if there is a way to do this elegantly.
I know the instruction for I in N downto 0 generate but I don't think I can use it to create components in series, it only creates components in parallel, where each one works on a different value of the I parameter, or not ?

The generate statement is indeed what you need. Example if your X component has one input a and one output b of type bit:
entity bar is
end entity bar;
architecture rtl of bar is
signal c: bit_vector(0 to 24);
component x is
port(
a: in bit;
b: out bit
);
end component x;
begin
u0: for i in 0 to 23 generate
x0: x
port map(
a => c(i),
b => c(i+1)
);
end generate u0;
end architecture rtl;
The input of the first X instance is c(0) and the output of the last one is c(24).

Related

Signal in Top Module of a design being driven by two drivers (from different components)

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.

Modelsim/Questasim: Unknown entity <entity_name>. Use expanded name

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).

vhdl structural statement inside a sequential architecture

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;

VHDL signal dimension issue when reducing a generic value down to 0

How can one handle this case:
entity foo is
generic (
num_instances : natural := 8
);
port (
data_in_per_instance : in std_logic_vector(num_instances-1 downto 0);
data_out_per_instance : out std_logic_vector(num_instances-1 downto 0)
);
end foo;
architecture bar of foo is
component do_stuff is
port(
din : in std_logic;
dout : out std_logic
);
end component do_stuff;
signal sig_per_instance : std_logic_vector(num_instances-1 downto 0);
begin
L1: for i in 0 to num_instances-1 generate
L2: do_stuff
port map(
din => data_in_per_instance(i),
dout => data_out_per_instance(i)
);
end generate;
end bar;
The problem here is that if num_instances is reduced to 0 there will be an error when the signal ranges (num_instances-1 downto 0) are evaluated....
Is there an elegant way around this? All I can come up with is using a function like max(num_instances-1,0) to prevent this problem (but then synthesis may not give me exactly what I want, i.e. nothing).
Is there some way to handle this case a little more seamless?
A simple answer is to wrap the for-generate statement in an if-generate, if num_instances /= 0 generate ... Unfortunately if-generates have no else part, however there is nothing to stop you adding a second if num_instances = 0 generate ... statement to handle that special case.
Alternatively you can wrap the problem part of the for-generate using if-generate.
EDIT: re the need for a correct signal declaration guarded by the if ... generate.
AHA! You may have discovered a legitimate use for VHDL's (in my experience) rarely used "block" statement!
A block statement may contain signal declarations, and can be wrapped in a generate.
So this is valid VHDL:
Normality : block is
-- signal declarations here
begin
-- concurrent code here
end block Normality;
and it can be legally wrapped in a generate statement...
A std_logic_vector with an empty range (for example 3 downto 4) is perfectly legitimate - it's called a "null range" by the LRM. If you create one, then (at least with Modelsim) you will get warnings, which is usually considered poor form. To eliminate those, then Brian's block suggestion is what you'll have do.
Similarly the for..generate will result in an empty loop and no instances. No warnings for this.
I'm intrigued why you'd want a block with no instances in? I'd make num_instances a positive to force at least one of them, but that may not actually what you want!

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