Donald E. Thomas - The Verilog Hardware Description Language, Fifth Edition (798541), страница 22
Текст из файла (страница 22)
The implication of the description using a task or function is thatthis divide algorithm will be part of the final data path and state machine synthesizedto implement the Mark-1 processor. That is, we enlarged the behavioral descriptionby specifying the details of the multiply algorithm and thus we would expect the finalstate machine that implements this behavior to have more states. Likewise, the datapath may need more components to hold the values and perform the operations.Another design decision could have been to use a possibly pre-existing multiplymodule in conjunction with the Mark-1 module.
This case, shown in Example 3.12,illustrates the multiply as an instantiated module within the mark1Mod module. Thisdescription approach would be used if a previously designed multiply module was tobe used, or if the designer wanted to force a functional partitioning of the moduleswithin the design. The multiply module ports are connected to the mark1Mod andthe mark1Mod module starts the multiply module with the go line. When done, themultiply module signals the Mark-1 with the done line which Mark-1 waits for.
Thisstructural description leads to a very different design. Now we have two statemachines, one for mark1Mod and one for multiply. To keep the two modules synchronized, we have defined a handshaking protocol using wait statements and signalling variables go and done. At this point in the design process it is not possible topoint to one of these solutions as being the best. Rather we can only suggest, as wehave done above, why one would describe the system solely with behavioral modelingconstructs ( *, function, task) or suggest structural partitioning of the behavior.References. Functions in continuous assign 6.3.1Behavioral Modeling101module mark1Mod;reg [15:0] signedreg [12:0]signedreg [12:0]signedreg [15:0]regm [0:8191];pc;acc;ir;ck;// signed 8192 x 16 bit memory// signed 13 bit program counter// signed 13 bit accumulator// 16 bit instruction register// a clock signalregsigned [12:0] mcnd;reggo;wiresigned [12:0] prod;wiredone;multiplymul (prod, acc, mcnd, go, done);alwaysbegin@(posedge ck)go <= 0;ir <= m [pc];@(posedge ck)case (ir [15:13])//other case expressions3'blll:beginwait (~done) mcnd <= m [ir [12:0]];go <= 1;wait (done);acc <= prod;endendcasepc <= pc + 1;endendmodulemodule multiply(output reg signed [12:0]inputsigned [12:0]inputoutput regreg[5:0]myMpy,prod,mpy, mcnd,go,done);The Verilog Hardware Description Language102alwaysbegindone = 0;wait (go);myMpy = mpy[5:0];prod = 0;repeat (6)beginif (myMpy[0])prod = prod + {mcnd, 6'b000000};prod = prod >> 1;myMpy = myMpy >> 1;enddone = 1;wait (~go);endendmoduleExample 3.12 The Multiply as a Separate Module3.6 Rules of Scope and Hierarchical NamesAn identifier’s scope is the range of the Verilog description over which the identifier isknown.
The rules of scope define this range. Verilog also has a hierarchical namingfeature allowing any identifier in the whole design to be accessed from anywhere inthe design.3.6.1 Rules of ScopeModule names are known globally across the whole design. Verilog then allows foridentifiers to be defined within four entities: modules, tasks, functions, and namedblocks. Each of these entities defines the local scope of the identifier, the range of thedescription over which the identifier is known. This local scope encompasses themodule-endmodule, task-endtask, function-endfunction, and begin:name-end pairs.Within a local scope, there may only be one identifier with the given name.Identifiers can be known outside of the local scope.
To understand the scope ruleswe need to distinguish between situations which allow forward referencing and thosewhich do not.Behavioral Modeling103Forward referenced. Identifiers for modules, tasks, functions, and named beginend blocks are allowed to be forward referencing and thus may be used before theyhave been defined.
That is, you can instantiate a module, enable a task, enable afunction, or disable a named block before either of these entities has been defined.Not forward referenced. Forward referencing is not allowed with register and netaccesses. That is, before you can use them, they must be defined. Typically, theseare defined at the start of the local scope (i.e., module, task, function or namedbegin-end) in which they are being used. An exception to this is that output netsof gate primitives can be declared implicitly (See section 6.2.3).For the case of the forward referencing entities (module, task, function, and namedbegin-end blocks), there is also an upward scope defined by the module instantiationhierarchy.
From the low end of the hierarchy, forward referenced identifiers in eachhigher local scope are known within the lowest scope. This path up the moduleinstantiation hierarchy is the upward scope.Consider Example 3.13. The identifiers in the local scope of module top are: top,instance1, y, r, w, and t. When module b is instantiated within module top, proceduralstatements in b can enable tasks and functions defined in the local scope of moduletop and also disable a named block in its local scope. However, task t in module tophas a named block (c) within its scope.
c cannot be disabled from module b because cis not in top’s local scope and thus it is not in b’s upward scope (rather, it is down alevel from it in task t’s local scope). Further, named block y in top’s local scope can bedisabled from module b and it can be disabled from within a task or function definedin module top, or from within named blocks within the task or function.Note however, that register r and wire w, although in the upward scope of moduleb, are not accessible from it; registers and nets are not forward referencing and thuscan only be accessed in the local scope. The rule is that forward-referencing identifiers(i.e. module, task, function, and named block identifiers) are resolved after the instantiations are known by looking upward through the module instantiation tree. Whenthe top of the hierarchy is reached (at a module that is not instantiated elsewhere) thesearch for the identifier is ended.
Non-forward referenced registers and nets areresolved immediately in the local scope.It is important to note that tasks and functions defined in a module can be enabledfrom within any of the modules instantiated (to any level) in that module. Thus functions and tasks used in many parts of the design should be defined in the top module.It is also useful to think of the upward identifier tree as arising from two sources:the module hierarchy, and procedural statement hierarchy.
The module hierarchy treewas described above. The procedural statement hierarchy arises from nested namedblocks within always and initial statements, tasks, and functions. Procedural statement hierarchies are rooted in modules (essentially, they are always and initial state-The Verilog Hardware Description Language104module top;regr;wirew;b instance1();alwaysbegin: yregend//hierarchical name is top.r//hierarchical name is top.wq;task t;begin: cregq;disable y;endendtaskendmodulemodule b;regs;alwaysbegint;disable y;disable c;disable t.c;s = 1;r = 1;top.r = 1;t.c.q = 1;y.q = 1;endendmodule//hierarchical name is top.y.q//hierarchical name is top.t.c//hierarchical name is top.t.c.q//OK//hierarchical name is top.instance1.s//OK//OK//Nope, c is not known//OK//OK//Nope, r is not known//OK//OK//OK, a different q than t.c.qExample 3.13 Scope and Hierarchical Namesments) and are separate from the module hierarchy. When accessing non-forwardreferencing identifiers (registers and wires), statements at the deepest point of nestinglook up the procedural hierarchy for the identifier.
When the root of the proceduralhierarchy is found, the search is stopped. The reason is that non-forward referencingidentifiers only have access to the current local scope and its procedural statementhierarchy for identifier resolution.Behavioral Modeling105Thus, identifiers representing registers and nets are searched up the proceduralhierarchy, but not searched across module instantiation boundaries. Identifiers representing tasks, functions, and named blocks are searched up the procedural and moduleinstantiation hierarchy.3.6.2 Hierarchical NamesThe previous section discussed the upward scope of identifiers within a description.When possible, these identifiers should be used — they are easier to read and easier totype.
On the other hand, hierarchical names can uniquely specify any task, function,named block, register, or wire in the whole description.Hierarchical names are forward referencing — they are not resolved until all modules are instantiated. Hierarchical names consist of a path name which has identifiersseparated by periods (“.”). The first identifier is a forward referencing identifier foundby searching up the procedural and module hierarchy name tree.