Building Custom Modules


In the Verilog hardware description language, modules are omni present and are required to perform a simulation, however simple the system be. libLCS does not require that a user has to define a module. As is presented in the getting started section, one can use the off-the-shelf logic gates to build his/her system and perform a simulation. However, such an approach is suitable only for building small and simple systems. As the system grows in size and complexity, building it using the off-the-shelf logic gates and modules gets very laborious and error prone. Moreover, as the system gets complex, simulating/testing the algorithm becomes more important than the actual gate-level circuit. For this, one would need to build modules which are functional equivalents of the actual gate-level circuit. Such a simulation is called as data flow modelling in Verilog.

Using libLCS, one can build two different kinds of modules: 1. Block-Level Modules and 2. Functional Modules. Block-level modules are ones which are internally a connected ensemble of other modules. They serve merely as an encapsulation of existsing modules into a larger module. Building block-level modules does not require any special care as one only needs to initialise the sub-modules (and connect them up suitably) in the constructor of the module class. The sub-modules will have to be destroyed in the destructor of the module class. Examples of building one's own block-level modules can be found here. Further in this section, I shall only discuss building functional modules in detail.


Functional Modules

[To understand the material presented below in a better/quicker fashion, use this as a reference implementation of the points discussed.]

Functional modules are ones which do not internally have other sub-modules. They merely read the input busses lines and set the output bus lines accordingly. They have to be built with proper care, following certain rules. To get a quick picture on how a functional module differs from a block-level module, compare the block-level realisation and, the functional realisation examples of a 1-bit full-adder. In this section, I shall discuss the concepts involved in building one's own functional modules. The first rule for building a functional module is to derive it from the class lcs::Module.

Input Busses of Functional Modules

Every module, functional or block-level, will have a set of input busses, and set of output busses. In case of functional modules, the module implementer should ensure that the input busses drive the module. For this, the input busses to a functional module should be of the class lcs::InputBus. Busses of type lcs::InputBus allow registration by a module to be driven by the bus. Module implementers should register the module to be driven by all the input busses using the function lcs::InputBus::drive in the constructor of the module class. The this argument should be passed to the lcs::InputBus::drive function.

When a module ceases to exist in the simulation space, it cannot be driven by the input busses with which it has registered. Hence, in the destructor of the module class, the module should de-register itself with all input busses from being driven by them. This is done using the lcs::InputBus::unDrive function. The this argument should be passed to the lcs::InputBus::unDrive function.

NOTE: Objects of the class lcs::InputBus are readonly busses. There is no way one can set the lines states of these objetcs. It has been designed this way, as the module to which these objects are input busses have no business to set their line states. In Verilog, this feature is incorporated by restricting module inputs to be of type wire only.

Output Busses of Functional Modules

An output bus of a module should only be driven by that module. A bus being driven by two different modules is a physical short-circuit and should not be allowed even in simulations. This is achieved in libLCS by using busses of class lcs::Bus as output busses of functional modules. The short-circuit prevention mechanism is provided through the function lcs::Bus::lock. A module should lock all of its output busses by passing the this argument to the lcs::Bus::lock function. Only the module which locks the bus can get write access to the bus lines.

When a module ceases to exist in the simulation space, it should release/un-lock all of its output busses for use by other modules. This is done by passing the this argument to the lcs::Bus::unLock function in the destructor of the module class.

The lcs::Module::propogate Function

As mentioned above, all functional modules should be a derivative of the class lcs::Module. Moreover, they should over-ride the virtual function lcs::Module::propogate. This is the function which is used by the input bus objects to drive the module. This function should read the input bus lines, perform the neccessary calculations, and set the output bus lines accordingly. See this topic guide to learn how to set lines of a lcs::Bus object which has been locked by a module.

NOTE:A call to its own propogate function should be the last operation by the constructor of a module. This will ensure that the input and output bus lines are in a coherent state after module construction.


Generated on Sat Oct 14 11:23:40 2006 for libLCS by  doxygen 1.4.7