.C1. CUPL LANGUAGE 1 This chapter explains CUPL language elements and CUPL language syntax. o .C2.LANGUAGE ELEMENTS This section describes the elements that comprise the CUPL logic description language. o .C3.VARIABLES Variables are strings of alphanumeric characters that specify device pins, internal nodes, constants, input signals, output signals, intermediate signals, or sets of signals. This section explains the rules for creating variables. Variables can start with a numeric digit, alphabet character, or underscore, but must contain at least one alphabet character. Variables are case sensitive; that is, they distinguish between uppercase and lowercase letters. Do not use spaces within a variable name. Use the underscore character to separate words. Variables can contain up to 31 characters. Longer variables are truncated to 31 characters. Variables cannot contain any of the CUPL reserved symbols (see Table 1-2). Variables cannot be the same as a CUPL reserved keyword (see Table 1-1). Examples of some VALID variable names are: a0 A0 8250_ENABLE Real_time_clock_interrupt _address Note how the use of the underscore in the above examples makes the variable names easier to read. Also, note the difference between uppercase and lowercase variable names. The variable A0 is not the same as a0. Examples of some INVALID variable names are: 99 does not contain an alpha character I/O enable contains a special character (/) out 6a contains a space; the system reads it as two separate variables tbl-2 contains a dash; the system reads it as two variables. o .C3.INDEXED VARIABLES Variable names can be used to represent a group of address lines, data lines, or other sequentially numbered items. For example, the following variable names could be assigned to the eight LO-order address lines of a microprocessor: A0 A1 A2 A3 A4 A5 A6 A7 Variable names that end in a number, as shown above, are referred to as indexed variables. ================================================== Note It is best to start indexed variables from zero (0).e.g. Use X0...4 instead of X1...5. ================================================== The index numbers are always decimal numbers between 0 and 31. When used in bit field operations (see the subtopic, Bit Field Declaration Statements in this chapter) the variable with index number 0 is always the lowest order bit. ================================================== Note Variables ending in numbers greater than 31 are not indexed variables ================================================== Examples of some valid indexed variable names are as follows: a23 D07 D7 counter_bit_3 Note the difference between index variables with leading zeroes; the variable D07 is not the same as D7. Examples of some invalid indexed variable names are as follows: D0F index number is not decimal a36 index number out of range These are valid variable names, but they are not considered indexed. o .C3.RESERVED WORDS AND SYMBOLS CUPL uses certain character strings with predefined meanings called keywords. These keywords cannot be used as names in CUPL. Table 1-1 lists these keywords. Table 1-1. CUPL Reserved Keywords -------------------------------------------------- APPEND ASSEMBLY ASSY COMPANY CONDITION DATE DEFAULT DESIGNER DEVICE ELSE FIELD FLD FORMAT FUNCTION FUSE GROUP IF JUMP LOC LOCATION MACRO MIN NAME NODE OUT PARTNO PIN PINNNODE PRESENT REV REVISION SEQUENCE SEQUENCED SEQUENCEJK SEQUENCERS SEQUENCET TABLE -------------------------------------------------- CUPL also reserves certain symbols for its use that cannot be used in variable names. Table 1-2 lists these reserved symbols. Table 1-2. CUPL Reserved Symbols ---------------------------- & # ( ) - * + [ ] / : . .. /* */ ; , ! ' = @ $ ^ ---------------------------- o .C3.NUMBERS All operations involving numbers in the CUPL compiler are done with 32-bit accuracy. Therefore, the numbers may have a value from 0 to 232 -1. Numbers may be represented in any one of the four common bases: binary, octal, decimal, or hexadecimal. The default base for all numbers used in the source file is hexadecimal, except for device pin numbers and indexed variables, which are always decimal. Numbers for a different base may be used by preceding them with a prefix listed in Table 1-3. Once a base change has occurred, that new base is the default base. Table 1-3. Number Base Prefixes Base Name Base Prefix Binary 2 'b' Octal 8 'o' Decimal 10 'd' Hexadecimal 16 'h' The base letter is enclosed in single quotes and can be either uppercase or lowercase. Some examples of valid number specifications are listed in Table 1-4. Table 1-4 Sample Base Conversions -------------------------------------------------- Number Base Decimal Value 'b'0 Binary 0 'B'1101 Binary 13 'O'663 Octal 435 'D'92 Decimal 92 'h'BA Hexadecimal 186 'O'[300..477] Octal (range) 192..314 -------------------------------------------------- Binary, octal, and hexadecimal numbers can have don't-care values ("X") and numerical values. Some examples of valid number specifications with don't-care values are listed in Table 1-5. Table 1-5. Sample Don't-Care Numbers --------------------------------------- Number Base 'b'1X11 Binary 'O'0X6 Octal 'H'[3FXX..7FFF] Hexadecimal (range) --------------------------------------- o .C3.COMMENTS Comments are an important part of the logic description file. They improve the readability of the code and document the intentions, but do not significantly affect the compile time, as they are removed by the preprocessor before any syntax checking is done. Use the symbols /* and */ to enclose comments; the program ignores everything between these symbols. Comments may span multiple lines and are not terminated by the end of a line. Comments cannot be nested. Some examples of valid comments are shown in Figure 1-1. ----------------------------------------------------------------- /*******************************************/ /* This is one way to create a title or */ /* an information block */ /*******************************************/ /* This is another way to create an information block */ out1=in1 # in2; /* A Simple OR Function */ out2=in1 & in2; /* A Simple AND Function */ out3=in1 $ in2; /* A Simple XOR Function */ ----------------------------------------------------------------- Figure 1-1. Sample Comments.i.comments:sample; o .C3.LIST NOTATION Shorthand notations are an important feature of the CUPL language. The most frequently used shorthand notation is the list. It is commonly used in pin and node declarations, bit field declarations, logic equations, and set operations. The list format is as follows: [variable, variable, ... variable] where [ ] are brackets used to delimit items in the list as a set of variables. Two examples of the list notation are as follows: [UP, DOWN, LEFT, RIGHT] [A0, A1, A2, A3, A4, A5, A6, A7] When all the variable names are sequentially numbered, either from lowest to highest or vice versa, the following format may be used: [variablem..n] where m is the first index number in the list of variables. n is the last number in the list of variables; n can be written without the variable name. For example, the second line from the example above could be written as follows: [A0..7] Index numbers are assumed to be decimal and contiguous. Any leading zeros in the variable index are removed from the variable name that is created. For example: [A00..07] is shorthand for: [A0, A1, A2, A3, A4, A5, A6, A7] not for: [A00, A01, A02, A03, A04, A05, A06, A07] The two forms for the list notation may be mixed in any combination. For example, the following two list notations are equivalent: [A0..2, A3, A4, A5..7] [A0, A1, A2, A3, A4, A5, A6, A7] o .C3.TEMPLATE FILE When a logic description source file is created using the CUPL language, certain information must be entered, such as header information, pin declarations, and logic equations. For assistance, CUPL provides a template file that contains the proper structure for the source file. Figure 1-2 shows the contents of the template file. ----------------------------------------------------------------- Name XXXXX; Partno XXXXX; Date XX/XX/XX; Revision XX; Designer XXXXX; Company XXXXX; Assembly XXXXX; Location XXXXX; /*************************************************************/ /* place description of design here */ /*************************************************************/ /* Allowable Target Device Types: */ /*************************************************************/ /** Inputs **/ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ /** Outputs **/ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ /** Declarations and Intermediate Variable Definitions **/ /** Logic Equations **/ ----------------------------------------------------------------- Figure 1-2. Template File The template file provides the following sections: Header Information - Keywords followed by XXXs that are replaced with text to identify the file for archival and revision purposes. Title Block - Comment symbols that enclose space for describing the function of the design and allowable target devices. Pin Declaration - Keywords and operators in the proper format for input and output pin declarations and comment space to describe the pin assignments. After pin declarations are made, remove any extra "pin = ;" lines. Otherwise, a syntax error will occur during compilation. The /* Inputs */ and /* Outputs */ are comments that provide groupings for readability only. Assign any pin type in any order, no matter how it is used in the logic description file. Declaration and Intermediate Variable - Space for making declarations, such as bit field declarations (see the subtopics, Bit Field Declaration Statements and Node Declaration Statements in this chapter) and for writing intermediate equations (see the subtopic, Logic Equations in this chapter). Logic Equation - Space for writing logic equations describing the function of the device (see the subtopic, Logic Equations in this chapter). .C4.HEADER INFORMATION The header information section of the source file identifies the file for revision and archival purposes. Normally place it at the beginning of the file. CUPL provides 10 keywords to use in header information statements. Begin each statement with a keyword which can be followed by any valid ASCII characters, including spaces and special characters. End each statement with a semicolon. Table 1-6 lists the CUPL header keywords and the information to provide with each keyword. Table 1-6. Header Information Keywords Keyword Information NAME Normally use the source logic description filename. Use only character strings that are valid for the operating system. The name specified here determines the name for any JEDEC, ASCII - hex, or HL download files. The NAME field accommodate s filenames up to 32 characters long. When using systems such as DOS which allow filenames of only eight characters, the filename will be truncated. PARTNO Specify a company's proprietary part number (usually issued by manufacturi ng) for a particular PLD design. The part number is not the type of target PLD. For GAL devices, the first eight characters are encoded using seven-bit ASCII in the User Signature Fuses of the devices' fuse map. REVISION Begin with 01 when first creating a file and increment each time a file is altered. REV can be used for an abbreviatio n. DATE Change to the current date each time a source file is altered. DESIGNER Specify the designer's name. COMPANY Specify the company's name for proper documentation practice and because specifications may be sent to semiconduct or manufacturers for high volume PLD orders. ASSEMBLY Give the assembly name or number of the PC board on which the PLD will be used. The abbreviatio n ASSY can be used. LOCATION Indicate the PC board reference or coordinate where the PLD is located. The abbreviatio n LOC can be used. DEVICE Set the default device type for the compilation. A device type specified on the command line overrides all device types set in the source file. For multi-device source files, DEVICE must be used with each section if the device types are different. FORMAT Set a download output format override for the current logic description section. The valid values to use for the output format are: h produce ASCII-hex output i produce Signetics HL output j produce JEDEC output FORMAT overrides any option flag on the command line. It is useful in multi-devic e source files where different parts have incompatibl e output formats. More than one format value at a time may be specified to produce more than one type of output. The format value must be a lowercase letter. The template file provides all the header keywords except DEVICE and FORMAT. An example of proper CUPL header information is as follows: Name WAITGEN; Partno P9000183; Revision 02; Date 1/11/89; Designer Osann; Company Logical Devices, Inc. ; Assembly PC Memory Board ; Location U106 ; Device F155; Format ij ; If any header information is omitted, CUPL issues a warning message, but continues with compilation. .c4.Pin Declaration Statements Pin declaration statements declare the pin numbers and assign them symbolic variable names. The format for a pin declaration is as follows: PIN pin_n=[!]var ; where PIN is a keyword to declare the pin numbers and assign them variable names. pin_n is a decimal pin number or a list of pin numbers grouped using the list notation; that is, [pin_n 1, pin_n 2 ... pin_nn] ! is an optional exclamation point to define the polarity of the input or output signal. = is the assignment operator. var is a single variable name or a list of variables grouped using the list notation; that is, [var, var ... var] ; is a semicolon to mark the end of the pin declaration statement. The template file provides a section for entering the pin variables individually or in groups using the list notation. The concept of polarity can often be a confusing one. In any PLD design, the designer is primarily concerned with whether a signal is true or false. The designer should not have to care whether this means that the signal is high or low. For a variety of reasons a board design may require a signal to be considered true when it is logic level 0(low) and false when it is logic 1(high). This signal is considered active-low since it is activated when it is low. This might also be called low-true. If a signal is changed from active-high to active low then the polarity has been changed. For this reason, CUPL allows you to declare signal polarity in the pin definition and then you do not have to be concerned with it again. When writing equations in CUPL syntax, the designer should not be concerned with the polarity of the signal. The pin declarations declare a translation that will handle the signal polarity. Suppose that we wanted the following function. Y = A & B; What this statement means is that Y will be true when A is true and B is true. We can implement this in a P22V10 device very easily. Pin 2 = A; Pin 3 = B; Pin 16 = Y; Y = A & B; When the device is plugged into a circuit, if a logic 1 is asserted at pins 2 and 3 then the signal at pin 16 will be high. Let us assume that for some reason we wanted the inputs to read logic 0 as true. We could modify the design to behave this way. Pin 2 = !A; Pin 3 = !B; Pin 16 = Y; Y = A & B; Now even though the ! symbol was placed in the pin declaration to indicate the inverted polarity, the equation still reads as "Y is true when A is true and B is true". All that has been changed is the translation of true=0 and false=1. So at the design level nothing has changed but in the pin declarations we now map 0 to true and 1 to false. This promotes the designer to separate the design into layers so as to minimize confusion related to polarity. It is important also that CUPL will modify the feedback signal so that the true/false layer is maintained. [Picture] Figure 1-3. Relationship Between Pin Declaration and Signal Polarity Use the exclamation point (!) to define the polarity of an input or output signal. If an input signal is active-level LO (that is, the asserted TTL signal voltage level is 0 volts), put an exclamation point before the variable name in the pin declaration. The exclamation point informs the compiler to choose the inverted sense of the signal when it is listed as active in the logic equations. The virtual device is an exception to this rule, however. When using the virtual device, CUPL ignores the polarity in the pin declaration. In this case, the equation itself must be negated. Similarly, if an output signal is active-level LO, define the variable with an exclamation point in the pin declaration and write the logic equation in a logically true form. Use of the exclamation point permits declaring pins without regard to the limitations of the type of target device. With the virtual device, the equation itself must be inverted, since the compiler ignores the polarity in the pin declaration. If a pin declaration specifying an active-level HI output is compiled for a target device (such as a PAL16L8) that has only inverting outputs, CUPL automatically performs DeMorgan's Theorem on the logic equation to fit the function into the device. Consider the following example. The logic description file is written for a PAL16L8 device. All output pins are declared as active-HI. The following equation has been written to specify an OR function: c = a # b ; However, because the PAL16L8 contains a fixed inverting buffer on the output pins, CUPL must perform DeMorganization to fit the logic to the device. CUPL generates the following product term in the documentation file (see Documentation File Formats in Appendix C): c => ! a & ! b Figure 1-4 shows the process described above. [Picture] Figure 1-4. Active-HI Pin Declaration for Inverting Buffer If a design has excessive product terms, CUPL displays an error message and the compilation stops. The documentation file (filename.DOC) lists the number of product terms required to implement the logic function and the number of product terms the device physically has for the particular output pin. Some examples of valid pin declarations are: pin 1 = clock; /* Register Clock */ pin 2 = !enable; /* Enable I/O Port */ pin [3,4] = ![stop,go]; /* Control Signals */ pin [5..7] = [a0..2]; /* Address Bits 0-2 */ The last two lines in the example above are shorthand notations for the following: pin 3 = !stop; /* Control Signal */ pin 4 = !go; /* Control Signal */ pin 5 = a0; /* Address Bit 0 */ pin 6 = a1; /* Address Bit 1 */ pin 7 = a2; /* Address Bit 2 */ For the virtual device, the pin numbers may be left out. This provides a way to do a design without regard for any device related restrictions. The designer can then examine the results and thereby determine the requirements for implementation. The target device can then be chosen. The following are valid pin declarations when using the virtual device. pin = !stop; /* Control Signal */ pin = !go; /* Control Signal */ pin = a0; /* Address Bit 0 */ pin = a1; /* Address Bit 1 */ pin = a2; /* Address Bit 2 */ The input, output, or bi-directional nature of a device pin is not specified in the pin declaration. The compiler infers the nature of a pin from the way the pin variable name is used in the logic specification. If the logic specification and the physical characteristics of the target device are incompatible, CUPL displays an error message denoting the improper use of the pin. .c4.Node Declaration Statements Some devices contain functions that are not available on external pins, but logic equations must be written for these capabilities. For example, the 82S105 contains both buried state registers (flip-flops) and a mechanism for inverting any transition term through a complement array. Before writing equations for these flip-flops (or complement arrays), they must be assigned variable names. Since there are no pins associated with these functions, the PIN keyword cannot be used. Use the NODE keyword to declare variable names for buried functions. The format for node declarations is as follows: NODE [!] var ; NODE is a keyword to declare a variable name for a buried function. ! is an optional exclamation point to define the polarity of the internal signal. var is a single variable name or list of variables grouped using the list notation. ; is a semicolon to mark the end of the statement. Place node declarations in the "Declarations and Intermediate Variables Definitions" section of the source file provided by the template file. Most internal nodes are active-level HI, therefore, the exclamation point should not be used to define the polarity of an internal signal as active-level LO. Using the exclamation point almost always causes the compiler to generate a significantly greater number of product terms. An exception is the complement array node, which, by definition, is an active-level LO signal. Although no pin numbers are given in the declaration statement, CUPL assigns the variable name to an internal pseudo-pin number. These numbers begin with lowest possible number and are sequentially defined even if a node was assigned with the PINNODE statement. The assignment is automatic and determined by usage (flip-flop, complement array, and so on), so variable order is not a concern. However, once a node variable is declared, a logic equation must be created for the variable, or a compilation error results. CUPL uses the node declaration to distinguish between a logic equation for a buried function and an intermediate expression. Examples of the use of the NODE keyword are: NODE [State0..5]; /* Internal State Bit */ NODE !Invert; /* For Complement Array */ An alternative for assigning buried functions instead of allowing CUPL to automatically assign them via the NODE keyword, is to use the PINNODE keyword. The PINNODE keyword is used for explicitly defining buried nodes by assigning a node number to a symbolic variable name. This is similar to the way the pin declaration statements work. The format for a pinnode declaration is as follows: PINNODE node_n = [!]var; where PINNODE is a keyword to declare the node numbers and assign them variable names. node_n is a decimal node number or a list of node numbers grouped using the list notation; that is, [node_n1,node_n2 ... node_nn] ! is an optional exclamation point to define the polarity of the internal signal. = is the assignment operator. var is a single variable name or list of variables grouped using the list notation; that is, [var,var ... var] ; is a semicolon used to mark the end of the statement. Place pinnode declarations in the "Declarations and Intermediate Variables Definitions" section of the source file provided by the template file. As with node declarations, most internal nodes are active-level HI; therefore, the exclamation point should not be used to define the polarity of an internal signal as active level LO. Using the exclamation point almost always causes the compiler to generate a significantly greater number of product terms. An exception is the complement array node, which by definition is an active-level LO signal. A list of node numbers for all devices containing internal nodes is included in Appendix D. Please reference these node numbers for pinnode declarations. Examples of the use of the PINNODE keyword are: PINNODE [29..34] = [State0..5]; /* Internal State Bits */ PINNODE 35 = !Invert; /* For Complement Array */ PINNODE 25 = Buried; /* For Buried register part */ /* of an I/O macrocell with */ /* multiple feedback paths */ .c4.Bit Field Declaration Statements A bit field declaration assigns a single variable name to a group of bits. The format is as follows: FIELD var = [var, var, ... var] ; where FIELD is a keyword. var is any valid variable name. [var, var, ... var] is a list of variable names in list notation. = is the assignment operator. ; is a semicolon used to mark the end of the statement. Note ================================================== The square brackets do not indicate optional items. They are used to delimit items in a list. ================================================== Place bit field declarations in the "Declarations and Intermediate Variable Definitions" section of the source file provided by the template file. After assigning a variable name to a group of bits, the name can be used in an expression; the operation specified in the expression is applied to each bit in the group. See the subtopic, Set Operations in this chapter for a description of the operations allowed for FIELD statements. The example below shows two ways to reference the eight address input bits (A0 through A7) of an I/O decoder as the single variable named ADDRESS. FIELD ADDRESS = [A7,A6,A5,A4,A3,A2,A1,A0] ; or FIELD ADDRESS = [A7..0] ; When a FIELD statement is used, the compiler generates a single 32-bit field internally. This is used to represent the variables in the bit field. Each bit represents one member of the bit field. The bit number which represents a member of a bit field is the same as the index number if indexed variables are used. This means that A0 will always occupy bit 0 in the bitfield. This also means that the order of appearance of indexed variables in a bit field has no significance. A bit field declared as [A0..7] is exactly the same as a bit field declared as [A7..0]. Because of this mechanism, different indexed variables should not be included in the same bit field. A bit field containing A2 and B2 will assign both of these variables to the same bit position. This will result in the generation of erroneous equations. Also, bit fields should never contain both indexed and non-indexed variables. This will almost certainly result in erroneous generation of equations. Note ================================================== Do not mix indexed and non-indexed variables in a field statement. The compiler may produce unexpected results. ================================================== .c4.MIN Declaration Statements The MIN declaration statement overrides, for specified variables, the minimization level specified on the command line when running CUPL. The format is as follows: MIN var [.ext] = level ; where MIN is a keyword to override the command line minimization level. var is a single variable declared in the file or a list of variables grouped using the list notation; that is, [var, var, ... var] .ext is an optional extension that identifies the function of the variable. level is an integer between 0 and 4. ; is a semicolon to mark the end of the statement. The levels 0 to 4 correspond to the option flags on the command line, -m0 through -m4. The MIN declaration permits specifying different levels for different outputs in the same design, such as no reduction for outputs requiring redundant or contained product terms (to avoid asynchronous hazard conditions), and maximum reduction for a state machine application. The following are examples of valid MIN declarations. MIN async_out = 0; /* no reduction */ MIN [outa, outb] = 2; /* level 2 reduction */ MIN count.d = 4; /* level 4 reduction */ Note that the last declaration in the example above uses the .d extension to specify that the registered output variable is the one to be reduced. .c4.FUSE Statement The FUSE statement provides for special cases where it is necessary to blow TURBO or MISER bits. This statement should be used with utmost care, as it can lead to unpredictable results if used incorrectly. FUSE (fusenumber, x) where fusenumber is the fuse number corresponding to the MISER Bit or TURBO Bit that must be blown, and x is either 0 or 1. Specify 0 if the bit must not be blown. Specify 1 to blow the bit. Use this statement with extreme caution. In this example, fuse 101 is a MISER Bit or TURBO Bit. This blows fuse number 101. example: FUSE(101,1) DO NOT ATTEMPT TO USE THIS STATEMENT TO BLOW ARBITRARY FUSES! The fuse statement was designed to blow MISER bits and TURBO Bits only. The exact fuse number for the TURBO or MISER Bit must be specified. Every time this statement is used, CUPL will generate a warning. This is a reminder to double check that the fuse number specified is correct. If a wrong fuse number is specified, disastrous results can occur. Be very careful using this statement. If the FUSE statement is used in a design and strange results occur, check the fuse number specified and make sure that it is a MISER or TURBO Bit. o .c3.Preprocessor Commands The preprocessor portion of CUPL operates on the source file before it is passed to the parser and other sections of the compiler. The preprocessor commands add file inclusion, conditional compilation, and string substitution capabilities to the source processing features of CUPL. Table 1-7 lists the available preprocessor commands. Each command is described in detail in this section. Table 1-7. Preprocessor Commands ----------------- $DEFINE $IFDEF $UNDEF $ELSE $IFNDEF $REPEAT $ENDIF $INCLUDE $REPEND $MACRO $MEND ----------------- The dollar sign ($) is the first character in all preprocessor commands and must be used in column one of the line. Any combination of uppercase or lowercase letters may be used to type these commands. .c4.$DEFINE This command replaces a character string by another specified operator, number, or symbol. The format is as follows: $DEFINE argument1 argument2 where argument1 is a variable name or special ASCII character. argument2 is a valid operator, a number, or a variable name. "Argument1" is replaced by "argument2" at all locations in the source specification after the $DEFINE command is given (or until the preprocessor encounters an $UNDEF command). The replacement is a literal string substitution made on the input file before being processed by the CUPL compiler. Note that no semicolon or equal sign is used for this command. The $DEFINE command allows numbers or constants to be replaced with symbolic names, for example: $DEFINE ON 'b'1 $DEFINE OFF 'b'0 $DEFINE PORTC 'h'3F0 The $DEFINE command also allows creation of a personal set of logical operators. For example, the following define an alternate set of operators for logic specification: $DEFINE { /* Alternate Start Comment $DEFINE } */ Alternate End Comment $DEFINE / ! Alternate Negation $DEFINE * & Alternate AND $DEFINE + # Alternate OR $DEFINE :+: $ Alternate XOR Note ================================================== The above definitions are contained in the PALASM.OPR file included with the CUPL software package. This file may be included in the source file (see $INCLUDE command) to allow logic equations using the PALASM set of logical operator symbols, as well as the standard CUPL operator symbols. ================================================== .c4.$UNDEF This command reverses a $DEFINE command. The format is as follows: $UNDEF argument where argument is an argument previously used in a $DEFINE command. Before redefining a character string or symbol defined with the $DEFINE command, use the $UNDEF command to undo the previous definition. .c4.$INCLUDE This command includes a specified file in the source to be processed by CUPL. The format is as follows: $INCLUDE filename where filename is the name of a file in the current directory. File inclusion allows standardizing a portion of a commonly used specification. It is also useful for keeping a separate parameter file that defines constants that are commonly used in many source specifications. The files that are included may also contain $INCLUDE commands, allowing for "nested" include files. The named file is included at the location of the $INCLUDE command. For example, the following command includes the PALASM.OPR file in a source file. $INCLUDE PALASM.OPR PALASM.OPR is included with the CUPL software and contains $DEFINE commands that specify the following alternate set of logical operators. $DEFINE / ! Alternate Negation $DEFINE * & Alternate AND $DEFINE + # Alternate OR $DEFINE :+: $ Alternate XOR $DEFINE { /* Alternate Start Comment $DEFINE } */ Alternate End Comment .c4.$IFDEF This command conditionally compiles sections of a source file. The format is as follows: $IFDEF argument where argument may or may not have previously been defined with a $DEFINE command. When the argument has previously been defined, the source statements following the $IFDEF command are compiled until the occurrence of an $ELSE or $ENDIF command. When the argument has not previously been defined, the source statements following the $IFDEF command are ignored. No additional source statements are compiled until the occurrence of an $ELSE or $ENDIF command. One use of $IFDEF is to temporarily remove source equations containing comments from the file. It is not possible to "comment out" the equations because comments do not nest. The following example illustrates this technique. NEVER is an undefined argument. $IFDEF NEVER out1=in1 & in2; /* A Simple AND Function */ out2=in3 # in4; /* A Simple OR Function */ $ENDIF Because NEVER is undefined, the equations are ignored during compilation; that is, they function as comments. .c4.$IFNDEF This command sets conditions for compiling sections of the source file. $IFNDEF argument where argument may or may not have previously been defined with a $DEFINE command. The $IFNDEF command works in the opposite manner of the $IFDEF command. When the argument has not previously been defined, the source statements following the $IFNDEF command are compiled until the occurrence of an $ELSE or $ENDIF command. If the argument has previously been defined, the source statements following the $IFNDEF command are ignored. No additional source statements are compiled until the occurrence of an $ELSE or $ENDIF command. One use of $IFNDEF is to create a single source file containing two mutually exclusive sets of equations. Using an $IFNDEF and $ENDIF command to set off one of the sets of equations, quick toggling is possible between the two sets of equations by defining or not defining the argument specified in the $IFNDEF command. For example, some devices contain common output enable pins that directly control all the tri-state buffers, whereas other devices contain single product terms to enable each tri-state buffer individually. In the following example, the argument, COMMON_OE has not been defined, so the equations that follow are compiled. Any equations following $ENDIF are not compiled. $IFNDEF COMMON_OE pin 11 = !enable; /* input pin for OE*/ [q3,q2,q1,q0].oe = enable; /* assign tri-state*/ /* equation for 4*/ /* outputs */ $ENDIF If the device has common output enables, no equations are required to describe it. Therefore, in the above example, for a device with common output enables, define COMMON_OE so the compiler skips the equations between $IFNDEF and $ENDIF. .c4.$ENDIF This command ends a conditional compilation started with the $IFDEF or $IFNDEF commands. The format is as follows: $ENDIF The statements following the $ENDIF command are compiled in the same way as the statements preceding the $IFDEF or $IFNDEF commands. Conditional compilation may be nested, and for each level of nesting of the $IFDEF or $IFNDEF command, an associated $ENDIF must be used. The following example illustrates the use of $ENDIF with multiple levels of nesting. $IFDEF prototype_1 pin 1 = set; /* Set on pin 1 */ pin 2 = reset; /* Reset on pin 2 */ $IFDEF prototype_2 pin 3 = enable; /* Enable on pin 3 */ pin 4 = disable; /* Disable on pin 4 */ $ENDIF pin 5 = run; /* Run on pin 5 */ pin 6 = halt; /* Halt on pin 6 */ $ENDIF .c4.$ELSE This command reverses the state of conditional compilation as defined with $IFDEF or $IFNDEF. The format is as follows: $ELSE If the tested condition of the $IFDEF or $IFNDEF commands is true (that is, the statements following the command are compiled), then any source statements between an $ELSE and $ENDIF command are ignored. If the tested condition is false, then any source statements between the $IFDEF or $IFNDEF and $ELSE command are ignored, and statements following $ELSE are compiled. For example, many times the production printed circuit board uses a different pinout than does the wire-wrap prototype. In the following example, since Prototype has been defined, the source statements following $IFDEF are compiled and the statements following $ELSE are ignored. $DEFINE Prototype X /* define Prototype*/ $IFDEF Prototype pin 1 = memreq; /* memory request on */ /* pin 1 of prototype*/ pin 2 = ioreq; /* I/O request on */ /* pin 2 of prototype*/ $ELSE pin 1 = ioreq; /* I/O request on*/ /* pin 1 of PCB*/ pin 2 = memreq; /* memory request on */ /* pin 2 of PCB*/ $ENDIF To compile the statements following $ELSE, remove the definition of Prototype. .c4.$REPEAT This command is similar to the FOR statement in C language and DO statements in FORTRAN language. It allows the user to duplicate repeat body by index. The format is as follows: $REPEAT index=[number1,number2,...,numbern] repeat body $REPEND where n can be any number in the range 0 to 1023 In preprocessing, the repeat body will be duplicated from number1 to numbern. The index number can be written in short form as [number1..numbern] if the number is consecutive. The repeat body can be any CUPL statement. Arithmetic operations can be performed in the repeat body. The arithmetic expression must be enclosed by braces { }. For example, design a three to eight decoder. FIELD sel = [in2..0] $REPEAT i = [0..7] !out{i} = sel:'h'{i} & enable; $REPEND Where index variable i goes from 0 to 7, so the statement "out{i} = sel:'h'{i} &enable;" will be repeated during preprocessing and create the following statements: FIELD sel = [in2..0]; !out0 = sel:'h'0 & enable; !out1 = sel:'h'1 & enable; !out2 = sel:'h'2 & enable; !out3 = sel:'h'3 & enable; !out4 = sel:'h'4 & enable; !out5 = sel:'h'5 & enable; !out6 = sel:'h'6 & enable; !out7 = sel:'h'7 & enable; The following example shows how the arithmetic operation addition (+) and modulus (%) are used in the repeat body. /* Design a five bit counter with a control signal advance.If advance is high, counter is increased by one.*/ FIELD count[out4..0].i.sequence; SEQUENCE count { $REPEAT i = [0..31] PRESENT S{i} IF advance & !reset NEXT S{(i+1)%(32)}; IF reset NEXT S{0}; DEFAULT NEXT S{i}; $REPEND } .c4.$REPEND This command ends a repeat body that was started with $REPEAT. The format is as follows: $REPEND The statements following the $REPEND command are compiled in the same way as the statements preceding the $REPEAT command. For each $REPEAT command, an associated $REPEND command must be used. .c4.$MACRO This command creates user-defined macros. The format is as follows: $MACRO name argument1 argument2...argumentn macro function body $MEND The macro function body will not be compiled until the macro name is called. The function is called by stating function name and passing the parameters to the function. Like the $REPEAT command, the arithmetic operation can be used inside the macro function body and must be enclosed in braces. The following example illustrates how to use the $MACRO command. Use the $MACRO command to define a decoder function with an arbitrary number of bits. This example places the macro definition and call in the same file. $MACRO decoder bits MY_X MY_Y MY_enable; FIELD select = [MY_Y{bits-1}..0]; $REPEAT i = [0..{2**(bits-1)}] !MY_X{i} = select:'h'{i} & MY_enable; $REPEND $MEND /* Other statements */ decoder(3, out, in, enable); /* macro invocation */ Calling function decoder will create the following statements by macro expansion. FIELD sel = [in2..0]; !out0 = sel:'h'0 & enable; !out1 = sel:'h'1 & enable; !out2 = sel:'h'2 & enable; !out3 = sel:'h'3 & enable; !out4 = sel:'h'4 & enable; !out5 = sel:'h'5 & enable; !out6 = sel:'h'6 & enable; !out7 = sel:'h'7 & enable; When macros are called, the keyword NC is used to represent no connection. Because NC is a keyword, the letters NC should not be used as a variable elsewhere in CUPL. A macro expansion file can be created by using the -e flad when compiling the PLD file. CUPL will create an expanded macro file with the same name as the PLD file, with the extension ".mx". The macro definition can be stored in a separate file with a ".m" extension. Using the $INCLUDE command, specify the file. All the macro functions in that file will then be accessible. The following example shows the macro definition and calling statement stored in different files. The macro definition of decoder is stored in the file "macrolib.m" $INCLUDE macrolib.m /*specify the macro library */ /* other statements */ decoder(4, out, in, enable); /* other statements */ More examples can be found in the example files provided on diskette. .c4.$MEND This command ends a macro function body started with $MACRO. The format is as follows: $MEND The statements following the $MEND command are compiled in the same way as the statements preceding the $MACRO command. For each $MACRO command, an associated $MEND command.must be used. o .c2.LANGUAGE SYNTAX This section describes the CUPL language syntax. It explains how to use logic equations, truth tables, state machine syntax, condition syntax and user-defined functions to create a PLD design. o .c3.Logical Operators CUPL supports the four standard logical operators used for boolean expressions. Table 1-8 lists these operators and their order of precedence, from highest to lowest. Table 1-8. Precedence of Logical Operators Operator Example Description Precedence ! !A NOT 1 & A & B AND 2 # A # B OR 3 $ A $ B XOR 4 The truth tables in Figure 1-5 list the Boolean Logic rules for each operator. ----------------------------------------------------------------- AND OR XOR NOT ------ ------ ------ ----- 00 | 0 00 | 0 00 | 0 0 | 1 01 | 0 01 | 1 01 | 1 1 | 0 10 | 0 10 | 1 10 | 1 11 | 1 11 | 1 11 | 0 ----------------------------------------------------------------- Figure 1-5. Truth Tables o .c3.Arithmetic Operators CUPL supports six standard arithmetic operators used for arithmetic expressions. The arithmetic expressions can only be used in the $REPEAT and $MACRO commands. Arithmetic expressions must appear in braces { }. Table 1-9 lists these operators and their order of precedence, from highest to lowest. Table 1-9 Precedence of Arithmetic Operators ----------------------------------------------------------------- Operator Example Description Precedence ** 2**3 Exponentiation 1 * 2*i Multiplication 2 / 4/2 Division 2 % 9%8 Modulus 2 + 2+4 Addition 3 - 4-i Subtraction 3 ----------------------------------------------------------------- o .c3.Arithmetic Function CUPL supports one arithmetic function used for arithmetic expressions. The arithmetic expressions can only be used in the $REPEAT and $MACRO commands. Table 1-10 lists the function. Table 1-10 Arithmetic Function Function Base LOG2 Binary LOG8 Octal LOG16 Hexadecimal LOG Decimal The LOG function returns an integer value. For example: LOG2(32) = 5 <==> 2**5 = 32 LOG2(33) = ceil(5.0444) = 6 <==> 2**6 = 64 Ceil(x) returns the smallest integer not less than x. o .c3.Extensions Extensions can be added to variable names to indicate specific functions associated with the major nodes inside a programmable device, including such capabilities as flip-flop description and programmable three-state enables. Table 1-11 lists the extensions that are supported by CUPL and on which side of the equal sign (=) they are used. The compiler checks the usage of the extension to determine whether it is valid for the specified device and whether its usage conflicts with some other extension used. Table 1-11 Extensions Extension Side Description Used .AP L Asynchronous preset of flip-flop .AR L Asynchronous reset of flip-flop .APMUX L Asynchronous preset multiplexer selection .ARMUX L Asynchronous reset multiplexer selection .BYP L Programmable register bypass .CA L Complement array .CE L CE input of enabled D-CE type flip-flop .CK L Programmable clock of flip-flop .CKMUX L Clock multiplexer selection .D L D input of D-type flip-flop .DFB R D registered feedback path selection .DQ R Q output of D-type flip-flop .IMUX L Input multiplexer selection of two pins .INT R Internal feedback path for registered macrocell .IO R Pin feedback path selection .IOAR L Asynchronous reset for pin feedback register .IOAP L Asynchronous preset for pin feedback register .IOCK L Clock for pin feedback register .IOD R Pin feedback path through D register .IOL R Pin feedback path through latch .IOSP L Synchronous preset for pin feedback register .IOSR L Synchronous reset for pin feedback register .J L J input of JK-type output flip-flop .K L K input of JK-type output flip-flop .L L D input of transparent latch .LE L Programmable latch enable .LEMUX L Latch enable multiplexer selection .LFB R Latched feedback path selection .LQ R Q output of transparent input latch .OBS L Programmable observability of buried nodes .OE L Programmable output enable .OEMUX L Tri-state multiplexer selection .PR L Programmable preload .R L R input of SR-type output flip-flop .S L S input of SR-type output flip-flop .SP L Synchronous preset of flip-flop .SR L Synchronous reset of flip-flop .T L T input of toggle output flip-flop .TEC L Technology-dependent fuse selection .TFB R T registered feedback path selection .T1 L T1 input of 2-T flip-flop .T2 L T2 input of 2-T flip-flop Each extension provides access to a specific function. For example, to specify an equation for output enable (on a device that has the capability) use the .OE extension. The equation will look as follows: PIN 2 = A; PIN 3 = B; PIN 4 = C; PIN 15 = VARNAME; VARNAME.OE = A & B; Note that the compiler supports only the flip-flop capabilities that are physically implemented in the device. For example, the compiler does not attempt to emulate a JK-type flip-flop in a device that only has D-type registers. Any attempt to use capabilities not present in a device will cause the compiler to report an error. For those devices containing bi-directional I/O pins with programmable output enables, CUPL automatically generates the output enable expression according to the usage of the pin. If the variable name is used on the left side of an equation, the pin is assumed to be an output and is assigned binary value 1; that is, the output enable expression is defaulted to the following: PIN_NAME.OE = 'b'1; /* Tri-state buffer always ON */ Those pins that are used only as inputs (that is, the variable name appears only on the right side of an equation) are assigned binary value 0; the output enable expression is defaulted to the following: PIN_NAME.OE = 'b'0; /* Tri-state buffer Always OFF */ When the I/O pin is to be used as both an input and output, any new output enable expression that the user specifies overrides the default to enable the tri-state buffer at the desired time. When using a JK or SR-type flip-flop, an equation must be written for both the J and K (or S and R) inputs. If the design does not require an equation for one of the inputs, use the following construct to turn off the input: COUNT0.J='b'0 ; /* J input not used */ Control functions such as asynchronous resets and presets are commonly connected to a group (or all) of the registers in a device. When an equation is written for one of these control functions, it is actually being written for all of the registers in the group. For documentation purposes, CUPL checks for the presence of such an equation for each register in the group and generates a warning message for any member of the group that does not have an identical equation. If all the control functions for a given group are defined with different equations, the compiler will generate an error since it cannot decide which equation is the correct one. Remember that this is a device specific issue and it is a good idea to understand the capability of the device being used. Figure 1-6 shows the use of extensions. Note that this figure does not represent an actual circuit, but shows how to use extensions to write equations for different functions in a circuit. [Picture] Figure 1-6. Circuit Illustrating Extensions The figure shows an equation with a .D extension that has been written for the output to specify it as a registered output. Note that when feedback (OUT_VAR) is used in an equation, it does not have an extension. Note ================================================== The .DQ extension is used for input pins only. ================================================== Additional equations can be written to specify other types of controls and control points. For example, an equation for the output enable can be written as follows: OUT_VAR.OE = IN_VAR1 # IN_VAR2