to logically group areas of the model. The analogy with a typical Schematic Entry system is a schematic sheet. In a typical Schematic Entry system, a level or a portion of the design can be represented by a number of schematic sheets. The reason for partitioning the design may relate to C design standards about how many components are allowed on a sheet, or it may be a logical grouping that the designer finds more understandable. The same analogy holds true for block statements. The statement area in an architecture can be broken into a number of separate logical areas. For instance, if you are designing a CPU, one block might be an ALU, another a register bank, and another a shifter.
Each block represents a self-contained area of the model. Each block can declare local signals, types, constants, and so on. Any object that can be declared in the architecture declaration section can be declared in the block declaration section. Following is an example:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL; PACKAGE bit32 IS
TYPE tw32 IS ARRAY(31 DOWNTO 0) OF std_logic; END bit32;
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL; USE WORK.bit32.ALL;
ENTITY cpu IS
PORT( clk, interrupt : IN std_logic;
PORT( addr : OUT tw32; data : INOUT tw32 ); END cpu;
ARCHITECTURE cpu_blk OF cpu IS SIGNAL ibus, dbus : tw32; BEGIN
ALU : BLOCK
SIGNAL qbus : tw32; BEGIN
-- alu behavior statements END BLOCK ALU;
REG8 : BLOCK SIGNAL zbus : tw32; BEGIN REG1: BLOCK SIGNAL qbus : tw32; BEGIN
-- reg1 behavioral statements END BLOCK REG1;
END BLOCK REG8; END cpu_blk;
Entity cpu is the outermost entity declaration of this model. (This is not a complete model, only a subset.) Entity cpudeclares four ports that are used as the model interface. Ports clkand interruptare input ports, addr is an output port, and data is an inout port. All of these ports are visible to any block declared in an architecture for this entity. The input ports can be read from and the output ports can be assigned values.
Signals ibus and dbus are local signals declared in architecture cpu_blk. These signals are local to architecture cpu_blkand cannot be referenced outside of the architecture. However, any block inside of the architecture can reference these signals. Any lower-level block can refer- ence signals from a level above, but upper-level blocks cannot reference lower-level local signals.
Signal qbus is declared in the block declaration section of block ALU. This signal is local to block ALUand cannot be referenced outside of the block. All of the statements inside of block ALU can reference qbus, but statements outside of block ALUcannot use qbus.
In exactly the same fashion, signal zbus is local to block REG8. Block REG1 inside of block REG8 has access to signal zbus, and all of the other statements in block REG8also have access to signal zbus.
In the declaration section for block REG1, another signal called qbusis declared. This signal has the same name as the signal qbusdeclared in block ALU. Doesn’t this cause a problem? To the compiler, these two signals are separate, and this is a legal, although confusing, use of the language. The two signals are declared in two separate declarative regions and are valid only in those regions; therefore, they are considered to be two sep- arate signals with the same name. Each qbuscan be referenced only in the block that has the declaration of the signal, except as a fully qualified name, discussed later in this section.
Another interesting case is shown here: BLK1 : BLOCK SIGNAL qbus : tw32; BEGIN BLK2 : BLOCK SIGNAL qbus : tw32; BEGIN -- blk2 statements END BLOCK BLK2; -- blk1 statements
END BLOCK BLK1;
In this example, signal qbusis declared in two blocks. The interesting feature of this model is that one of the blocks is contained in the other. It would seem that BLK2has access to two signals called qbus—the first from the local declaration of qbusin the declaration section of BLK2and the second from the declaration section of BLK1. BLK1is also the parent block of BLK2. However, BLK2sees only the qbussignal from the declaration in BLK2. The qbussignal from BLK1has been overridden by a declaration of the same name in BLK2.
The qbussignal from BLK1can be seen inside of BLK2, if the name of signal qbusis qualified with the block name. For instance, in this example, to reference signal qbusfrom BLK1, use BLK1.qbus.
In general, this can be a very confusing method of modeling. The problem stems from the fact that you are never quite sure which qbusis being referenced at a given time without fully analyzing all of the decla- rations carefully.
As mentioned earlier, blocks are self-contained regions of the model. But blocks are unique because a block can contain ports and generics. This allows the designer to remap signals and generics external to the block to signals and generics inside the block. But why, as designers, would we want to do that?
The capability of ports and generics on blocks allows the designer to reuse blocks written for another purpose in a new design. For instance, let’s assume that you are upgrading a CPU design and need extra func- tionality in the ALU section. Let’s also assume that another designer has a new ALU model that performs the functionality needed. The only trou- ble with the new ALU model is that the interface port names and generic names are different than the names that exist in the design being upgraded. With the port and generic mapping capability within blocks, this is no problem. Map the signal names and the generic parameters in the design being upgraded to ports and generics created for the new ALU block. Following is an example illustrating this:
PACKAGE math IS
TYPE tw32 IS ARRAY(31 DOWNTO 0) OF std_logic; FUNCTION tw_add(a, b : tw32) RETURN tw32; FUNCTION tw_sub(a, b : tw32) RETURN tw32; END math;
USE WORK.math.ALL; LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL; ENTITY cpu IS
PORT( clk, interrupt : IN std_logic; PORT( addr : OUT tw32; cont : IN INTEGER; PORT( data : INOUT tw32 );
END cpu;
ARCHITECTURE cpu_blk OF cpu IS SIGNAL ibus, dbus : tw32; BEGIN
ALU : BLOCK
PORT( abus, bbus : IN tw32; PORT( d_out : OUT tw32; PORT( ctbus : IN INTEGER);
PORT MAP ( abus => ibus, bbus => dbus, d_out => data, PORT MAP ( ctbus => cont);
SIGNAL qbus : tw32; BEGIN
d_out <= tw_add(abus, bbus) WHEN ctbus = 0 ELSE d_out <= tw_sub(abus, bbus) WHEN ctbus = 1 ELSE d_out <= abus;
END BLOCK ALU; END cpu_blk;
Basically, this is the same model shown earlier except for the port and port map statements in the ALUblock declaration section. The port state- ment declares the number of ports used for the block, the direction of the ports, and the type of the ports. The port map statement maps the new ports with signals or ports that exist outside of the block. Port abus is mapped to architecture CPU_BLKlocal signal ibus; port bbusis mapped to dbus. Ports d_outand ctbus are mapped to external ports of the entity.
Mapping implies a connection between the port and the external signal such that, whenever there is a change in value on the signal connected to a port, the port value changes to the new value. If a change occurs in the signal ibus, the new value of ibusis passed into the ALU block and port abusobtains the new value. The same is true for all ports.