o .C3.FEEDBACK EXTENSIONS USAGE Certain devices can program the feedback path. For example, the EP300 contains a multiplexer for each output that allows the feedback path to be selected as internal, registered, or pin feedback. Figure 1-7 shows the EP300 programmable feedback capability. [Picture] Figure 1-7. Programmable Feedback CUPL automatically chooses a default feedback path according to the usage of the output. For example, if the output is used as a registered output, then the default feedback path will be registered, as in Figure 1-6. This default can be overridden by adding an extension to the feedback variables. For example, by adding the .IO extension to the feedback variables of a registered output, CUPL will select the pin feedback path. Figure 1-8 shows a registered output with pin feedback. [Picture] Figure 1-8. Programmable Pin (I/O) Feedback Figure 1-9 shows a combinatorial output with registered feedback. [Picture] Figure 1-9. Programmable Registered Feedback Figure 1-10 shows a combinatorial output with internal feedback. [Picture] Figure 1-10. Programmable Internal Feedback o .C3.MULTIPLEXER EXTENSION USAGE Certain devices allow selection between programmable and common control functions. For example, for each output, the P29MA16 contains multiplexers for selecting between common and product term clocks and output enables. Figure 1-11 shows the P29MA16 programmable clock and output enable capability. [Picture] Figure 1-11. Output with Output Enable and Clock Multiplexers If expressions are written for the .OE and .CK extensions, the multiplexer outputs are selected as product term output enable and clock, respectively. Otherwise, if expressions are written for the .OEMUX and .CKMUX extensions, the multiplexer outputs are selected as common output enable and clock, respectively. Expressions written for the .OEMUX and .CKMUX extensions can have only one variable and be operated on only by the negation operator, !. This is because their inputs are not from the fuse array, but from a common source, such as a clock pin. This is in contrast with expressions written for the .OE and .CK extensions, which take their inputs from the fuse array. Figure 1-12 shows a registered output with the output enable multiplexer output selected as Vcc, output enable always enabled, and the clock multiplexer output selected as the common clock pin inverted, negative-edge clock. [Picture] Figure 1-12. Output with Output Enable and Clock Multiplexers Selected Expressions for the .OE and .OEMUX extensions are mutually exclusive; that is, only one may be written for each output. Likewise, expressions for the .CK and .CKMUX extensions are mutually exclusive. O .C3.EXTENSION USAGE This section contains diagrams and explanations for all the variable extensions. [Picture] Figure 1-13. .AP Extension The .AP extension is used to set the Asynchronous Preset of a register to an expression. For example, the equation "Y.AP = A & B;" causes the register to be asynchronously preset when A and B are logically true. [Picture] Figure 1-14. .APMUX Extension Some devices have a multiplexer that enables the Asynchronous Preset to be connected to one of a set of pins. The .APMUX extension is used to connect the Asynchronous Preset directly to one of the pins. [Picture] Figure 1-15. .AR Extension The .AR extension is used to define the expression for Asynchronous Reset for a register. This is used in devices that have one or more product terms connected to the Asynchronous Reset of the register. [Picture] Figure 1-16. .ARMUX Extension In devices that have a multiplexer for connecting the Asynchronous Reset of a register directly to one or more pins, the .ARMUX extension is used to make the connection. It is possible that a device may have the capability to have Asynchronous Reset connected either to a pin or to a product term. In this case, the .AR extension is used to select the product term connection, whereas, the .ARMUX extension is used to connect the pin. [Picture] Figure 1-17. .CA Extension The .CA extension is used in a few special cases where devices have complementa array nodes. Devices that have this capability are the F501 and F502.(See Appendix B) [Picture] Figure 1-18. .CE Extension The .CE extension is used for D-CE registers. It serves to specify the input to the CE of the register. In devices that have D-CE registers, and the CE terms are not used, they must be set to binary 1 so that the registers behave the same as D registers. Failure to enable the CE terms will result in D registers that never change state. [Picture] Figure 1-19. .CK Extension.i.Extensions:CK ; The .CK extension is used to select a product term driven clock. Some devices have the capability to connect the clock for a register to one or more pins or to a product term. The .CK extension will select the product term. To connect the clock to a pin directly, use the .CKMUX extension. [Picture] Figure 1-20. .CKMUX Extension.i.Extensions:CK MUX; The .CKMUX extension is used to connect the clock input of a register to one of a set of pins. This is needed because some devices have a multiplexer for connecting the clock to one of a set of pins. This does not mean that the clock may be connected to any pin. Typically, the multiplexer will allow the clock to be connected to one of two pins. Some devices have a multiplexer for connecting to one of four pins. [Picture] Figure 1-21. .D Extension The .D extension is used to specify the D input to a D register. The use of the .D register actually causes the compiler to configure programmable macrocells as D registers. For outputs that have only D registered output, the .D extension must be used. If the .D extension is used for an output that does not have true D registers, the compiler will generate an error. [Picture] Figure 1-22. .DFB Extension.i.Extensions:DF B; The .DFB extension is used in special cases where a programmable output macrocell is configured as combinatorial but the D register still remains connected to the output. The .DFB extension provides a means to use the feedback from the register. Under normal conditions, when an output is configured as registered, the feedback from the register is selected by not specifying an extension. [Picture] Figure 1-23. .DQ Extension.i.Extensions:DQ ; The .DQ extension is used to specify an input D register. Use of the .DQ extension actually configures the input as registered. The .DQ extension is not used to specify Q output from an output D register. [Picture] Figure 1-24. .IMUX Extension.i.Extensions:IM UX; The .IMUX extension is an advanced extension which is used to select a feedback path. This is used in devices that have pin feedback from two I/O pins connected to a multiplexer. Only one of the pins may use the feedback path. [Picture] Figure 1-25. .INT Extension.i.Extensions:IN T; The .INT extension is used for selecting an internal feedback path. This could be used for combinatorial or registered output. The .INT extension provides combinatorial feedback. [Picture] Figure 1-26. .IO Extension.i.Extensions:IO ; The .IO extension is used to select pin feedback when the macrocell is configured as registered. [Picture] Figure 1-27. .IOAP Extension.i.Extensions:IO AP; The .IOAP extension is used to specify the expression for Asynchronous Preset in cases where there is registered pin feedback from an output macrocell. [Picture] Figure 1-28. .IOAR Extension The .IOAR extension is used to specify the expression for Asynchronous Reset.in cases where there is registered pin feedback from an output macrocell. [Picture] Figure 1-29. .IOCK Extension The .IOCK extension is used to specify a clock expression for a registered pin feedback that is connected to an output macrocell. [Picture] Figure 1-30. .IOD Extension.i.Extensions:IO D; The .IOD extension is used to specify feedback from a register that is connected to an output macrocell by the pin feedback path. [Picture] Figure 1-31. .IOL Extension.i.Extensions:IO L; The .IOL extension is used to specify feedback from a buried latch that is connected to an output macrocell by the pin feedback path. [Picture] Figure 1-32. .IOSP Extension.i.Extensions:IO SP; The .IOSP extension is used to specify the expression for Synchronous Preset in cases where there is registered pin feedback from an output macrocell. [Picture] Figure 1-33. .IOSR Extension.i.Extensions:IO SR; The .IOSR extension is used to specify the expression for Synchronous Reset in cases where there is registered pin feedback from an output macrocell. [Picture] Figure 1-34. .J and .K Extension The .J and .K extensions are used to specify J and K input to a JK register. The use of the .J and the .K extensions actually cause the compiler to configure the output as JK, if the macrocell is programmable. Equations for both J and K must be specified. If one of the inputs is not used, it must be set to binary 0 to disable it. [Picture] Figure 1-35. .L Extension The .L extension is used to specify input into a Latch. In devices with programmable macrocells, the use of the .L extension causes the compiler to configure the macrocell as a latched output. [Picture] Figure 1-36. .LE Extension.i.Extensions:LE ; The .LE extension is used to specify the latch enable equation for a latch. The .LE extension causes a product term to be connected to the latch enable. [Picture] Figure 1-37. .LEMUX Extension.i.Extensions:LE MUX; The .LEMUX extension is used to specify a pin connection for the latch enable. [Picture] Figure 1-38. .LFB Extension.i.Extensions:LF B; The .LFB extension is used in special cases where a programmable output macrocell is configured as combinatorial but the latch still remains connected to the output. The .LFB extension provides a means to use the feedback from the latch. Under normal conditions, when an output is configured as latched, the feedback from the latch is selected by using no extension. [Picture] Figure 1-39. .LQ Extension.i.Extensions:LQ ; The .LQ extension is used to specify an input latch. Use of the .LQ extension actually configures the input as latched. The .LQ extension is not used to specify Q output from an output latch. [Picture] Figure 1-40. .OE Extension.i.Extensions:OE ; The .OE extension is used to specify a product term driven output enable signal. [Picture] Figure 1-41. .OEMUX Extension.i.Extensions:OE MUX; The .OEMUX extension is used to connect the output enable to one of a set of pins. This is needed because some devices have a multiplexer for connecting the output enable to one of a set of pins. This does not mean that the output enable may be connected to any pin. Typically, the multiplexer will allow the output enable to be connected to one of two pins. Some devices have a multiplexer for connecting to one of four pins. [Picture] Figure 1-42. .S and .R Extension The .S and .R extensions are used to specify S and R input to a SR register. The use of the .S and the .R extensions actually cause the compiler to configure the output as SR, if the macrocell is programmable. Equations for both S and R must be specified. If one of the inputs is not used, it must be set to binary 0 to disable it. [Picture] Figure 1-43. .SP Extension The .SP extension is used to set the Synchronous Preset of a register to an expression. For example, the equation "Y.SP = A & B;" causes the register to be synchronously preset when A and B are logically true. [Picture] Figure 1-44. .SR Extension The .SR extension is used to define the expression for Synchronous Reset for a register. This is used in devices that have one or more product terms connected to the Synchronous Reset of the register. [Picture] Figure 1-45. .T Extension The .T extension specifies the T input for a T register. The use of the T extension itself causes the compiler to configure the macrocell as a T register. Special consideration should be given to devices with T registers and programmable polarity before the register. Since T registers toggle when the incoming signal is true, the behavior will be changed when the polarity is changed since the incoming signal is now inverted before reaching the register. It is best to declare pins that will use T registers as active high always. [Picture] Figure 1-46. .TFB Extension The .TFB extension is used in special cases where a programmable output macrocell is configured as combinatorial but the T register still remains connected to the output. The .TFB extension provides a means to use the feedback from the register. Under normal conditions, when an output is configured as registered, the feedback from the register is selected by using no extension. o .c3.Boolean Logic Review Table 1-12 lists the rules that the CUPL compiler uses for evaluating logic expressions. These basic rules are listed for reference purposes only. Table 1-12. Logic Evaluation Rules -------------------------------------------------- Commutative Property: A & B = B & A A # B = B # A Associative Property: A & (B & C) = (A & B) & C A # (B # C) = (A # B) # C Distributive Property: A & (B # C) = (A & B) # (A & C) A # (B & C) = (A # B) & (A # C) Absorptive Property: A & (A # B) = A A # (A & B) = A DeMorgan's Theorem: !(A & B & C) = !A # !B # !C !(A # B # C) = !A & !B & !C XOR Identity: A $ B = (!A & B) # (A & !B) !(A $ B) = A $ !B = !A $ B = (!A & !B) # (A& B) Theorems: A & 0 = 0 A & 1 = A A # 0 = A A # 1 = 1 A & A = A A & !A = 0 A # A = A A # !A = 1 -------------------------------------------------- O .C3.EXPRESSIONS Expressions are combinations of variables and operators that produce a single result when evaluated. An expression may be composed of any number of sub-expressions. Expressions are evaluated according to the precedence of the particular operators involved. When operators with the same precedence appear in an expression, evaluation order is taken from left to right. Parentheses may be used to change the order of evaluation; the expression within the innermost set of parentheses is evaluated first. In Table 1-13, note how the order of evaluation and use of parentheses affect the value of the expression. Table 1-13. Sample Expressions ----------------------------------------------------------------- Expression Result Comments A # B & C A # B & C (A # B) & C A & C Parentheses change order # B & C !A & B !A & B !(A & B) !A # !B DeMorgan's Theorem A # B & C # D A # D # B & C A # B & (C # D) A # B & C # B & D Parentheses change order ----------------------------------------------------------------- O .C3.LOGIC EQUATIONS Logic equations are the building blocks of the CUPL language. The form for logic equations is as follows: [!] var [.ext] = exp ; where var is a single variable or a list of indexed or non-indexed variables defined according to the rules for the list notation (see the subtopic, List Notation in this chapter). When a variable list is used, the expression is assigned to each variable in the list. .ext is an optional extension to assign a function to the major nodes inside a programmable device (see Table 1-11). exp is an expression; that is, a combination of variables and operators (see "Expressions" in this chapter). = is the assignment operator; it assigns the value of an expression to a variable or set of variables. ! is the complement operator. The complement operator can be used to express the logic equation in negative true logic. The operator directly precedes the variable name (no spaces) and denotes that the expression on the right side is to be complemented before it is assigned to the variable name. Use of the complement operator on the left side is provided solely as a convenience. The equation may just as easily be written by complementing the entire expression on the right side. Older logic design software that did not provide the automatic DeMorgan capability (output polarity assigned according to the pin variable declaration) required the use of the complement operator when using devices with inverting buffers. Place logic equations in the "Logic Equation" section of the source file provided by the template file. Logic equations are not limited solely to pin (or node) variables, but may be written for any arbitrary variable name. A variable defined in this manner is an intermediate variable. An intermediate variable name can be used in other expressions to generate logic equations or additional intermediate variables. Writing logic equations in this "top down" manner yields a logic description file that is generally easier to read and comprehend. Place intermediate variables in the "Declarations and Intermediate Variable Definitions" section of the source file. The following are some examples of logic equations: SEL_0 = A15 & !A14; /* A simple, decoded output pin */ Q0.D = Q1 & Q2 & Q3; /* Output pin w/ D flip-flop */ Q1.J = Q2 # Q3; /* Output pin w/ JK flip-flop */ Q1.K = Q2 & !Q3; MREQ = READ # WRITE; /* Intermediate Variable */ SEL_1=MREQ & A15; /* Output intermediate var */ [D0..3] = 'h'FF; /* Data bits assigned to constant*/ [D0..3].oe = read; /* Data bits assigned to variable*/ .C4.APPEND STATEMENTS In standard logic equations, normally only one expression is assigned to a variable. The APPEND statement enables multiple expressions to be assigned to a single variable. The format is as follows: APPEND [!]var[.ext] = expr ; where ! is the complement operator to optionally define the polarity of the variable. var is a single variable or a list of indexed or non-indexed variables in standard list format. .ext is an optional extension that defines the function of the variable. = is the assignment operator. expr is a valid expression. ; is a semicolon to mark the end of the statement. The expression that results from multiple APPEND statements is the logical OR of all the APPEND statements. If an expression has not already been assigned to the variable, the first APPEND statement is treated as the first assignment. The following example shows several APPEND statements. APPEND Y = A0 & A1 ; APPEND Y = B0 & B1 ; APPEND Y = C0 & C1 ; The three statements above are equivalent to the following equation. Y = (A0 & A1) # (B0 & B1) # (C0 & C1) ; The APPEND statement is useful in adding additional terms (such as reset) to state-machine variables or constructing user-defined functions (see the subtopics, State Machine Syntax and User-Defined Functions in this chapter). o .c3.Set Operations All operations that are performed on a single bit of information, for example, an input pin, a register, or an output pin, may be applied to multiple bits of information grouped into sets. Set operations can be performed between a set and a variable or expression, or between two sets. The result of an operation between a set and a single variable (or expression) is a new set in which the operation is performed between each element of the set and the variable (or expression). For example [D0, D1, D2, D3] & read evaluates to: [D0 & read, D1 & read, D2 & read, D3 & read] When an operation is performed on two sets, the sets must be the same size (that is, contain the same number of elements). The result of an operation between two sets is a new set in which the operation is performed between elements of each set. For example [A0, A1, A2, A3] & [B0, B1, B2, B3] evaluates to: [A0 & B0, A1 & B1, A2 & B2, A3 & B3] Bit field statements (see the subtopic, Bit Field Declaration Statements in this chapter) may be used to group variables into a set that can be referenced by a single variable name. For example, group the two sets of variables in the above operation as follows: FIELD a_inputs = [A0, A1, A2 A3] ; FIELD b_inputs = [B0, B1, B2, B3] ; Then perform a set operation between the two sets, for example, an AND operation, as follows: a_inputs & b_inputs When numbers are used in set operations, they are treated as sets of binary digits. A single octal number represents a set of three binary digits, and a single decimal or hexadecimal number represents a set of four binary digits. Table 1-14 lists the representation of numbers as sets. Table 1-14. Equivalent Binary Sets ------------------------------------------------------------ Number Binary Set 'O'X [X, X, X] 'H'X [X,X,X,X] 'O'0 [0, 0, 0] 'H'0 [0,0,0,0] 'O'1 [0, 0, 1] 'H'1 [0,0,0,1] 'O'2 [0, 1, 0] 'H'2 [0,0,1,0] 'O'3 [0, 1, 1] 'H'3 [0,0,1,1] 'O'4 [1, 0, 0] 'H'4 [0,1,0,0] 'O'5 [1, 0, 1] 'H'5 [0,1,0,1] 'O'6 [1, 1, 0] 'H'6 [0,1,1,0] 'O'7 [1, 1, 1] 'H'7 [0,1,1,1] 'D'0 [0,0,0,0] 'H'8 [1,0,0,0] 'D'1 [0,0,0,1] 'H'9 [1,0,0,1] 'D'2 [0,0,1,0] 'H'A [1,0,1,0] 'D'3 [0,0,1,1] 'H'B [1,0,1,1] 'D'4 [0,1,0,0] 'H'C [1,1,0,0] 'D'5 [0,1,0,1] 'H'D [1,1,0,1] 'D'6 [0,1,1,0] 'H'E [1,1,1,0] 'D'7 [0,1,1,1] 'H'F [1,1,1,1] 'D'8 [1,0,0,0] 'D'9 [1,0,0,1] ------------------------------------------------------------ Numbers may be effectively used as "bit masks" in logic equations using sets. An example of this application is the following 4-bit counter. field count = [Q3, Q2, Q1, Q0]; count.d = 'b' 0001 & (!Q0) # 'b' 0010 & (Q1 $ Q0) # 'b' 0100 & (Q2 $ Q1 & Q0) # 'b' 1000 & (Q3 $ Q2 & Q1 & Q0); The equivalent logic equations written without set notation are as follows: Q0.d = !Q0; Q1.d = Q1 $ Q0; Q2.d = Q2 $ Q1 & Q0; Q3.d = Q3 $ Q2 & Q1 & Q0; .c4.Equality Operations Unlike other set operations, the equality operation evaluates to a single Boolean expression. It checks for bit equality between a set of variables and a constant. The format for the equality operation is as follows: Format 1. [var, var, ... var]:constant ; Format 2. bit_field_var:constant ; where [var, var, ... var] is a list of variables in shorthand notation. constant is a number (hexadecimal by default). bit_field_var is a variable defined using a bit field statement. : is the equality operator. ; is a semicolon used to mark the statement end. ------------------------------------------------------------- Note Square brackets do not indicate optional items, but delimit variables in a list. -------------------------------------------------------------- Format 1 is used between a list of variables and a constant value. Format 2 is used between a bit field variable and a constant value. The bit positions of the constant number are checked against the corresponding positions in the set. Where the bit position is a binary 1, the set element is unchanged. Where the bit position is a binary 0, the set element is negated. Where the bit position is a binary X, the set element is removed. The resulting elements are then ANDed together to create a single expression. In the following example, hexadecimal D (binary 1101) is checked against A3, A2, A1, and A0. select = [A3..0]:'h'D ; The set elements A3, A2, and A0 remain unchanged because the corresponding bit position is one or true. Set element A1 is negated because its corresponding bit position is zero or false. Therefore, the above expression is equivalent to the following expression: select = A3 & A2 & !A1 & A0 ; In the following example, binary 1X0X is checked against A3, A2, A1, A0. select = [A3..0]:'b'1X0X ; The set element A3 remains unchanged because the corresponding bit position is one or true. Set element A1 is negated because its corresponding bit position is zero or false. Set elements A2 and A0 are removed from the expression because the corresponding bit positions are "don't-cared." Therefore, the above expression is equivalent to the following equation: select = A3 & !A1 ; In addition to address decoding, the equality operator can be used to specify a counter or state machine. For example, a 4-bit counter can be specified using the following notation: FIELD count = [Q0..3]; Q0.J = count:0 # count:2 # count:4 # count:6 # count:8 # count:A # count:C # count:E ; Q0.K = count:1 # count:3 # count:5 # count:7 # count:9 # count:B # count:D # count:F ; Q1.J = count:1 # count:5 # count:9 # count:D ; Q1.K = count:3 # count:7 # count:B # count:F ; Q2.J = count:3 # count:B ; Q2.K = count:7 # count:F ; Q3.J = count:7 ; Q3.K = count:F ; The equality operator can also be used with a set of variables that are to be operated upon identically. The following syntax can be used as a time-saving convenience: [var, var, ... , var]:op which is equivalent to: var op var op ... var where op is the &, # or $ operator (or its equivalent if an alternate set of operators has been defined). var is any variable name. For example, the following three expressions [A3,A2,A1,A0]:& [B3,B2,B1,B0]:# [C3,C2,C1,C0]:$ are equivalent respectively to: A3 & A2 & A1 & A0 B3 # B2 # B1 # B0 C3 $ C2 $ C1 $ C0 The equality operation can be used with an equivalent binary set to create a function table description of the output values. For example, in the following Binary-to-BCD code converter, output values are assigned by using the equality operation to define the inputs, and equivalent binary sets to group the output. FIELD input = [in3..0] ; FIELD output = [out4..0] ; /* in3..0 ->out4..0*/ $DEFINE L 'b'0 $DEFINE H 'b'1 output = input:0 & [L,L,L,L,L] # input:1 & [L,L,L,L,H] # input:2 & [L,L,L,H,L] # input:3 & [L,L,L,H,H] # input:4 & [L,L,H,L,L] # input:5 & [L,L,H,L,H] # input:6 & [L,L,H,H,L] # input:7 & [L,L,H,H,H] # input:8 & [L,H,L,L,L] # input:9 & [L,H,L,L,H] # input:A & [H,L,L,L,L] # input:B & [H,L,L,L,H] # input:C & [H,L,L,H,L] # input:D & [H,L,L,H,H] # input:E & [H,L,H,L,L] # input:F & [H,L,H,L,H]; $UNDEF L $UNDEF H Indexed Variables Bit Fields and Equality. Indexed variables, field statements and the range function operate with each other in tight union. This section will attempt to illustrate this relationship. As discussed earlier in this chapter, indexed variables can be used as an easy way to declare multiple variables with few actual lines of code. For example Pin [2..4] = [AD0..2]; expands to: Pin 2 = AD0; Pin 3 = AD1; Pin 4 = AD2; The FIELD statement is used to group a set of related signals into one element. It works by using a 32 bit field where each bit in the field represents one of the members of the field. If there are less than 32 members then the extra bits are ignored. For example: Pin 2 = VAR_A; Pin 3 = VAR_B; Pin 4 = VAR_C; Pin 15 = ROM_SEL; FIELD ADDR = [VAR_A,VAR_B,VAR_C]; The following figure shows how the variables VAR_A, VAR_B and VAR_C map into the bit field. [Picture] Figure 1-47.Bit field mapping of member variables Now suppose that we had an output as follows: ROM_SEL = ADDR:3; The contents of the bit field for this equation would be as follows: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX011" This would result in the following equations: ROM_SEL = !VAR_A & VAR_B & VAR_C; When using indexed variables, the internal representation changes slightly. The index number of the variable determines its position in the bit field. Therefore, VAR0 always resides in bit position 0 regardless of the declaration of the field. The two following declarations both have the identical internal representation. field ADDR = [VAR0, VAR1, VAR2]; field ADDR = [VAR2, VAR1, VAR0]; [Picture] Figure 1-48. Bit field representation with indexed variables Now suppose that we had an output as follows: ROM_SEL = ADDR:3; The contents of the bit field for this equation would be as follows: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX011" This would result in the following equations: ROM_SEL = !VAR2 & VAR1 & VAR0; If we take a set of variables that use a higher index we can see that the way indexed variables are handled may affect the output differently than we expect. If the variables used are VAR17, VAR18 and VAR19 then the bit map changes accordingly. The equivalence with 3 now does not work because 3 only maps into bits 0, 1 and 2. What needs to be done is to add zeroes to move the desired equivalence up to the desired range. Now suppose that we had an output as follows: FIELD ADDR = [VAR18, VAR17, VAR16]; ROM_SEL = ADDR:3; The variables would map into the bit field ADDR as follows: [Picture] Figure 1-49. Bit field representation with indexed variables not starting at 0 If we attempt to apply an equivalence of three to this bit field, the bits will not match correctly. The following line shows how the constant three maps onto the bit field. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX011" Notice that the significant bits in the above equivalence does not map over the bits representing the variables. What needs to be done to make this correct is to append enough zeroes to the end of the constant so that it represents what we truly want. ROM_SEL = ADDR:30000; This will now produce the correct results since the bit map from this constant is as follows: "XXXXXXXXXXXXX0110000000000000000" ROM_SEL = !VAR18 & VAR17 & VAR16; .c4.Range Operations The range operation is similar to the equality operation except that the constant field is a range of values instead of a single value. The check for bit equality is made for each constant value in the range. The format for the range operation is as follows: 1. [var, var, ... var]:[constant_lo..constant_hi] ; 2. bit_field_var:[constant_lo..constant_hi] ; where: [var, var, ... var] is a list of variables in shorthand notation. bit_field_var is a variable that has been defined using a bit field statement. : is the equality operator. ; is a semicolon used to end the statement. [constant_lo constant_hi] are numbers (hexadecimal by default) that define the range operation. ------------------------------------------------------------ Note Square brackets do not indicate optional items, but delimit items in a list ------------------------------------------------------------ Format 1 specifies the range operation between a list of variables and a range of constant values. Format 2 specifies a range operation between a bit field variable and a range of constant values. All numbers greater than or equal to constant_lo and less than or equal to constant_hi are used to create ANDed expressions as in the equality operation. The sub-expressions are then ORed together to create the final evaluated expression. For example, the RANGE notation can be used to look for a decoded hex value between 1100 and 1111 on an address bus containing A3, A2, A1, and A0. First, define the address bus, as follows: FIELD address = [A3..A0] Then write the RANGE equation: select = address:[C..F] ; This is equivalent to the following equation: select = address:C # address:D # address:E # address:F ; This equation expands to: select = A3 & A2 & !A1 & !A0 # A3 & A2 & !A1 & A0 # A3 & A2 & A1 & !A0 # A3 & A2 & A1 & A0 ; The logic minimization capabilities within CUPL reduce the previous equation into a single product term equivalent. The range minimization works as follows. First, lines one and two are combined and lines three and four are combined to produce the following equation: select = A3 & A2 & !A1 & (!A0 # A0) # A3 & A2 & A1 & (!A0 # A0) ; Since the expression (!A0 # A0) is always true, it can be removed from the equation, and the equation reduces to: select = A3 & A2 & !A1 # A3 & A2 & A1 ; By the same process, the equation reduces to the following: select = A3 & A2 & (!A1 # A1) ; Since the expression (!A1 # A1) is always true, removing it reduces the equation to the single product term: select = A3 & A2 ; When either the equality or range operations are used with indexed variables, the CONSTANT field must contain the same number of significant bit locations as the highest index number in the variable list. Index positions not in the pin list or field declaration are DON'T CAREd in the operation. In the following example, pin assignments are made, an address bus is declared, and a decoded output is asserted over the hexadecimal memory address .range 8000 through BFFF. PIN [1..4] = [A15..12] ; FIELD address = [A15..12] ; chip_select = address:[8000..BFFF] ; Although the variables A15, A14, A13, and A12 are the only address inputs to the device, a full 16-bit address is used in the range expression. The most significant bit, A15, determines that the field is a 16-bit field. The lower order address bits (A0 through A11) are effectively DON'T CAREd in the equation, because the variable index numbers are used to determine bit position. Even though the lower order bits are not present in the device, the constant value is written as though they did exist, generating a more meaningful expression in terms of documentation. Consider, for example, the following application that decodes a microprocessor address for an I/O port: PIN [3..6] = [A7..10] ; FIELD ioaddr = [A7..10]; /* order of field declaration is not important when using indexed variables */ io_port = ioaddr:[400..6FF] ; Since the most significant bit is A10, an 11-bit constant field is required (although three hex digits form a 12-bit address, the bit position for A11 is ignored). Address bits A0 through A6 are DON'T CAREd in the expression. Without the bit position justification, the range equation would be written as io_port = ioaddr:[8..D] ; This expression doesn't clearly document the actual I/O address range that is desired. The original equation without the range operation could be written as follows: io_port = A10 & !A9 & !A8 & !A7 # A10 & !A9 & !A8 & A7 # A10 & !A9 & A8 & !A7 # A10 & !A9 & A8 & A7 # A10 & A9 & !A8 & !A7 # A10 & A9 & !A8 & A7 ; CUPL reduces this equation to the following: io_port = A10 & !A9 # A10 & A9 & !A8 ; -------------------------------------------------- Note Careless use of the range feature may result in the generation of huge numbers of product terms, particularly when fields are composed of variables with large index numbers. The algorithm for the range does a bit-by-bit comparison of the two constant values given in the range operation, starting with index variable 0 (whether it exists in the field or not). If the value of the bit position for constant_lo is less than that for constant_hi, the variable for that bit position is not used in the generation of the ANDed expressions. When the value of the bit position for constant_lo is equal to or greater than that for constant_hi, an ANDed expression is created for all constant values between this new value and the original constant_hi value. -------------------------------------------------- For example, consider the following logic equation that uses the range function on a 16-bit address field. field address = [A15..12] ; board_select = address:[A000..DFFF] ; Figure 1-50 shows how the CUPL algorithm treats this equation. [Picture] Figure 1-50. Range Function Algorithm The algorithm ignores all bit positions lower than position 13, because for these positions constant_lo is less than constant_hi. Figure 1-51 shows the result. [Picture] Figure 1-51. Range Function Results The following two product terms are generated as a result of the range function in Figure 1-51. A15 & A14 & !A13 A15 & !A14 & A13 The following equation is another example using the range function. board_select = address:[A000..D000] ; Because the values of constant_lo and constant_hi match for the least significant bits, the algorithm generates product terms as follows: 1010 0000 0000 0000 1010 0000 0000 0001 1010 0000 0000 0010 1010 0000 0000 0011 . 1100 1111 1111 1111 1101 0000 0000 0000 The number of product terms generated is over twelve thousand (4096 x 3 + 1). This number of product terms would probably produce an "out of memory" error message because CUPL cannot hold this many product terms in memory at one time. o .c3.Truth Tables Sometimes the clearest way to express logic descriptions is in tables of information. CUPL provides the TABLE keyword to create tables of information. The format for using TABLE is as follows: TABLE var_list_1 => var_list_2 { input_n => output_n ; . . input_n => output_n; } where var_list_1 defines the input variables. var_list_2 defines the output variables. input_n is a decoded value (hex by default) or a list of decoded values of var_list_1. output_n is a decoded value (hex by default) of var_list_2. { } are braces to begin and end the assignment block. => specifies a one-to-one assignment between variable lists, and between input and output numbers. First, define relevant input and output variable lists, and then specify one-to-one assignments between decoded values of the input and output variable lists. Don't-care values are supported for the input decode value, but not for the output decode value. A list of input values can be specified to make multiple assignments in a single statement. The following block describes a simple hex-to-BCD code converter: FIELD input = [in3..0] ; FIELD output = [out4..0] ; TABLE input => output { 0=>00; 1=>01; 2=>02; 3=>03; 4=>04; 5=>05; 6=>06; 7=>07; 8=>08; 9=>09; A=>10; B=>11; C=>12; D=>13; E=>14; F=>15; } The following example illustrates the use of a list of input numbers to do address decoding for various-sized RAM, ROM, and I/O devices. The address range is decoded according to the rules (in terms of indexed variable usage) for the range operation (see the subtopic, Range Operations in this chapter). PIN [1..4] = [a12..15]; /* Upper 4 address*/ PIN 12 = !RAM_sel ; /* 8K x 8 RAM */ PIN 13 = !ROM_sel ; /* 32K x 8 ROM */ PIN 14 = !timer_sel; /* 8253 Timer */ FIELD address = [a15..12] ; FIELD decodes = [RAM_sel,ROM_sel,timer_sel] ; TABLE address => decodes { [1000..2FFF] => 'b'100; /* select RAM */ [5000..CFFF] => 'b'010; /* select ROM */ F000 => 'b'001; /* select timer */ } o .c3.State-Machine Syntax This section describes the CUPL state machine syntax, providing a brief overview of its use, a definition of a state machine, and explaining in detail the CUPL state machine syntax. The state-machine approach used with the CUPL compiler-based PLD language permits bypassing the gate and equation level stage in logic design and to move directly from a system-level description to a PLD implementation. Additionally, unlike assembler-based approaches, the state-machine approach allows clear documentation of design, for future users. o .c3.State-Machine Model A synchronous state machine is a logic circuit with flip-flops. Because its output can be fed back to its own or some other flip-flop's input, a flip-flop's input value may depend on both its own output and that of other flip-flops; consequently, its final output value depends on its own previous values, as well as those of other flip-flops. The CUPL state-machine model, as shown in Figure 1-52, uses six components: inputs, combinatorial logic, storage registers, state bits, registered outputs, and non-registered outputs. [Picture] Figure 1-52. State Machine Model The following definitions refer to the timing diagram in Figure 1-52. .c4.Inputs Inputs are signals entering the device that originate in some other device. .c4.Combinatorial Logic Combinatorial Logic is any combination of logic gates (usually AND-OR) that produces an output signal that is valid Tpd (propagation delay time) nsec after any of the signals that drive these gates changes. Tpd is the delay between the initiation of an input or feedback event and the occurrence of a non-registered output. .c4.State Bits State Bits are storage register outputs that are fed back to drive the combinatorial logic. They contain the present-state information. .c4.Storage Registers Storage Registers are any flip-flop elements that receive their inputs from the state machine's combinatorial logic. Some registers are used for state bits: others are used for registered outputs. The registered output is valid Tco (clock to out time) nsec after the clock pulse occurs. Tco is the time delay between the initiation of a clock signal and the occurrence of a valid flip-flop output. Figure 1-53 shows the timing relationships between the state machine components. [Picture] Figure 1-53. State Machine Timing Diagram .c4.Inputs For the system to operate properly, the PLD's requirements for setup and hold times must be met. For most PLDs, the setup time (Tsu) usually includes both the propagation delay of the combinatorial logic and the actual setup time of the flip-flops. Tsu is the time it takes for the result of either feedback or an input event to appear at the input to a flip-flop. A subsequent clock input cannot be applied until this result becomes valid at the flip-flop's input. The flip-flops can be either D, D-CE, J- K, S-R, or T types. .c4.Nonregistered Outputs Non-registered Outputs - are outputs that come directly from the combinatorial logic gates. They may be functions of the state bits and the input signals (and have asynchronous timing), or they may be purely dependent on the current state-bit values, in which case they become valid Tco + Tpd nsec after an active clock edge occurs. .c4.Registered Outputs Registered Outputs are outputs that come from the storage registers but are not included in the actual state-bit field (that is, a bit field composed of all the state bits). State- machine theory requires that the setting or resetting of these registered outputs depends on the transition from a present state to a next state. This allows a registered output to be either set or reset in a given state depending upon how the machine came to be in that state. Thus, a registered output can assume a hold operation mode. In the hold mode, the registered output will remain at its last value as long as the current state transition does not specify an operation on that registered output. ================================================================= Note This hold mode of operation is available only for devices which use D-CE, J-K, or S-R type flip-flops. ================================================================= o .c3.Syntax To implement the state machine model, CUPL supplies a syntax that allows the describing of any function in the state machine. .i. Keywords:SEQUENCE;.i.Keywo rds:PRESENT;The SEQUENCE keyword identifies the outputs of a state machine and is followed by statements that define the function of the state machine. The format for the SEQUENCE syntax is as follows: SEQUENCE state_var_list { PRESENT state_n0 statements ; . . . PRESENT state_nn statements ; } where state_var_list is a list of the state bit variables used in the state machine block. The variable list can be represented by a field variable. state_n is the state number and is a decoded value of the state_variable_list and must be unique for each PRESENT statement. statements are any of the conditional, next, or output statements described in the following subsections of this section. ; is a semicolon used to mark the end of a statement. { } are braces to mark the beginning and end of the state machine description. Symbolic names defined with the $DEFINE command may be used to represent state_numbers. The SEQUENCE keyword causes the storage registers and registered output types generated to be the default type for the target device. For example, by using the SEQUENCE keyword in a design with a P16R8 target device, the state storage registers and registered outputs will be generated as D-type flip-flops. The storage registers for certain devices can be programmed as more than one type. In the case of the F159 (Signetics PLS159), they can be either D or J-K type flip-flops. By default, using the SEQUENCE statement with a design for the F159 will cause the state storage registers and registered outputs to be generated as J-K type flip-flops. To override this default, the SEQUENCED keyword would be used in place of the SEQUENCE keyword. This would cause the state registers and registered outputs to be generated as D-type flip-flops. Along with the SEQUENCE and SEQUENCED keywords are the SEQUENCEJK, SEQUENCERS, and SEQUENCET keywords. Respectively, they cause the state registers and registered outputs to be generated as J-K, S-R, and T-type flip-flops. The subsections that follow describe the types of statements that can be written in the state-machine syntax. Statements use the IF, NEXT, OUT and DEFAULT keywords. .c4.Unconditional NEXT Statement This statement describes the transition from the present state to a specified next state. The format is: PRESENT state_n NEXT state_n ; where state_n is a decoded value of the state bit variables that are the output of the state machine. A symbolic name can be assigned with the $DEFINE command to represent state_n. Because the statement is unconditional (that is, it describes the transition to a specific next state), there can be only one NEXT statement for each PRESENT statement. The following example specifies the transition from binary state 01 to binary state 10. PRESENT 'b'01 NEXT 'b'10 ; Figure 1-54 shows the transition described in the example above. [Picture] Figure 1-54. Unconditional NEXT Statement Diagram For the transition described in the example and figure above, CUPL generates the following equations, depending on the type of flip-flop that is specified: D-Type Flip-Flop APPEND Q1.D = !Q1 & Q0; APPEND Q0.D = 'b'0; /* implicitly resets */ J-K-Type Flip-Flop APPEND Q1.J = !Q1 & Q0; APPEND Q1.K = 'b'0; APPEND Q0.J = 'b'0; APPEND Q0.K = !Q1 & Q0; S-R-Type Flip-Flop APPEND Q1.S = !Q1 & Q0; APPEND Q1.R = 'b'0; APPEND Q0.S = 'b'0; APPEND Q0.R = !Q1 & Q0; D-CE-Type Flip-Flop APPEND Q1.D = !Q1 & Q0; APPEND Q1.CE = !Q1 & Q0; APPEND Q0.D = 'b'0; APPEND Q0.CE = !Q1 & Q0; T-Type Flip-Flop APPEND Q1.T = !Q1 & Q0; APPEND Q0.T = !Q1 & Q0; See the subtopic, APPEND Statements in this chapter for a description of the APPEND command. .c4.Conditional NEXT Statement This statement describes the transition from the present state to a next state if the conditions in a specified input expression are met. The format is as follows. PRESENT state_n IF expr NEXT state_n; . . . IF expr NEXT state_n; [DEFAULT NEXT state_n;] where state_n is a decoded value of the state bit variables that are the output of the state machine. expr is any valid expression (see the subtopic, Expressions in this chapter). ; is a semicolon used to mark the end of a statement. ======================================== Note The square brackets indicate optional items. ======================================== The value for each state number must be unique. More than one conditional statement can be specified for each PRESENT statement. The DEFAULT statement is optional. It describes the transition from the present state to a next state if none of the conditions in the specified conditional statements are met. In other words, it describes the condition that is the complement of the sum of all the conditional statements. ================================================================= Note Be careful when using the DEFAULT statement. Because it is the complement of all the conditional statements, the DEFAULT statement can generate an expression complex enough to greatly slow CUPL operation. In most applications, one or two conditional statements can be specified instead of the DEFAULT statement. ================================================================= The following is an example of two conditional NEXT statements without a DEFAULT statement. PRESENT 'b'01 IF INA NEXT 'b'10; IF !INA NEXT 'b'11; Figure 1-55 shows the transitions described by the above example. [Picture] Figure 1-55. Conditional NEXT Statement Diagram For the transitions described in the above example and figure, CUPL generates the following equations, depending on the type of flip-flop that is specified: D-Type Flip-Flop APPEND Q1.D = !Q1 & Q0; APPEND Q0.D = !Q1 & Q0 & !INA; D-CE-Type Flip-Flop APPEND Q1.D = !Q1 & Q0; APPEND Q1.CE = !Q1 & Q0; APPEND Q0.D = !Q1 & Q0 & !INA; APPEND Q0.CE = !Q1 & Q0 & INA; J-K-Type Flip-Flop APPEND Q1.J = !Q1 & Q0; APPEND Q1.K = 'b'0; APPEND Q0.J = 'b'0; APPEND Q0.K = !Q1 & Q0 & INA; S-R-Type Flip-Flop APPEND Q1.S = !Q1 & Q0; APPEND Q1.R = 'b'0; APPEND Q0.S = 'b'0; APPEND Q0.R = !Q1 & Q0 & INA; T-Type Flip-Flop APPEND Q1.T = !Q1 & Q0; APPEND Q0.T = !Q1 & Q0 & INA; The following is an example of two conditional statements with a DEFAULT statement. PRESENT 'b'01 IF INA & INB NEXT 'b'10'; IF INA & !INB NEXT 'b'11; DEFAULT NEXT 'b'00; Figure 1-56 shows the transitions described by the above example. Note the equation generated by the DEFAULT statement. [Picture] Figure 1-56. Conditional NEXT Statement with Default Diagram For the transitions described in the above example and figure, CUPL generates the following equations, depending on the type of flip-flop that is specified. D-Type Flip-Flop APPEND Q1.D = !Q1 & Q0 & INA; APPEND Q0.D = !Q1 & Q0 & INA & !INB; D-CE-Type Flip-Flop APPEND Q1.D = !Q1 & Q0 & INA; APPEND Q1.CE = !Q1 & Q0 & INA; APPEND Q0.D = 'b'0; APPEND Q0.CE = !Q1 & Q0 & !INA # !Q1 & Q0 & INA & INB; J-K-Type Flip-Flop APPEND Q1.J = !Q1 & Q0 & INA; APPEND Q1.K = 'b'0; APPEND Q0.J = 'b'0; APPEND Q0.K = !Q1 & Q0 & INA & INB # !Q1 & Q0 & !INA; S-R-Type Flip-Flop APPEND Q1.S = !Q1 & Q0 & INA; APPEND Q1.R = 'b'0; APPEND Q0.S = 'b'0; APPEND Q0.R = !Q1 & Q0 & INA & INB # !Q1 & Q0 & !INA; T-Type Flip-Flop APPEND Q1.T = !Q1 & Q0 & INA; APPEND Q0.T = !Q1 & Q0 & !INA # !Q1 & Q0 & INA & INB; .c4.Unconditional Synchronous Output Statement This statement describes a transition from the present state to a next state, specifies a variable for the registered (synchronous) outputs associated with the transition, and defines whether the variable is logically asserted. The format is as follows: PRESENT state_n NEXT state_n OUT [!]var... OUT [!]var; where state_n is a decoded value (default hex) of the state bit variables that are the output of the state machine. var is a variable name declared in the pin declarations. It is not a variable from the SEQUENCE state_var_list. ! is the complement operator; use it to logically negate the variable, or omit it to logically assert the variable. ; is a semicolon used to mark the end of a statement. ======================================== Note The square brackets indicate optional items. ======================================== The PIN declaration statement (see the subtopic, Pin Declaration Statements in this chapter) determines whether the variable, when asserted, is active-HI or active-LO. For example, if the variable has the negation symbol (!var) in the pin declaration, when it is asserted in the OUT statement, its value is active-LO. ================================================================= Note Use the negation mode only for D-CE, J-K, T or S-R type flip-flops; D-type flip-flops implicitly reset when assertion is not specified. ================================================================= The following is an example of an unconditional synchronous output statement. PRESENT 'b'01 NEXT 'b'10 OUT Y OUT !Z ; Figure 1-57 shows the transition and output variable definition described in the example above. [Picture] Figure 1-57. Unconditional Synchronous Output Diagram For the synchronous output definitions in the example and figure above, CUPL generates the following equations, depending on the type of flip-flop that is specified. D-Type Flip-Flop APPEND Y.D = !Q1 & Q0; (not defined for Z output) D-CE Type Flip-Flop APPEND Y.D = !Q1 & Q0; APPEND Y.CE = !Q1 & Q0; APPEND Z.D = 'b'0; APPEND Z.CE = !Q1 & Q0; J-K-Type Flip-Flop APPEND Y.J = !Q1 & Q0; APPEND Y.K = 'b'0; APPEND Z.J = 'b'0; APPEND Z.K = !Q1 & Q0; S-R-Type Flip-Flop APPEND Y.S = !Q1 & Q0; APPEND Y.R = 'b'0; APPEND Z.S = 'b'0; APPEND Z.R = !Q1 & Q0; T-Type Flip-Flop APPEND Y.T = !Q1 & Q0; APPEND Z.T = !Q1 & Q0; .c4.Conditional Synchronous Output Statement This statement describes a transition from the present state to a next state, specifies a variable for the registered (synchronous) outputs associated with the transition, and defines whether the variable is logically asserted if the conditions specified in an input expression are met. The format is as follows: PRESENT state_n IF expr NEXT state_n OUT [!]var...OUT [!] var; . . IF expr NEXT state_n OUT [!]var...OUT [!]var; [ [DEFAULT] NEXT state_n OUT [!]var;] where state_n is a decoded value (default hex) of the state bit variables that are the output of the state machine. var is a variable name declared in the pin declarations. It is not a variable from the SEQUENCE state_variable_list. ! is the complement operator; use it to logically negate the variable, or omit it to logically assert the variable. ; is a semicolon used to mark the end of a statement. expr is any valid expression. ================================================== Note The square brackets indicate optional items. ================================================== The PIN declaration statement (see the subtopic, Pin Declaration Statements in this chapter) determines whether the variable, when asserted, is active-HI or active-LO. For example, if the variable has the negation symbol (!var) in the pin declaration, when it is asserted in the OUT statement, its value is active-LO. ======================================================== Note Use the negation mode only for J-K or S-R-type flip-flops. D-type flip-flops implicitly reset when assertion is not specified. ======================================================== The DEFAULT statement is optional. It describes the transition from the present state to a next state, and defines the output variable, if none of the conditions in the specified conditional statements are met. In other words, it describes the condition that is the complement of the sum of all the conditional statements. Note Be careful when using the DEFAULT statement. Because it is the complement of all the conditional statements, the DEFAULT statement can generate an expression complex enough to greatly slow CUPL operation. In most applications, one or two conditional statements can be specified instead of the DEFAULT statement. The following is an example of conditional synchronous output statements without a DEFAULT statement. PRESENT 'b'01 IF INA NEXT 'b'10 OUT Y; IF !INA NEXT 'b'11 OUT Z; Figure 1-58 shows the transitions and outputs defined by the statements in the example above. [Picture] Figure 1-58. Synchronous Conditional Output Diagram For the synchronous output definitions in the example and figure above, CUPL generates the following equations, depending on the type of flip-flop specified: D-Type Flip-Flop APPEND Y.D = !Q1 & Q0 & INA; APPEND Z.D = !Q1 & Q0 & !INA; D-CE-Type Flip-Flop APPEND Y.D = !Q1 & Q0 & INA; APPEND Y.CE = !Q1 & Q0 & INA; APPEND Z.D = !Q1 & Q0 & !INA; APPEND Z.CE = !Q1 & Q0 & !INA; J-K-Type Flip-Flop APPEND Y.J = !Q1 & Q0 & INA; APPEND Y.K = 'b'0; APPEND Z.J = !Q1 & Q0 & !INA; APPEND Z.K = 'b'0; S-R-Type Flip Flop APPEND Y.S = !Q1 & Q0 & INA; APPEND Y.R = 'b'0; APPEND Z.S = !Q1 & Q0 & !INA; APPEND Z.R = 'b'0; T-Type Flip-Flop APPEND Y.T = !Q1 & Q0 & INA; APPEND Z.T = !Q1 & Q0 & !INA; The following is an example of conditional output statements with a DEFAULT statement. PRESENT 'b'01 IF INA & INB NEXT 'b'10; IF INA & !INB NEXT 'b'11; DEFAULT NEXT 'b'00 OUT Y OUT !Z; Figure 1-59 shows the transitions described by the above example. Note the equation generated by the DEFAULT statement. [Picture] Figure 1-59. Synchronous Conditional Output with Default Diagram For the transitions described in the above example and figure, CUPL generates the following equations, depending on the type of flip-flop that is specified. D-Type Flip-Flop APPEND Y.D = !Q1 & Q0 & !INA;(not defined for Z output) D-CE-Type Flip-Flop APPEND Y.D = !Q1 & Q0 & !INA; APPEND Y.CE = !Q1 & Q0 & !INA; APPEND Z.D = 'b'0; APPEND Z.CE = !Q1 & Q0 & INA; J-K-Type Flip-Flop APPEND Y.J = !Q1 & Q0 & !INA; APPEND Y.K = 'b'0; APPEND Z.J = 'b'0; APPEND Z.K = !Q1 & Q0 & !INA; S-R-Type Flip-Flop APPEND Y.S = !Q1 & Q0 & !INA; APPEND Y.R = 'b'0; APPEND Z.S = 'b'0; APPEND Z.R = !Q1 & Q0 & !INA; T-Type Flip-Flop APPEND Y.T = !Q1 & Q0 & !INA APPEND Z.T = !Q1 & Q0 & INA; .c4.Unconditional Asynchronous Output Statement This statement specifies variables for the non-registered (asynchronous) outputs associated with a given present state, and defines when the variable is logically asserted. The format is as follows: PRESENT state_n OUT var ... OUT var ; where: state_n is a decoded value (default hex) of the state bit variables that are the output of the state machine. var is a variable name declared in the pin declarations. It is not a variable from the SEQUENCE state_var_list. ; is a semicolon used to mark the end of a statement. The PIN declaration statement (see the subtopic, Pin Declaration Statements in this chapter) determines whether the variable, when asserted, is active-HI or active-LO. For example, if the variable has the negation symbol (!var) in the pin declaration, when it is asserted in the OUT statement, its value is active-LO. Negating the variable (with the complement operator) is not a valid format for this statement. Only one output statement can be written for each present state. However, multiple variables can be defined using more than one OUT keyword. The following is an example of an unconditional asynchronous output statement. PRESENT 'b'01 OUT Y OUT Z; Figure 1-60 shows the outputs defined by the statements in the example above. [Picture] Figure 1-60. Unconditional Asynchronous Output Diagram For the asynchronous output definitions in the example and figure above, CUPL generates the following equations: APPEND Y = !Q1 & Q0; APPEND Z = !Q1 & Q0; .c4.Conditional Asynchronous Output Statement This statement specifies variables for the non-registered (asynchronous) outputs associated with a given present state, and defines when the variables are logically asserted, if the conditions in an input expression are met. The format is as follows: PRESENT state_n IF expr OUT var ... OUT var; . . IF expr OUT var ... OUT var; [DEFAULT OUT var ... OUT var;] where state_n is a decoded value (default hex) of the state bit variables that are the output of the state machine. var is a variable name declared in the pin declarations. It is not a variable from the SEQUENCE statement. expr is any valid expression. ; is a semicolon used to mark the end of a statement. ================================================== Note The square brackets indicate optional items. ================================================== The PIN declarati on statement determines whether the variable, when asserted, is active-HI or active-LO. For example, if the variable has the negation symbol (!var) in the pin declaration, when it is asserted in the OUT statement, its value is active-LO. Negating the variable (with the complement operator) is not a valid format for this statement. Multiple output statements can be written for each present state, and define multiple variables using the OUT keyword. .i.Keywords:DEF AULT;The DEFAULT statement is optional. It defines the output variable if none of the conditions in the specified conditional statements are met. In other words, it describes the condition that is the complement of the sum of all the conditional statements. =================================================================== Note Be careful when using the DEFAULT statement. Because it is the complement of all the conditional statements, the DEFAULT statement can generate an expression complex enough to greatly slow CUPL operation. In most applications, one or two conditional statements can be specified instead of the DEFAULT statement. The following is an example of conditional asynchronous output statements without a default statement. =================================================================== PRESENT 'b'01 IF INA OUT Y; IF !INA OUT Z; Figure 1-61 shows the outputs defined by the statements in the above example. [Picture] Figure 1-61. Conditional Asynchronous Output Diagram For the asynchronous output definitions in the example and figure above, CUPL generates the following equations: APPEND Y = !Q1 & Q0 & INA; APPEND Z = !Q1 & Q0 & !INA; The following is an example of conditional asynchronous output statements with a DEFAULT statement. PRESENT 'b'01 IF INA & INB OUT X; IF INA & !INB OUT Y; DEFAULT OUT Z; Figure 1-62 shows the transitions described by the above example. Note the equation generated by the DEFAULT statement. [Picture] Figure 1-62. Conditional Asynchronous Output with Default Diagram For the transitions described in the above example and figure, CUPL generates the following equations, depending on the type of flip-flop that is specified. APPEND X = !Q1 & Q0 & INA & !INB; APPEND Y = !Q1 & Q0 & INA & INB; APPEND Z = !Q1 & Q0 & !INA; .c4.Sample State-Machine Syntax File This section provides an example of a simple two-bit counter implemented with state-machine syntax. Figure 1-63 shows a diagram of the counter operation. [Picture] Figure 1-63. Simple 2-Bit Counter Diagram The $DEFINE command assigns symbolic names to the states of the counter, and the SEQUENCE statement defines the transitions between states. $DEFINE S0 0 /* assign symbolic names */ $DEFINE S1 1 /* to states */ $DEFINE S2 2 $DEFINE S3 3 FIELD count = [Q1,Q0]; /* assign field variable to statebits */ SEQUENCE count { PRESENT S0 NEXT S1 ; PRESENT S1 NEXT S2 ; PRESENT S2 NEXT S3 ; PRESENT S3 NEXT S0 ; } See the example, Decade Up/Down Counter, in Chapter U5 for another illustration of a state machine implementation. o .c3.Condition Syntax The CONDITION syntax provides a higher-level approach to specifying logic functions than does writing standard Boolean logic equations for combinatorial logic. The format is as follows: CONDITION { IF expr0 OUT var ; . . IF exprn OUT var ; DEFAULT OUT var ; } where expr is any valid expression. var is a variable name declared in the pin declaration. It can also be a list of indexed or non-indexed variables in list notation. ; is a semicolon used to mark the end of a statement. The CONDITION syntax is equivalent to the asynchronous conditional output statements of the state machine syntax, except that there is no reference to any particular state. The variable is logically asserted whenever the expression or DEFAULT condition is met. The variable cannot be logically negated in this format. ======================================================== Note Be careful when using the DEFAULT statement. Because it is the complement of all the conditional statements, the DEFAULT statement can generate an expression complex enough to greatly slow CUPL operation. In most applications, one or two conditional statements may be specified instead of the DEFAULT statement. ======================================================== The following is an example of a 2 to 4 line decoder for the CONDITION syntax. The two data inputs, A and B, select one of four decoded outputs, Y0 through Y3, whenever the ENABLE signal is asserted. The NO_MATCH output is asserted if none of the other four outputs are true. PIN [1,2] = [A,B] ; /* Data Inputs */ PIN 3 = !enable ; /* Enable Input */ PIN [12..15] = [Y0..3] ; /* Decoded Outputs */ PIN 14 = no_match ; /* Match Output */ CONDITION { IF enable & !B & !A out Y0 ; IF enable & !B & A out Y1 ; IF enable & B & !A out Y2 ; IF enable & B & A out Y3 ; } The DEFAULT expression of the above example is equivalent to the following logic equation no_match = !( enable & !B & !A) # enable & !B & A # enable & B & !A # enable & B & A ; which reduces to the following: no_match = !enable ; o .c3.User-Defined Functions The FUNCTION keyword permits the creating of personal keywords by encapsulating some logic as a function and giving it a name. This name can then be used in a logic equation to represent the function. The format for user-defined functions is as follows: FUNCTION name([parameter0,....,parametern]) { body } where name is any group of valid symbols used to reference the function. Do not use any of the CUPL reserved keywords. parameter is an optional variable used to reference variables when the function is used in a logic equation. It cannot be an expression. body is any combination of logic equations, truth tables, state-machine syntax, condition syntax, or user function. ( ) are parentheses used to enclose the parameter list. { } are braces used to enclose the body of the function. ======================================== Note The square brackets indicate optional items. ======================================== The statements in the body may assign an expression to the function, or may be unrelated equations. When using optional parameters, the number of parameters in the function definition and in the reference must be identical. The parameters defined in the body of the function are substituted for the parameters referenced in the logic equation. For example, the following defines an exclusive OR function: FUNCTION xor(in1, in2) { /* in1 and in2 are parameters */ xor = in1 & in2 # !in1 & in2 ; } An xor can be used in an equation with the inputs A and B passed as parameters, as follows: Y = xor(A,B) ; The result is the following logic equation assignment for the output variable Y: Y = A & !B # !A & B ; When a function variable is referenced in an expression, the compiler takes the following action: 1. A special function invocation variable is assigned for the function name and its arguments. This variable name is not user accessible. 2. The rest of the expression is evaluated. 3. The function body, with the invocation parameters substituted, is evaluated. 4. The function invocation variable is assigned an expression according to the body of the function. If no assignment is made in the body statements, the function invocation variable is assigned the value of 'h'o. ============================================================ Note Functions must be defined before they may be referenced. Functions are not recursive. That is, a function body may not include a reference of the function being defined. ============================================================ The following example shows a user-defined function .i.Functions:User defined;to construct state-machine-type transitions for non-registered devices without internal feedback (such as PROMs). FUNCTION TRANSITION(present_state,next_state,input_conditions) { APPEND state_out = state_in:present_state & input_condition & next_state; } The function defined in the example above is used in the following example to implement a simple up/down counter as a series of TRANSITION function references: PIN [10,11] = [Qin0..1]; /* Registered PROM */ /* output feed */ /* back externally */ /* on input pins */ PIN [12,13] = [count0..1] ; /*Count Control */ PIN [1,2] = [Q0..1] ; /* PROM Outputs */ FIELD state_in = [Qin0..1] ; FIELD state_out = [Q0..1] ; count_up = !count1 & !count0 ; /* count up */ count_dn = !count1 & count0 ; /* count down */ hold_cnt = count1; /* hold count */ $DEFINE STATE0 'b'00 $DEFINE STATE1 'b'01 $DEFINE STATE2 'b'10 $DEFINE STATE3 'b'11 /* (transition function definition made here) */ TRANSITION(STATE0,STATE1,count_up); TRANSITION(STATE1,STATE2,count_up); TRANSITION(STATE2,STATE3,count_up); TRANSITION(STATE3,STATE0,count_up); TRANSITION(STATE0,STATE3,count_dn); TRANSITION(STATE1,STATE0,count_dn); TRANSITION(STATE2,STATE1,count_dn); TRANSITION(STATE3,STATE2,count_dn); TRANSITION(STATE0,STATE0,hold_cnt); TRANSITION(STATE1,STATE1,hold_cnt); TRANSITION(STATE2,STATE2,hold_cnt); TRANSITION(STATE3,STATE3,hold_cnt);