Donald E. Thomas - The Verilog Hardware Description Language, Fifth Edition (798541), страница 20
Текст из файла (страница 20)
Inthis case, bits fifteen through thirteen of the instruction register (the controllingexpression) are compared with each of the seven case expressions. Bit widths must matchexactly. The first expression to match the controlling expression causes the statementfollowing the colon to be executed. Then execution continues with the statement afterthe case. The comparison is done using 4-valued logic; thus a 2-bit case condition canevaluate to sixteen different values.The general form of the case statement isstatementcase_statementThe Verilog Hardware Description Language88module mark1Case;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 signalalwaysbegin@(posedge ck)ir <= m [pc];@(posedge ck)case (ir [15:13])3'b000 : pc <= m [ir [12:0]];3'b001: pc <= pc + m [ir [12:0]];3'b0l0 : acc <= -m [ir [12:0]];3'b011: m [ir [12:0]] <= acc;3'b100,3'bl0l : acc <= acc - m [ir [12:0]];3'bll0 : i f ( a c c < 0 ) p c < = p c + l;endcasepc <= pc + 1;endendmoduleExample 3.6 The Mark-1 With a Case Statementcase_statementcase (expression ) case_item { case_item} endcasecase_itemexpression {, expression): statement_or_nulldefault [: ] statement_or_nullA default may be specified using the default keyword in place of a case expression.When present, the default statement will be executed if none of the other case expressions match the controlling expression.
The default may be listed anywhere in the casestatement.The example also illustrates how a single action may be specified for several of thecase expressions. The commas between case expressions specify that if either of thecomparisons are TRUE, then the statement is executed. In the Mark-1 example, if theBehavioral Modeling89three bits have either of the values 4 or 5, a value is subtracted from the accumulator.The first line of case_item, above, details the syntax.Finally, note that the controlling expressions and case expressions do not need to beconstants.References: casez, casex 3.4.4; comparison with if-else-if 3.4.3; conditional operator 3.2.2; registerspecification E.1; memory specification E.23.4.3 Comparison of Case and If-Else-lfIn the Mark-1 examples above, either case or if-else-if could be used.
Stylistically, thecase is more compact in this example and makes for easier reading. Further, since allof the expressions were compared with one controlling expression, the case is moreappropriate. However, there are two major differences between these constructs.The conditional expressions in the if-else-if construct are more general. Any set ofexpressions may be used in the if-else-if whereas with the case statement, the caseexpressions are all evaluated against a common controlling expression.The case expressions may include unknown (x) and high impedance (z) bits.
Thecomparison is done using 4-valued logic and will succeed only when each bitmatches exactly with respect to the values 0,1, x, and z. Thus it is very importantto make sure the expression widths match in the case expressions and controllingexpression. In contrast, if statement expressions involving unknown or highimpedance values may result in an unknown or high impedance value which willbe interpreted as FALSE (unless case equality is used).An example of a case statement with unknown and high impedance values isshown below in a debugging example.reg ready;// other statementscase (ready)1'bz:1'bx:default:endcase// a one bit register("ready is high impedance");("ready is unknown");("ready is %b", ready);In this example, the one bit ready is compared with high impedance (z) and unknown(x); the appropriate display message is printed during simulation. If ready is neitherhigh impedance or unknown, then its value is displayed.References: four-level logic 6.2.2; casez, casex 3.4.4; case equality 3.2The Verilog Hardware Description Language903.4.4 Casez and Casexcasez and casex are two types of case statements that allow don’t-care values to be considered in case statements.
casez allows for z values to be treated as don’t-care values,and casex allows for both z and x to be treated as don’t-care. In addition to specifyingbits as either z or x, they may also be specified with a question mark (“?”) which alsoindicates don’t-care. The syntax for casex and casez is the same as with the case statement, except the casez or casex keyword is substituted for case.case_statementcase (expression ) case_item { case_item} endcase| casez (expression) case_item { case_item} endcase| casex ( expression ) case_item { case_item } endcasemodule decode;reg[7:0]r;alwaysbegin// other statementsr = 8'bx1x0x1x0;casex (r)8'b001100xx: statement1;8'b1100xx00: statement2;8'b00xx0011: statement3;8'bxx001100: statement4;endcaseendendmoduleExample 3.7 An Example of CasexConsider the casex shown in Example 3.7.
In this example we have loaded registerr with the eight bit value x1x0x1x0, indicating that every other bit is unknown. Sincethe unknown x is treated as a don’t-care, then only statement 2 will be executed.Although statement 4 also matches, it will not be executed because the condition onstatement 2 was found first.x1x0x1x01100xx00value in register rmatching case expressionThe difference between the two case types is in whether only z is considered as adon’t-care (casez), or whether z and x are considered don’t-cares (casex).References: Verilog operators C; case 3.4.2Behavioral Modeling913.5 Functions and TasksIn software programming, functions and procedures are used to break up large programs into more-manageable pieces, and to allow commonly used functionality to becalled from multiple places. In Verilog, modules provide the means of partitioning adesign into more-manageable parts; the use of modules implies that there are structural boundaries being described.
These boundaries may in fact model the logicalstructure or the physical packaging boundaries of the design. Verilog provides functions and tasks as constructs analogous to software functions and procedures that allowfor the behavioral description of a module to be broken into more-manageable parts.module mark1Mult;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 signalalwaysbegin@(posedge ck)ir <= m [pc];@(posedge ck)case (ir [15:13])3'b000 : pc <= m [ir [12:0]];3'b001: pc <= pc + m [ir [12:0]];3'b010 : acc <= -m [ir [12:0]];3'b011: m [ir [12:0]] <= acc;3'b100,3'b101: acc <= acc - m [ir [12:0]];3'b110 : if (acc < 0) pc <= pc + 1;3'b111: acc <= acc * m [ir [12:0]];endcasepc <= pc + 1;//multiplyendendmoduleExample 3.8 The Mark-1 With a Multiply InstructionFunctions and tasks allow often-used behavioral sequences to be written once andcalled when needed.
They also allow for a cleaner writing style; instead of longsequences of behavioral statements, the sequences can be broken into more readablepieces, regardless of whether they are called one or many times. Finally, they allow for92The Verilog Hardware Description Languagedata to be hidden from other parts of the design.
Indeed, functions and tasks play akey role in making a behavioral description more readable and maintainable.Consider defining opcode 7 of the Mark-1 description in the previous sections tobe a multiply instruction. Early in the behavioral modeling process, we could use theBehavioral Modeling93multiply operator as shown in Example 3.8.
This is a perfectly reasonable behavioralmodel for early in the design process in that the functionality is thoroughly described.However, we may want to further detail the multiply algorithm used in the design.Our first approach will be to use functions and tasks to describe the multiply algorithm. Later, we will contrast this approach to that of describing the multiply as a separate module. Table 3.1 contrasts the differences between tasks and functions.3.5.1 TasksA Verilog task is similar to a software procedure. It is called from a calling statement.After execution, control returns to the next statement. It cannot be used in an expression.
Parameters may be passed to it and results returned. Local variables may bedeclared within it and their scope will be the task. Example 3.9 illustrates how module Mark-1 could be rewritten using a task to describe a multiply algorithm.A task is defined within a module using the task and endtask keywords. This task isnamed multiply and is defined to have one inout (a) and one input (b). This task iscalled from within the always statement. The order of task parameters at the callingsite must correspond to the order of definitions within the task. When multiply iscalled, acc is copied into task variable a, the value read from memory is copied into b,and the task proceeds. When the task is ready to return, prod is loaded into a.
Onreturn, a is then copied back into acc and execution continues after the task call site.Although not illustrated here, a task may include timing and event control statements. Twice within Example 3.9 named begin-end blocks are used, illustrating thatwithin these blocks, new register identifiers may be defined. The scope of these names(ir, mcnd, mpy, and prod) is the named begin-end block. The general form of the taskdeclaration is:task_declarationtask [ automatic] task_identifier ;{task_item_declaration}statement_or_nullendtask|task [ automatic] task_identifier (task_port_list) ;{block_item_declaration}statementendtask|task_item_declarationblock_item_declaration| tf_output_declaration| tf_input_declaration|inout_declarationThe Verilog Hardware Description Language94module mark1Task;signedreg [15:0]reg [12:0]signedsignedreg [12:0]regm [0:8191];pc;acc;ck;//signed 8192 x 16 bit memory// signed 13 bit program counter// signed 13 bit accumulator// a clock signalalwaysbegin: executeInstructionsreg [15:0] ir; // 16 bit instruction register@(posedge ck)ir <= m [pc];@(posedge ck)case (ir [15:13])// other case expressions as before3'b111: multiply (acc, m [ir [12:0]]);endcasepc <= pc + 1;endtask multiply(inout[12:0] a,input[15:0] b);begin: serialMultreg[5:0] mcnd, mpy; //multiplicand and multiplierreg[12:0] prod;//productmpy = b[5:0];mcnd = a[5:0];prod = 0;repeat (6)beginif (mpy[0])prod = prod + {mcnd, 6'b000000};prod = prod >> 1;mpy = mpy >> 1;enda = prod;endendtaskendmoduleExample 3.9 A Task SpecificationBehavioral Modeling95block_item_declarationblock_register_declarationreg_declarationparameter_declarationlocal_parameter_declarationinteger_declarationreal_declarationtime_declarationrealtime_declarationevent_declarationThe input and output tf declarations take the form of:tf_output_declarationoutput [reg] [signed] [range] list_or_port_identifiers|output [task_port_type] list_or_port_identifiersThe first shows the style of making multiple definitions in a single statement.
Thesecond allows the specification of the task_port_type (to be time, real, realtime, orinteger).The multiply algorithm uses a shift and add technique. The low-order sixteen bitsof the operands are multiplied producing a 32-bit result that is returned. The statementmpy = b[5:0];does a part-select on b and loads the low order six bits into mpy.