Up to now the designs have consisted of only one entity. Just like in software, there quickly comes a time when putting every statement in one source file is no longer practical. There is also the need to separate designs into functional units that can be designed and tested independently of each other, before they are integrated into one design.
In VHDL speak, these are called modules.
VHDL achieves this through "architectures", "components", "entities" and "instances" - we have already breezed over all of this.
-
The "entity" statement defines the 'inside' view of a module’s interface:
entity mymodule is
Port ( input1 : in STD_LOGIC_VECTOR (3 downto 0);
output1 : out STD_LOGIC_VECTOR (3 downto 0));
end mymodule;
This is at the top of the defining module, following the "use" statements.
-
The "architecture" statement defines how a component works - it contains all the internal signals and sub-components, and all the internal logic:
architecture Behavioral of mymodule is
begin
output1 <= input1;
end Behavioral;
This is usually the bulk of the module, and appears after the entity statement.
-
The "component" statement defines the \'external' connections of the module, and appears in the module that uses the component:
COMPONENT mymodule
PORT(
input1 : IN std_logic_vector(3 downto 0);
output1 : OUT std_logic_vector(3 downto 0));
END COMPONENT;
Component declarations appear in the same area of the code as the signal declarations.
-
The "instance" statement describes the connections of the component inside the containing module - it is this that actually triggers the component to be included in the final design:
Inst_mymodule: mymodule PORT MAP(
input1 => input_signal1,
output1 => output_signal1
);
These can be intermingled with the assignment statements and processes, but not contained within a process block. One source of frustration for me is that when signals are mapped they cannot be operated on (e.g., 'input_a ⇒ signal_a' is valid but 'input_a ⇒ NOT(signal_a)' is not). All inputs should have a value, but if you don’t want to use an output, you can map it to the keyword "open" (e.g., "output1 ⇒ open").
The easy way to create a new module is by using the "New Source" wizard.
On the first screen, give the module a name:
Then define the interface - do not worry if you are not 100% sure of the signals, you can change them directly in the source afterwards:
You are then presented with a summary screen, and can then click \'Finish'.
Once you have a new module, you can highlight it, and under "Design Utilities" you can run the "View HDL Instantiation Template" process to get a template that you can cut and paste as needed:
It will look something like this:
COMPONENT mymodule
PORT(
input1 : IN std_logic_vector(3 downto 0);
output1 : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
Inst_mymodule: mymodule PORT MAP(
input1 => ,
output1 =>
);
In most large designs the very top level module ends up containing very little logic and resembles a big wiring loom - with a lot of instances of smaller components and the signals that interconnect them.
-
Create a new module - a 30-bit counter called "counter30", with the following external signals:
-
clk : in STD_LOGIC
-
enable : in STD_LOGIC
-
count : out STD_LOGIC_VECTOR(29 downto 0)
-
The internal design is up to you, but your earlier counter project will be pretty close.
-
View the \'Instantiation Template' for your component. Copy the component declaration into your switches_leds.vhd source
-
In switches_leds create an instance of counter30
-
Connect the counter’s 'count' output to a bus called count1
-
Connect the "enable" signal to switch(0)
-
Connect the clock
-
Connect the top four bits of count1 to LEDs(3 downto 0). Remember to add a signal definition for 'count1'
-
-
Implement the design and test that it works as expected - switch 0 should enable the counter driving the lower four LEDs. It is usual to get a lot of warnings about unused signals that will be trimmed from the design. This is expected as we are only using the top four bits of the counters.
-
Create a second instance of counter30 in the switches_leds vhd source
-
have its 'count' output connected to a bus called 'count2'
-
connect the "enable" signal to switch(1).
-
connect the top four bits of 'count2' to LEDs(7 downto 4)
-
-
Check that this too works as expected