.C1.DESIGN EXAMPLES U5 This chapter provides examples of using CUPL and CSIM. It is divided into two parts. Part A provides step-by-step instructions through a sample design session. Part B describes some of the designs that can be implemented with the logic description files provided with the CUPL package. .c2.PART A. SAMPLE DESIGN SESSION This part provides step-by-step instructions through a sample design session using CUPL and CSIM. The steps in the process are: Step 1. Examining the Design Task Step 2. Creating the CUPL Source File Step 3. Formulating the Equations Step 4. Choosing a Target Device Step 5. Making the Pin Assignments Step 6. Running CUPL Step 7. Creating the CSIM Source File Step 8. Running CSIM o .c3.STEP 1. EXAMINING THE DESIGN TASK The system in this programmable logic device (PLD) design example is microprocessor-based, with the CPU interfacing with ROM and RAM. Figure U5-1 shows a diagram of the system. [Picture] Figure U5-1. Microprocessor-Based System A PLD provides a flexible interface between the CPU and peripherals by performing address decoding and timing control functions. As the diagram shows, a ROM (or PROM) is used for system control and two static RAMs are used for scratch pad and auxiliary memory functions. In this sample session, a PLD will be designed that decodes the CPU's address using a memory map, and creates chip select signals for the ROM and RAM chips based upon CPU address and CPU data strobes. The memory map in Figure U5-2 shows where the ROM and two RAM chips reside in the CPU's addressing space. [Picture] Figure U5-2. Memory Map Addresses are marked and shown in hexadecimal in the memory map. Use this memory map when designing the logic for the PLD. Because the ROM chip is slow, the PLD must be designed to perform a wait state generation that adds at least one CPU clock period to the ROM access. The worm arrows on the timing diagram in Figure U5-3 show signals affected or created by other signals. [Picture] Figure U5-3. Wait State Generator Timing Diagram A description of the operation of the timing diagram follows. The numbers in parentheses indicate the rising edge of the CLOCK signal. A wait state sequence starts with the CPU address becoming valid prior to the memory read strobe. Only the !MEMR signal needs to be considered, because the wait state is generated only for the ROM. When the !MEMR strobe is active for an address corresponding to the ROM, the !ROM_CS signal is asserted and turns on the three-state buffer, driving the CPU READY signal LO, (indicating not ready, or wait). The next rising edge of the CPU clock (1) after !ROM_CS becomes active and sets the WAIT1 signal. After one CPU clock period passes, the WAIT2 signal is asserted (2); the wait state period (one CPU clock) is completed, causing the CPU READY signal to be driven HI, which causes the CPU to continue its read cycle and remove the !MEMR strobe at the appropriate time. The !ROM_CS signal is negated, disabling the three-state buffer driving the ready signal and, at the next rising edge of the CPU clock (3), causing WAIT1 and WAIT2 to be reset. The wait state generator is now prepared for the next CPU access time. o .c3.STEP 2. CREATING A CUPL SOURCE FILE In this step, a logic description file will be created to describe the design for the PLD. The logic description file serves as input to CUPL, which compiles the design for downloading to a device programmer. To make it easy to set up the required format for the logic description file, CUPL provides a template file, TMPL.PLD, that can be copied into the file being used. First, choose a name for the file that reflects the use being designed for the PLD. Since this is a sample session, use the name SAMPLE.PLD. Copy TMPL.PLD to SAMPLE.PLD, by typing: copy tmpl.pld sample.pld [Enter] ======================================================== Note To move more quickly through this design example, it is not necessary to actually create and edit the SAMPLE.PLD file. The CUPL package provides a sample file, WAITGEN.PLD, that can be used instead. ======================================================== A completed SAMPLE.PLD file is shown here to explain the different sections of the file. This is followed by step-by step instructions for creating SAMPLE.PLD. [Picture] Figure U5-4. Source File Example Use a text editor in non-document mode to open SAMPLE.PLD. Figure U5-5 shows the template information that has been copied into the file. ----------------------------------------------------------------------- TEMPLATE FILE Name XXXXX; Partno XXXXX; Date XX/XX/XX; Revision XX; Designer XXXXX; Company XXXXX; Assembly XXXXX; Location XXXXX; /***********************************************************/ /* */ /* */ /* */ /***********************************************************/ /* Allowable Target Device */ /***********************************************************/ /** Inputs **/ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ /** Outputs **/ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ Pin = ; /* */ /** Declarations and Intermediate Variable Definitions **/ ----------------------------------------------------------------------- Figure U5-5. SAMPLE.PLD Template Information The file can be edited, in order to enter specific header and title information, specify the input and output pins, and write the intermediate and logic equations. In the header section, replace the XXXs with specific information referring to the company and the PLD being designed. Since this is a sample design, use the information provided (as shown in Figure U5-6) or any other desired information. Below the header section is a title block with comment symbols (/* and */). In the title block, type in information describing the design, as shown in Figure U5-6. ------------------------------------------------------------- SAMPLE.PLD Name Sample; Partno P9000183; Date 07/16/87; Revision 02; Designer Osann; Company ATI; Assembly PC Memory; Location U106; /******************************************************/ /* This device generates chip select signals for one */ /* 8Kx8 ROM and two 2Kx8 static RAMs. It also drives */ /* the system READY line to insert a wait-state of at */ /* least one cpu clock for ROM accesses */ /******************************************************/ ------------------------------------------------------------- Figure U5-6. SAMPLE.PLD Header and Title Block o .c3.STEP 3. FORMULATING THE EQUATIONS To make it easier to enter the specific equations for address decoding and wait state generation, first enter equations for intermediate variables. Intermediate variables are arbitrary names; that is, they do not represent specific pins. Enter the intermediate equations in the space provided in the SAMPLE.PLD file for "Declarations and Intermediate Variable Definitions." The first intermediate equation to enter is a bit field declaration to define the address bus. Use the name MEMADR (memory address) to represent the address, and type the equation as follows: FIELD MEMADR = [A15..11] ; In the system diagram in Figure U5-1, notice that the chip select signals for the static RAMs are not dependent solely upon address but must be asserted for either the MEMW or MEMR data strobes. To simplify the equations for the static RAM chip select signals, create a signal called MEMREQ (memory request). Type the following: MEMREQ = MEMW # MEMR ; Whenever MEMREQ is used in other equations, CUPL substitutes MEMW # MEMR when it compiles. Notice in the timing diagram in Figure U5-3 that the decoding of the address corresponding to the ROM combines with the !MEMR strobe to produce the ROM chip select (ROM_CS), and to initiate the wait state sequence. Create an intermediate variable, called SELECT_ROM, representing the combination of the !MEMR strobe and the specific address decoding for the ROM's address space, by typing the following: SELECT_ROM = MEMR & MEMADR :[0000..1FFF] ; After entering the above intermediate equations, the specific equations for address decoding and wait state generation may be entered. If the signal ROM_CS, which feeds back into the array, is being used to initiate the wait state timing, an additional pass delay is incurred through the PLD. Because the clock rate is relatively slow (4-8 MHz), in this example the additional delay is not a problem. However, at higher clock rates it is better to recreate the same logic (using the SELECT_ROM intermediate) in the registered logic equations. Create the ROM chip select (ROM_CS) using the intermediate variable SELECT_ROM, by typing: ROM_CS = SELECT_ROM ; The chip-selects for the two RAMs, RAM_CS0 and RAM_CS1, are dependent on MEMREQ and the address bus being within the hexadecimal boundaries taken from the memory map. Use the CUPL .i.range;range operation with the lower and upper boundaries of the desired address range to decode these signals. Type the following: RAM_CS0 = MEMREQ & MEMADR : [2000..27FF]; RAM_CS1 = MEMREQ & MEMADR : [2800..2FFF]; Next, create the equations that relate to the wait state timing and generation. First, as shown in the timing diagram (Figure U5-3), a signal called WAIT1 is required that responds to the selection of the ROM chip by being set at the next rising edge of the CPU clock. According to the rules for a D-type flip-flop, the logic level at the D input is transferred to the Q output after the clock. Enter the equation for this signal, where WAIT.D represents the signal at the D input of the flip-flop within the PLD, by typing the following: WAIT.D = SELECT_ROM & !RESET ; Notice that in the equation for WAIT1.D, the !RESET signal has been ANDed with the rest of the equation to perform a synchronous reset when the RESET signal is asserted. Next, create the signal WAIT2 at the next clock edge following the one that causes WAIT1 to set, by making the equation for WAIT2.D dependent on the signal WAIT1. Since WAIT2.D must reset at the next clock edge following the removal of the CPU's access of the ROM, and the variable, and then select_rom into this equation by typing the following: WAIT2.D = SELECT_ROM & WAIT1 ; This creates the signal SELECT_ROM in accordance with the timing diagram (Figure U5-3) to indicate that the three-state buffer should be turned on while the ROM is being decoded and the MEMR data strobe is active. Therefore, enter the equation for the three-state output by typing the following: READY.OE = SELECT_ROM ; While this equation determines when the three-state buffer actually drives its output and leaves the high impedance state, it does not determine which logic level the signal is driven to. The equation for READY determines the logic level to which the signal is driven; the signal should remain inactive at READY until the completion of a wait state period equal to one full CPU clock cycle. As this condition does not occur until WAIT2 becomes set, type the equation for READY as follows: READY = WAIT2 ; o .c3.STEP 4. CHOOSING A TARGET DEVICE After the equations are completed, the next step is to identify a compatible, commercially available PLD. Points to consider when choosing a target device are: _ The number of input pins required. _ The relative number of registered and non-registered output pins. _ Three-state output control (if required). _ The number of product terms required to implement the logic function for each equation. The PLD package diagram in Figure U5-7 shows pin assignments configured to match up with a device similar to a PAL16R4 or an 82S155 IFL. [Picture] Figure U5-7. Sample Pin Configuration In the pin configuration in Figure U5-7, the three chip select signals are assigned to I/O type pins that should always be in the output drive mode. The READY pin, attached to the READY signal on the CPU bus, is used in a controllable three-state mode. The two flip-flops that are needed to implement the wait state generator have been assigned to output pins that are internally connected to registers. One of the registered outputs could be used to drive the READY signal directly, since the logical function of READY is the same as that of the signal WAIT2. However, use of the dedicated three-state output enable signal connected to pin 11 of the target device would be required. Since pin 11 controls the three state outputs of all four pins connected to internal registers, this defeats the ability to use the other two registered output pins for any purpose other than wait state generation. It is better to keep options open by not using the dedicated three-state control, since it is difficult to predict all the changes that might be made during the evolution of a design. Therefore, pin 11 is tied to ground, which always enables the three-state outputs coming from the registers. The PAL16R4 has at least seven product terms available on all outputs, which is an adequate number for this application. The IFL 82S155, which is a second source for this socket position, has a total of thirty-two product terms available for all outputs combined, which is also an adequate number for this application. The PAL16R4 devices have only D-type flip-flops, whereas the 82S155 devices may be configured for either D or JK types. CUPL automatically chooses a D-type flip flop configuration because the equations entered for WAIT1 and WAIT2 in step 3 specified the .D extension. o .c3.STEP 5. MAKING THE PIN ASSIGNMENTS Match the pin assignments to the pins in Figure U5-7 for a PAL16R4 or 82S155 device. First, in SAMPLE.PLD in the comment space labeled "Allowable Target Device Types," type: pal16r4, 82s155 [Enter] To ensure consistent documentation when making the pin assignments, be certain that the signal polarities (signal levels) assigned are the same as those in the logic schematic. Make the pin assignments as shown in Figure U5-8. -------------------------------------------------------------- SAMPLE PIN ASSIGNMENTS /** Inputs **/ Pin 1 = cpu_clk ; /* CPU clock */ Pin [2..6] = [a15..11] ; /* CPU Address Bus */ Pin [7,8] = ![memw,memr] ; /* Memory Data Strobes */ Pin 9 = reset ; /* System Reset */ Pin 11 = !oe ; /* Output Enable */ /** Outputs **/ Pin 19 = !rom_cs ; /* ROM Chip select */ Pin 18 = ready ; /* CPU Ready signal */ Pin 15 = wait1 ; /* Start wait state */ Pin 14 = wait2 ; /* End wait state */ Pin [13,12] = ![ram_cs1..0] ; /* RAM Chip selects */ -------------------------------------------------------------- Figure U5-8. SAMPLE.PLD Pin Assignments After making all the pin assignments, delete the extra "pin = ;" lines provided by the template file. Figure U5-9 shows the completed logic description file, SAMPLE.PLD. -------------------------------------------------------------- SAMPLE.PLD Name Sample; Partno P9000183; Date 07/16/87; Revision 02; Designer Osann; Company ATI; Assembly PC Memory; Location U106; /******************************************************/ /* This device generates chip select signals for one */ /* 8Kx8 ROM and two 2Kx8 static RAMs. It also drives */ /* the system READY line to insert a wait-state of at */ /* least one cpu clock for ROM accesses */ /******************************************************/ /******************************************************/ /** Allowable Target Device Types : PAL16R4, 82S155 **/ /******************************************************/ /** Inputs **/ Pin 1 = cpu_clk ; /* CPU clock */ Pin [2..6] = [a15..11] ; /* CPU Address Bus */ Pin [7,8] = ![memw,memr] ;/* Memory Data Strobes (low-true) */ Pin 9 = reset ; /* System Reset */ Pin 11 = !oe ; /* Output Enable (active low) */ /** Outputs **/ Pin 19 = !rom_cs ; /* ROM chip select (low-true) */ Pin 18 = ready ; /* CPU ready */ Pin 15 = wait1 ; /* Wait state 1 */ Pin 14 = wait2 ; /* Wait state 2 */ Pin [13,12] = ![ram_cs1..0] ; /* RAM chip select (low-true) */ /** Declarations and Intermediate Variable Definitions */ Field memadr = [a15..11] ; /* Give the address bus */ /* the Name "memadr" */ memreq = memw # memr ; /* Create the intermediate */ /* variable "memreq" */ select_rom = memr & memadr:[0000..1FFF] ; /* = rom_cs */ /** Logic Equations **/ rom_cs = select_rom; ram_cs0 = memreq & memadr:[2000..27FF] ; ram_cs1 = memreq & memadr:[2800..2FFF] ; /* read as: when select_rom is true and reset is false */ wait1.d = select_rom & !reset ; /* read as: when when select_rom is true and wait1 is true */ /* Synchronous Reset */ wait2.d = select_rom & wait1 ; /* wait1 delayed */ ready.oe = select_rom ; /* Turn Buffer off */ ready = wait2 ; /* end wait */ -------------------------------------------------------------- Figure U5-9. SAMPLE.PLD File o .c3.STEP 6. RUNNING CUPL When running CUPL, specify the target PLD, the source logic description file, and option flags to enable specific output files. In this step, compile the logic description file SAMPLE.PLD for the target device PAL16R4, and create the following output files: SAMPLE.ABS (-a flag) - This is the absolute file for later use by CSIM, the CUPL simulator (This file is needed for step 7). It contains a condensed representation of the logical function to be programmed into a device. CSIM compares this representation to test vectors in a user-created input file to determine whether the response vectors in the input file are a correct response to the stimulus vectors. SAMPLE.DOC (-x, and -f flags) - This is the documentation file. It provides fully expanded product terms for both intermediate and output pin variables, and a fuse plot and chip diagram. SAMPLE.LST (-l flag) - This is the list file. It is a recreation of the description file, except line numbers have been added and any error messages generated during compilation are appended at the end of the file. SAMPLE.JED (-j flag) - This is a JEDEC file for downloading to a device programmer. It contains a fuse pattern but no test vectors. ======================================================== Note The SAMPLE.JED filename is determined by the NAME field in the header information section of the logic description file. When only one device is described in the file, be certain to use the same name (in this case, SAMPLE) as the filename. ======================================================== To begin to compile and create the files described above, type the following .i.command line;command line: cupl -jaxfl p16r4 sample [Enter] ======================================================== Note If SAMPLE.PLD has not been created, type WAITGEN instead of SAMPLE to specify the sample file, WAITGEN.PLD, provided by CUPL. The filename for all output files created by CUPL is WAITGEN instead of SAMPLE. ======================================================== The following messages appear on the screen, indicating how much time each CUPL module takes for completion. The actual time will vary depending on the system being used. CUPL: Universal Compiler for Programmable Logic Version 4.XX Serial # XX-XXX-XXXX Copyright (C) 1983, 1990 Logical Devices, Inc. cuplx time: 2 secs cupla time: 2 secs cuplb time: 2 secs cuplm time: 1 secs cuplc time: 5 secs total time: 12 secs When the prompt appears, compilation is complete. SAMPLE.LST and SAMPLE.DOC are ASCII files, so it is possible to display them on the screen, open them with a text editing program, or print a hard copy of their contents. The list file, SAMPLE.LST, is essentially a recreation of the source file with line numbers inserted and any error messages attached to the end. The line numbers facilitate the quick locating of error sources, if any are detected by CUPL. Figure U5-10 shows the contents of SAMPLE.LST. --------------------------------------------------------------------- SAMPLE.LST CUPL Version 4.XX Serial # XX-XXX-XXXX Copyright (C) 1983,1990 Logical Devices,Inc. CREATED Thur Jan 14 08:42:12 1990 LISTING FOR LOGIC DESCRIPTION FILE: sample.pld; 1:Name Sample; 2:Partno P9000183; 3:Date 07/16/87; 4:Revision 02; 5:Designer Osann; 6:Company ATI; 7:Assembly PC Memory; 8:Location U106; 9: 10:/******************************************************/ 11:/* This device generates chip select signals for one */ 12:/* 8Kx8 ROM and two 2Kx8 static RAMs. It also drives */ 13:/* the system READY line to insert a wait-state of at */ 14:/* least one cpu clock for ROM accesses */ 15:/******************************************************/ 16:/******************************************************/ 17:/** Allowable Target Device Types : PAL16R4, 82S155 **/ 18:/******************************************************/ 19:/** Inputs **/ 20: 21:Pin 1 = cpu_clk ; /* CPU clock */ 22:Pin [2..6] = [a15..11] ; /* CPU Address Bus */ 23:Pin [7,8] = ![memw,memr] ; /* Memory Data Strobes */ 24:Pin 9 = reset ; /* System Reset */ 25:Pin 11 = !oe ; /* Output Enable */ 26: 27:/** Outputs **/ 28: 29:Pin 19 = !rom_cs ; /* */ 30:Pin 18 = ready ; /* */ 31:Pin 15 = wait1 ; /* */ 32:Pin 14 = wait2 ; /* */ 33:Pin [13,12] = ![ram_cs1..0] ; /* */ 34: 35:/** Declarations and Intermediate Variable Definitions */ 36: 37:Field memadr = [a15..11] ; /* Give the address bus */ 38: /* the Name "memadr" */ 39: 40:memreq = memw # memr ; /*Create the intermediate */ 41: /*variable "memreq" */ 42: 43:select_rom = memr & memadr:[0000..1FFF]; /* = rom_cs */ 44: 45:/** Logic Equations **/ 46: 47:rom_cs = select_rom; 48:ram_cs0 = memreq & memadr:[2000..27FF] ; 49:ram_cs1 = memreq & memadr:[2800..2FFF] ; 50:wait1.d = select_rom & !reset ; 51: /* Synchronous Reset */ 52:wait2.d = select_rom & wait1 ; /* wait1 delayed */ 53:ready.oe = select_rom ; /* Turn Buffer off */ 54:ready = wait2 ; /* end wait */ Jedec Fuse Checksum (4D50) Jedec Transmit Checksum (E88F) --------------------------------------------------------------------- Figure U5-10. SAMPLE.LST Figure U5-11 shows the documentation file, SAMPLE.DOC, created by CUPL. --------------------------------------------------------------------- SAMPLE.DOC ************************************************************************ Sample ************************************************************************ CUPL 4.XX Serial# XX-XXX-XXXX Device p16r4 Library DLIB-d-26-11 Created Mon Aug 20 10:48:32 1990 Name Sample; Partno P9000183; Date 04/1/90; Revision 02; Designer Osann; Company ATI; Assembly PC Memory; Location U106; ======================================================================== Expanded Product Terms ======================================================================== wait1.d => !memr # a15 # a14 # a13 # reset select_rom => !a13 & !a14 & !a15 & memr wait2.d => !memr # a15 # a14 # a13 !wait memadr => a15,a14,a13,a12,a11 ready => !wait2 ready.oe => !a13 & !a14 & !a15 & memr rom_cs => !a13 & !a14 & !a15 & memr Figure U5-11. SAMPLE.DOC Sheet 1 of 4 memreq => memw # memr ram_cs0 => !a11 & !a12 & !a13 & !a14 & !a15 & memw # !a11 & !a12 & !a13 & !a14 & !a15 & memr ram_cs1 => a11 & !a12 & a13 & !a14 & !a15 & memw # a11 & !a12 & a13 & !a14 & !a15 & memr rom_cs.oe => 1 ram_cs0.oe => 1 ram_cs1.oe => 1 ============================================================================== Symbol Table ============================================================================== Pin Variable Pterms Max Min Pol Name Ext Pin Type Used Pterms Level --- -------- --- --- ---- ------ ------ ------ wait1 15 V - - - wait1 d 15 X 5 8 1 a11 6 V - - select_rom I 1 - - wait2 14 V - - - wait2 d 14 X 5 8 1 a12 5 V - - a13 4 V - - - a14 3 V - - - a15 2 V - - - ! oe 11 V - - - ! memr 8 V - - - memadr 0 F - - - ready 18 V 1 7 1 ready oe 18 X 1 1 1 ! memw 7 V - - - cpu_clk 1 V - - - ! rom_cs 19 V 1 7 1 reset 9 V - - - memreq 0 I 2 - - ! ram_cs0 12 V 2 7 1 ! ram_cs1 13 V 2 7 1 rom_cs oe 19 D 1 1 0 ram_cs0 oe 12 D 1 1 0 ram_cs1 oe 13 D 1 1 0 LEGEND F : field D : default M : extended node N : node I : Intermediate variable T : function V : variable X : extended variable U : undefined Figure U5-11. Sheet 2 of 4 ================================================================ ` Fuse Plot ================================================================ Pin #19 0000 -------------------------------- 0032 -x---x---x---------------x------ 0064 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0096 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0128 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0160 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0192 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0224 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Pin #18 0256 -x---x---x---------------x------ 0288 -----------------------x-------- 0320 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0352 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0384 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0416 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0448 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0480 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxPin #17 0512 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0544 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0578 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0608 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0640 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0672 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0704 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0738 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Pin #16 0768 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0800 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0832 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0864 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0896 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0928 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0960 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0992 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Pin #15 1024 ------------------------x------- 1056 x------------------------------- 1088 ----x--------------------------- 1120 --------x----------------------- 1152 ----------------------------x--- 1184 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1216 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1248 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Pin #14 1280 ------------------------x------- 1312 x------------------------------- 1344 ----x--------------------------- 1378 --------x----------------------- 1408 -------------------x------------ 1440 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1472 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1504 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Figure U5-11. Sheet 3 of 4 Pin #13 1536 -------------------------------- 1568 -x---x--x----x--x----x---------- 1600 -x---x--x----x--x--------x------ 1632 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1664 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1696 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1728 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1760 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Pin #12 1792 -------------------------------- 1824 -x---x--x----x---x---x---------- 1856 -x---x--x----x---x-------x------ 1888 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1920 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1952 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1984 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 2016 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ======================================================================== Chip Diagram ======================================================================== -------------- | WAITGEN | cpu_clk x---| 1 20 |---x VCC | | a15 x---| 2 19 |---x !rom_cs | | a14 x---| 3 18 |---x ready | | a13 x---| 4 17 |---x | | a12 x---| 5 16 |---x | | a11 x---| 6 15 |---x wait1 | | !memw x---| 7 14 |---x wait2 | | !memr x---| 8 13 |---x !ram_cs1 | | reset x---| 9 12 |---x !ram_cs0 | | GND x---|10 11 |---x !oe | | -------------- --------------------------------------------------------------------- Figure U5-11. Sheet 4 of 4 The expanded product terms for WAIT1.D and WAIT2.D show five product terms, because the fixed inverting output buffer (active-LO architecture) in the PAL16R4 causes CUPL to perform DeMorgan's Theorem on equations when an output variable has been declared as active-HI in the pin list for this particular device. o .c3.STEP 7. CREATING A CSIM SOURCE FILE In this step, a simulation will be performed to verify the compiled design for the PAL16R4 device. Performing this step before downloading to a logic programmer decreases the probability of programming a device with incorrect logic. Create a source specification file, SAMPLE.SI, containing test vectors for input to CSIM. CSIM compares the test vector inputs and expected outputs to the actual values contained in the SAMPLE.ABS file that was created during CUPL operation, and flags any discrepancies. Figure U5-12 shows the contents of a sample source specification file. ---------------------------------------------------------------- Name Sample; Partno P9000183; Date 07/16/87; Revision 02; Designer Osann; Company ATI; Assembly PC Memory; Location U106; /******************************************************/ /* This device generates chip select signals for one */ /* 8Kx8 ROM and two 2Kx8 static RAMs. It also drives */ /* the system READY line to insert a wait-state of at */ /* least one cpu clock for ROM accesses */ /******************************************************/ ORDER: cpu_clk, %2, a15, %2, a14, %2, a13, %2, a12, %2, a11, %2, !memw, %2, !memr, %2, reset, %2, !oe, %4, !ram_cs1, %2, !ram_cs0, %2, !rom_cs, %2, wait1, %2, wait2, %2, ready; VECTORS: /* 123456-leave six blanks to allow for numbers in .SO file */ $msg " ! !"; $msg " c r r !"; $msg " p a a r"; $msg " u ! ! r m m o w w r"; $msg " _ m m e _ _ m a a e"; $msg " c a a a a a e e s ! c c _ i i a"; $msg " l 1 1 1 1 1 m m e o s s c t t d"; $msg " k 5 4 3 2 1 w r t e 1 0 s 1 2 y"; $msg " ____________________________________________"; $msg " Power On Reset "; O X X X X X 1 1 1 0 H H H * * Z $msg " Reset Flip Flops "; C X X X X X 1 1 0 0 H H H L L Z $msg " Write RAM0 "; 0 0 0 1 0 0 0 1 0 0 H L H L L Z $msg " Read RAM0 "; 0 0 0 1 0 0 1 0 0 0 H L H L L Z $msg " Write RAM1 "; 0 0 0 1 0 1 0 1 0 0 L H H L L Z $msg " Read RAM1 "; 0 0 0 1 0 1 1 0 0 0 L H H L L Z $msg " Begin ROM read "; 0 0 0 0 0 0 1 0 0 0 H H L L L L $msg " Two clocks for wait state, Then drive READY High "; $repeat 2; C 0 0 0 0 0 1 0 0 0 H H L * * * $msg " End ROM Read "; 0 0 0 0 0 0 1 1 0 0 H H H H H Z $msg " End ROM Read "; C 0 0 0 0 0 1 1 0 0 H H H L L Z ---------------------------------------------------------------- Figure U5-12. SAMPLE.SI The source specification file contains three major parts: header information and title block, an ORDER statement, and a VECTORS statement. SAMPLE.SI must have the same header information as SAMPLE.PLD to ensure that the proper files, including current revision level, are being compared against each other. Therefore, first copy SAMPLE.PLD to SAMPLE.SI and then use a text editor to delete everything in SAMPLE.SI, except the header and title block. Figure U5-13 shows the result. ---------------------------------------------------------------- Name Sample; Partno P9000183; Date 07/16/87; Revision 02; Designer Osann; Company ATI; Assembly PC Memory; Location U106; /******************************************************/ /* This device generates chip select signals for one */ /* 8Kx8 ROM and two 2Kx8 static RAMs. It also drives */ /* the system READY line to insert a wait-state of at */ /* least one cpu clock for ROM accesses */ /******************************************************/ ---------------------------------------------------------------- Figure U5-13. SAMPLE.SI Header Information In the ORDER statement, list the input and output variables from SAMPLE.PLD to be included in test vectors. List the variables in the order in which they will be used in test variables; that is, put the clock variable, CPU_CLK, first, followed by the other input variables. Put the output variables to the right. Separate variables with commas. Use the % symbol to insert spaces between the variables; put two spaces between each variable, and four spaces between the last input variable in the list, !OE, and the first output variable, !RAM_CS1. Type the ORDER statement as follows: ORDER: CPU_CLK, %2, A15, %2, A14, %2, A13, %2,A12, %2, ALL, %2, !MEMW, %2, !MEMR, %2, RESET, %2, !OE, %4, !RAM_CS1, %2, !RAM_CSO, %2, !ROM_CS, %2 WAIT1, %2, READY; Following the ORDER statement, enter a VECTORS statement that creates a function table containing eleven test vectors (see Figure U5-12). First, to make the vectors easier to enter and understand, use the $MSG command to create a heading for the function table. List the variable names in vertical columns in the same order and with the same spacing as specified in the ORDER statement, by typing the information in Figure U5-14. -------------------------------------------------------------------- /* 123456-leave six blanks to allow for numbers in .SO file */ $msg " ! !"; $msg " c r r !"; $msg " p a a r"; $msg " u ! ! r m m o w w r"; $msg " _ m m e _ _ m a a e"; $msg " c a a a a a e e s ! c c _ i i a"; $msg " l 1 1 1 1 1 m m e o s s c t t d"; $msg " k 5 4 3 2 1 w r t e 1 0 s 1 2 y"; $msg " ____________________________________________"; -------------------------------------------------------------------- Figure U5-14. Vectors Table Header Now enter the test vectors. Create the vectors by assigning a value to each of the input variables and an expected value to each of the output variables. Refer to Table 4-4 in Chapter 4, "Using CSIM", for allowable values to use for test vectors. Use the $MSG directive to describe the device function tested by the function. The ORDER statement above specifies the spacing when creating the test vectors. For example, create the first vector, Power On Reset, by typing: $msg " Power On Reset "; 0 X X X X X 1 1 1 0 H H H * * Z Note that the output value (*) has been used for WAIT1 and WAIT2 to instruct CSIM to calculate the power-on state of the registers, since some devices power-on to X and some to H or L. Using the asterisk gives a more universal simulation file. Type in the rest of the test vectors, as shown in Figure U5-15. ----------------------------------------------------------- $msg " Power On Reset "; O X X X X X 1 1 1 0 H H H * * Z $msg " Reset Flip Flops "; C X X X X X 1 1 0 0 H H H L L Z $msg " Write RAM0 "; 0 0 0 1 0 0 0 1 0 0 H L H L L Z $msg " Read RAM0 "; 0 0 0 1 0 0 1 0 0 0 H L H L L Z $msg " Write RAM1 "; 0 0 0 1 0 1 0 1 0 0 L H H L L Z $msg " Read RAM1 "; 0 0 0 1 0 1 1 0 0 0 L H H L L Z $msg " Begin ROM read "; 0 0 0 0 0 0 1 0 0 0 H H L L L L $msg " Two clocks for wait state, Then drive READY High "; $repeat 2; C 0 0 0 0 0 1 0 0 0 H H L * * * $msg " End ROM Read "; 0 0 0 0 0 0 1 1 0 0 H H H H H Z $msg " End ROM Read "; C 0 0 0 0 0 1 1 0 0 H H H L L Z ----------------------------------------------------------- Figure U5-15. Test Vectors The $REPEAT directive in the test vectors causes the eighth vector to be repeated twice. The asterisks in the eighth vector for WAIT1, WAIT2, and READY tell CSIM to compute the output based on the inputs and place the results in the output file. The value of the clock variable, CPU_CLK, is 0 in some vectors and C in others. A value of 0 causes no clocking to occur. A value of C causes CSIM to examine the input values in the vector and also look back to the previous vector for any registered outputs that would be fed back internally prior to the clock. Then, after a clock is applied, CSIM computes the appropriate expected outputs for registered and non-registered variables. After putting in the VECTORS statement, save the file. The next step is to run CSIM to perform the simulation. o .c3.STEP 8. RUNNING CSIM When CSIM is run, it creates SAMPLE.SO, which contains the result of the simulation. Specify the -l flag to list any errors that might be generated. To run CSIM, type: csim -1 p16r4 sample [Enter] ============================================================ Note If WAITGEN.PLD was used to run CUPL in step 6, specify WAITGEN instead of SAMPLE when running CSIM. ============================================================ CSIM displays the amount of time to perform the simulation, as follows: CSIM: CUPL Simulation Program Version 4.XX Serial # XX-XXX-XXXXCopyright (C) 1983, 1990 Logical Devices, Inc. csima time: 4 secs total time: 4 secs When the prompt reappears, the simulation is complete. SAMPLE.SO is an ASCII file, so it is possible to display it on the screen, print a hardcopy of it, or open it with a text editor. Figure U5-16 shows the contents of SAMPLE.SO. ----------------------------------------------------------- SAMPLE.SO CSIM: CUPL Simulation Program Version 4.XX Serial # XX-XXX-XXXX copyright (c) 1983,1990 Logical Devices, Inc. CREATED Thur Aug 20 09:34:16 1990 1: Name Sample; 2: Partno P9000183; 3: Date 07/16/87; 4: Revision 02; 5: Designer Osann; 6: Company ATI; 7: Assembly PC Memory; 8: Location U106; 9: 10: /******************************************************/ 11: /* This device generates chip select signals for one */ 12: /* 8Kx8 ROM and two 2Kx8 static RAMs. It also drives */ 13: /* the system READY line to insert a wait-state of at */ 14: /* least one cpu clock for ROM accesses */ 15: /******************************************************/ 16: 17: ORDER: 18: cpu_clk, %2, a15, %2, a14, %2, 19: a13, %2, a12, %2, a11, %2, 20: !memw, %2, !memr, %2, reset, %2, !oe, 21: %4, !ram_cs1, %2, !ram_cs0, %2, !rom_cs, %2, 22: wait1, %2, wait2, %2, ready; 23: ================================================================= Simulation Results ================================================================= ! ! c r r ! p a a r u ! ! r m m o w w r _ m m e _ _ m a a e c a a a a a e e s ! c c _ i i a l 1 1 1 1 1 m m e o s s c t t d k 5 4 3 2 1 w r t e 1 0 s 1 2 y ____________________________________________ Power On Reset 0001: O X X X X X 1 1 1 0 H H H X X Z Reset Flip Flops 0002: C X X X X X 1 1 0 0 H H H L L Z Write RAM0 0003: 0 0 0 1 0 0 0 1 0 0 H L H L L Z Read RAM0 0004: 0 0 0 1 0 0 1 0 0 0 H L H L L Z Write RAM1 0005: 0 0 0 1 0 1 0 1 0 0 L H H L L Z Read RAM1 0006: 0 0 0 1 0 1 1 0 0 0 L H H L L Z Begin ROM read 0007: 0 0 0 0 0 0 1 0 0 0 H H L L L L Two clocks for wait state, Then drive READY High 0008: C 0 0 0 0 0 1 0 0 0 H H L H L L 0009: C 0 0 0 0 0 1 0 0 0 H H L H H H End ROM Read 0010: 0 0 0 0 0 0 1 1 0 0 H H H H H Z End ROM Read 0011: C 0 0 0 0 0 1 1 0 0 H H H L L Z ----------------------------------------------------------- Figure U5-16. SAMPLE.SO Compare SAMPLE.SO to the SAMPLE.SI file in Figure U5-12. Note that vectors 8 and 9 were created as a result of the $REPEAT directive, and that CSIM has replaced the asterisks from SAMPLE.SI with the appropriate logic levels (H and L) for the WAIT1, WAIT2 and READY signals. Now that a successful simulation has been completed, test vectors can be added to the JEDEC file created while running CUPL (in step 6). Run the simulation again with the -j option flag, by typing: csim -j p16r4 sample [Enter] If WAITGEN.SI was used to perform the simulation, specify it here instead of SAMPLE.SI. Figure U5-17 shows the contents of SAMPLE.JED, which now contains both programming and testing information. ----------------------------------------------------------- SAMPLE.JED CUPL 4.XX Serial# XX-XXX-XXXX Device p16r4 Library DLIB-d-26-11 Created Thur Aug 20 09:52:02 1990 Name Sample Partno P9000183 Revision 02 Date 12/16/89 Designer Osann Company ATI Assembly PC Memory; Location U106; *QP20 *QF2048 *G0 *F0 *L00000 11111111111111111111111111111111 *L00032 10111011101111111111111110111111 *L00256 10111011101111111111111110111111 *L00288 11111111111111111111111011111111 *L01024 11111111111111111111111101111111 *L01056 01111111111111111111111111111111 *L01088 11110111111111111111111111111111 *L01120 11111111011111111111111111111111 *L01152 11111111111111111111111111110111 *L01280 11111111111111111111111101111111 *L01312 01111111111111111111111111111111 *L01344 11110111111111111111111111111111 *L01376 11111111011111111111111111111111 *L01408 11111111111111111110111111111111 *L01536 11111111111111111111111111111111 *L01568 10111011011110110111101111111111 *L01600 10111011011110110111111110111111 *L01792 11111111111111111111111111111111 *L01824 10111011011110111011101111111111 *L01856 10111011011110111011111110111111 *C4D50 *V0001 0XXXXX111N0HHXXXXZHN *V0002 CXXXXX110N0HHLLXXZHN *V0003 000100010N0LHLLXXZHN *V0004 000100100N0LHLLXXZHN *V0005 000101010N0HLLLXXZHN *V0006 000101100N0HLLLXXZHN *V0007 000000100N0HHLLXXLLN *V0008 C00000100N0HHLHXXLLN *V0009 C00000100N0HHHHXXHLN *V0010 000000110N0HHHHXXZHN *V0011 C00000110N1HHLLXXZHN *3152 ----------------------------------------------------------- Figure U5-17. SAMPLE.JED with Test Vectors o .c3.SUMMARY This part provided the opportunities to create and compile a CUPL source file and a CSIM test specification file. The important points were how to: _ Use the template file. _ Choose a PLD and make pin assignments. _ Write intermediate and logic equations to describe the design. _ Run CUPL to compile a file. _ Create and compile a test specification file to verify the design. _ Run CSIM to simulate a logic design. The design examples in Part B do not provide the same step-by-step instruction, but are provided as familiarization with how CUPL can be used to describe different types of designs. .c2.PART B. SAMPLE PLD FILES This section lists the logic description files that are included in the CUPL package to illustrate how CUPL and CSIM implement various designs. FILE: ADDER.PLD DEVICES: PAL16L8, PAL16P8, 82S153 4-bit asynchronous adder implemented as a ripple-carry through four adder-slice circuits. Each adder-slice was implemented using a user-defined function. FILE: ADDER_TT.PLD DEVICES: RA9P8 (512x8 PROM) 4-bit asynchronous adder implemented using a truth table. Makes use of nested $REPEAT statements. FILE: BARREL22.PLD DEVICES: PAL22V10 8-bit registered barrel shifter with synchronous presetting capability. FILE: BUSARB.PLD DEVICES: 82S105 Multiprocessor bus arbiter having two machines in one design. FILE: COUNT8.PLD DEVICES: PAL20X8 8-bit counter with parallel load, clear, and hold using XOR capability. FILE: COUNT8A.PLD DEVICES: PAL20X8 8-bit counter with parallel load, clear, and hold using set notation. FILE: COUNT10.PLD DEVICES: PAL16RP4, GAL16V8 4-bit up/down decade counter with synchronous clear capability. An asynchronous ripple carry output is provided for cascading multiple devices. FILE: COUNT13.PLD DEVICES: PAL32R16 13-bit counter using set notation with parallel load hold and clear. FILE: CYP_CNT.PLD DEVICES: CY7C330 Up/Down counter with preloadable upper and lower limits. FILE: DATASEP.PLD DEVICES: EP600 Single density 8" floppy disk data separator. FILE: DECADE.PLD DEVICES: 82S157 4-bit synchronous free-running decade counter that uses the complement-array to force invalid states to reset the counter registers. State machine syntax is used. FILE: FLOP.PLD DEVICES: PAL16R8, PAL16RP8, 82S159 Using D-type flip-flop to create a 2-bit counter (four ways). FILE: GATES.PLD DEVICES: PAL16L8, PAL16P8 , 82S153 Simple use of NOT, AND, OR, and XOR gates. FILE: HEXDISP.PLD DEVICES: RA5p8 (32x8 PROM) Hexidecimal to 7-segment decoder used for displaying numbers. FILE: IODECODE.PLD DEVICES: PAL12L6 , PAL12P6, 82S153 A chip select signal generator for I/O functions. It also enables the data bus transceiver for both memory and I/O write cycles. FILE: IOPORT.PLD DEVICES: PAL20RA10 7-bit register with handshake logic used to interface between a microprocessor and I/O port. FILE: KEYBOARD.PLD DEVICES: 82S100 Converts the rows and columns of a matrix keyboard and generates the corresponding ASCII code required for the key. FILE: LOOKUP.PLD DEVICES: RA8P8 (256 x 8 EPROM) Arithmetic lookup table that calculates the perimeter of a circle given the radius. Truth table syntax is used. FILE: MDECODE.PLD DEVICES: PAL16L8, PAL16P8 , 82S153 A memory RAS generator and CAS signal initiator. It also enables the data bus transceiver for both memory and I/O read cycles. FILE: MULTIBUS.PLD DEVICES: PAL23S8 Simple MULTIBUS arbiter supports parallel and serial priority. FILE: PRIORITY.PLD DEVICES: PALR19L8 Priority Interrupt Encoder for the Motorola 68000 using both Boolean equations and Conditional syntax. The use of input registers is shown. FILE: RIPPLE8.PLD DEVICES: PAL20RA10 8-bit ripple counter with asynchronous load. FILE: SHFTCNT.PLD DEVICES: 82S105 4-bit counter/shifter using SR -type flip-flops. FILE: SHFTCNT4.PLD DEVICES: 82S159 4-bit counter/shifter using JK-type flip-flops. FILE: SHFTCNT6.PLD DEVICES: 82S167 4-bit counter/shifter using SR-type flip-flops. FILE: STEPPER.PLD DEVICES: PALT19R6 Memory mapped stepper motor controller interfaced to the 8048 single chip microprocessor. FILE: TCOUNTER.PLD DEVICES: EP600 16-bit up/down counter with built-in shift register using toggle flip-flops. FILE: TTL.PLD DEVICES: PAL16L8 Multiple TTL chip representation using $Macros from the $Include file. Any of these logic description files can be viewed or printed out, or they can be input to CUPL to generate documentation or download files. A corresponding test specification file (filename.SI) is also provided for each logic description file, so that CSIM can be run to verify the designs. The following examples describe key points of the following designs (the logic description file for each design is shown in parentheses): _ Simple gates (GATES.PLD) _ TTL conversion (WGTTL.PLD) _ Two-bit counter (FLOPS.PLD) _ Decade up/down counter using state-machine syntax (COUNT10.PLD) _ Seven-segment display decoder (HEXDISP.PLD) o .c3.EXAMPLE 1. SIMPLE GATES This example describes a design containing simple gates. Figure U5-18 shows the design. [Picture] Figure U5-18. Design with Simple Gates The outputs are labeled to reflect the function of their gate; for example, the AND gate has an output labeled AND. Figure U5-19 shows the CUPL source file (GATES.PLD provided in the CUPL package) that describes the design. ----------------------------------------------------------------- GATES.PLD Name Gates; Partno CA0001; Date 07/16/87; Designer G Woolheiser; Company ATI; Location San Jose, CA.; Assembly Example; /******************************************************/ /* */ /* This is an example to demonstrate how CUPL */ /* compiles simple gates. */ /* */ /******************************************************/ /* Target Devices: P16L8, P16P8, EP300, and 82S153 */ /******************************************************/ /* Inputs: define inputs to build simple gates */ Pin 1 = a; Pin 2 = b; /* Outputs: define outputs as active HI levels For PAL16L8 and PAL16LD8, De Morgan's Theorem is applied to invert all outputs due to fixed inverting buffer in the device. */ Pin 12 = inva; Pin 13 = invb; Pin 14 = and; Pin 15 = nand; Pin 16 = or; Pin 17 = nor; Pin 18 = xor; Pin 19 = xnor; /* Logic: examples of simple gates expressed in CUPL */ inva = !a; /* inverters */ invb = !b; and = a & b; /* and gate */ nand = !(a & b); /* nand gate */ or = a # b; /* or gate */ xor = a $ b; /* xor gate */ nor = !(a # b) /* nor gate */ xnor = !(a $ b); /* exclusive nor gate */ ----------------------------------------------------------------- Figure U5-19. Simple Gates Source File (GATES.PLD) The first part of the file provides archival information and a description of the intended function of the design, including compatible PLDs. Pin declarations are made corresponding to the inputs and outputs in the design diagram. In the "Logic" section of the file, equations describe each of the gates in the design. For the PAL16L8 and PAL16LD8 devices, which contain fixed inverting buffers, CUPL applies DeMorgan's Theorem to invert all outputs because they were all declared active-HI in the pin list. For example, during compilation, CUPL converts the following equation for an OR gate, on an output pin that has been declared as active high: or = a # b ; to the following single expanded product term (as shown in the documentation file): or => !a & !b o .c3.EXAMPLE 2. CONVERTING A TTL DESIGN TO PLDs This example shows how to use a PLD to replace existing TTL circuitry. The conversion requires translating the gates of a TTL logic design into equivalent Boolean logic equations, which can then be compiled by CUPL and assigned to a PLD. Figure U5-20 shows the TTL gate representations used in designing logic systems and the corresponding Boolean equation for each gate. [Picture] Figure U5-20. TTL Gate Representations and Boolean Equations The basic conversion rules shown in Figure U5-20 are sufficient to write equations for each gate within a system of TTL gates when converting the logic to a PLD equivalent. CUPL uses an expression substitution process to build larger equations from the smaller expressions representing each gate in the TTL schematic. Expression substitution permits approaching a schematic one gate at a time. Figure U5-21 shows the schematic for the TTL logic that is converted in Example 1. [Picture] Figure U5-21. TTL Schematic The TTL logic shown in Figure U5-21 performs the same address decoding and wait state generation as the WAITGEN.PLD file contained in the CUPL distribution package. The SAMPLE.PLD file created in the sample design session (see Part A of this chapter) is identical to WAITGEN.PLD.The PLD equivalent of this TTL circuit replaces five to six packages with one device.The first step in the conversion process is to determine from the TTL schematic the logic that is to be placed in the PLD. Figure U5-22 shows a PLD diagram equivalent to the TTL schematic with a box around the logic, and PLD pin number assignments. [Picture] Figure U5-22. PLD Equivalent Diagram Note that the outputs of the internal gates (those that do not connect to the PLD output pins) are arbitrarily labeled with the variable names, A-H, to aid in entering equations in the logic description file. The logic description file used to convert this design is named WGTTL.PLD because it performs wait state generation and is based on a TTL design. Figure U5-23 shows the contents of WGTTL.PLD. ----------------------------------------------------------------- WGTTL.PLD Name Sample; Partno P9000183; Date 07/16/87; Revision 02; Designer Osann; Company ATI; Assembly PC Memory; Location U106; /********************************************************/ /* This device generates chip select signals for one */ /* 8Kx8 ROM and two 2Kx8 static RAMs. It also drives */ /* the system READY line to insert a wait-state of at */ /* least one cpu clock for ROM accesses */ /********************************************************/ /** Inputs **/ PIN 1 = cpu_clk ; /* CPU clock */ PIN [2..6] = [a15..11] ; /* CPU Address Bus */ PIN [7 8] = ![memw,memr] ; /* Memory Data Strobes*/ PIN 9 = reset ; /* System Reset */ PIN 11 = !oe ; /* Output enable */ /** Outputs **/ PIN 19 = !rom_cs ; /* ROM Chip Select */ PIN 18 = ready ; /* CPU ready signal */ PIN 15 = wait1 ; /* Start wait state */ PIN 14 = wait2 ; /* End wait state */ PIN [13,12] = ![ram_cs1..0] ; /* RAM chip selects */ /** Declarations and Intermediate Variable Definitions **/ a = !(!memw) # !(!memr) ; b = !a15 & !a14 ; c = !a13 ; d = !a12 & !a11 ; e = !a11 ; f = !a12 & !oe ; g = !(!rom_cs # reset) ; h = !(!memr) ; /** Logic Equations **/ !rom_cs = !(h & b & c); !ram_cs0 = !(a & b & a13 & d) ; !ram_cs1 = !(a & b & a13 & f) ; wait1.d = g ; wait2.d = wait1 & g ; ready.oe = !(!(h & b & c)) ; ready = wait2 ; ----------------------------------------------------------------- Figure U5-23. WGTTL.PLD The header information is identical to that in WAITGEN.PLD (and SAMPLE.PLD; see Part A), because the functionality is the same. The pin assignments match the schematic in Figure U5-22. The logic equations for the internal gates are placed in the section of the file for "Declarations and Intermediate Variable Definitions." The equations in this section use the output variable names, A-H, assigned in the schematic in Figure U5-22. For example, the AND gate LS02 is described by the following equation: d = !a12 & !a11 ; The equations in this section can be simplified. For example, the double negations can be eliminated in the following equation: a = !(!memw) # !(!memr) ; by entering: a = memw # memr ; The section of the file "Logic Equations" contains equations that describe the output signals of the PLD. These equations are written in terms of the intermediate equations that describe the outputs of the internal gates. For example, the AND gate, LS10, has !ROM_CS as its output signal, and the signals H, B and C as inputs. Therefore, enter the following equation to describe LS10: !rom_cs = !(h & b & c) ; WGTTL.PLD to WAITGEN.PLD are not exactly alike, because the internal gates have been defined differently. When compiled, however, they perform the same function. This can be verified by simulating each logic description in turn with an identical simulation source file (WGTTL.SI and WAITGEN.SI provided in the CUPL package). When converting a TTL design to a PLD, some slight changes in functionality are required. The asynchronous reset capability found on TTL flip-flops like the LS74 is not found in many of the commonly available PLDs. However, the same reset capability can be achieved by including a RESET variable in all product terms to ensure a synchronous reset at the clock. Therefore, WGTTL.PLD incorporates !RESET into the equation for G, which is used in the equations for both WAIT1 (wait1.d = g;) and WAIT2 (wait2.d = wait1.d & g). Although the functional nature of the synchronous reset does differ in timing from that of the asynchronous reset, the synchronous reset is sufficient for proper function of the device. The simple methodology described in Example 2 allows the conversion of many TTL designs, especially those consisting of simple gates, to a PLD equivalent, regardless of the number of gate delays of TTL (logic) in the original design. In most cases, the only difference between the TTL design and the PLD is the total propagation delay through the circuit. o .c3.EXAMPLE 3. TWO-BIT COUNTER This example demonstrates the implementation of a two-bit counter for a D-type flip-flop. Figure U5-24 shows the timing diagram for the counter. [Picture] Figure U5-24. Two-Bit Counter Timing Diagram As indicated by the arrows, the registers are clocked on the rising edge of the clock signal. Figure U5-25 shows the CUPL source file (FLOPS.PLD, provided in the CUPL package) to describe the two-bit counter design. ----------------------------------------------------------------- FLOPS.PLD Name Flops; Partno CA0002; Revision 02; Date 07/16/87; Designer G. Woolheiser; Company ATI; Location None; Assembly None; /************************************************************/ /* This example demonstrates the use of D-type flip-flop */ /* to implement a two bit counter using the following */ /* timing diagram. */ /* ___ ___ ___ ___ ___ */ /* clock |___| |___| |___| |___| |___| */ /* _____ _______ _______ */ /* q0 /// |_______| |_______| |__ */ /* _____ _______________ */ /* q1 /// |_______________| |__ */ /* */ /* _________ */ /* reset |___________________________________ */ /* */ /************************************************************/ /* Target Devices: PAL16R8, PAL16RP8, GAL16V8 */ /************************************************************/ Pin 1 = clock; Pin 2 = reset; /* Outputs: define outputs and output active levels */ Pin 17 = q0; Pin 16 = q1; /* Logic: two bit counter using expanded exclusive ors with d-type flip-flop */ qo.d = !reset & (!q0 & !q1 # !q0 & q1); q1.d = !reset & (!q0 & q1 # q0 & !q1); /* ANDed !reset defines a synchronous register reset */ ----------------------------------------------------------------- Figure U5-25. Two-Bit Counter Source File (FLOPS.PLD) The first part of the file provides archival information and a description of the intended function of the design, including compatible PLDs. Pin declarations are made corresponding to the inputs and outputs in the design diagram. In the "Logic" section of the file, equations are written to implement the counter. The equation for q0 is written to define when q0 asserts; that is, it defines the situation immediately before the rising clock edge. The !reset term is used in the equations for both q0 and q1 to initialize the circuit, providing a synchronous reset. At power-on, the registers can be either high or low, as indicated by the DON'T CARE slashes in the timing diagram (see Figure U5-24); the reset signal is initially asserted. By ANDing !reset into the equation for each variable, the conditions are not met at power-on, so the registers do not set. Because the reset signal returns LO (false) after the power-on process is complete, !reset is then true and does not affect the value of the registers at any other point in the circuit. The .d extension in the equations specifies a D-type flip-flop. However, when an output is used as feedback, the .d extension is dropped. For example, if q0 is fed back to q1, an equation could be written as: q1.d = q0 & !reset ; not as: q1.d = q0.d & !reset ; or: q1.d = q0.dq & !reset ; o .c3.EXAMPLE 4. DECADE UP/DOWN COUNTER This example describes a four-bit up/down decade counter with a synchronous clear capacity. The counter also provides an asynchronous ripple carry output for cascading multiple devices. The source file to implement the counter uses CUPL state machine syntax. Figure U5-26 shows the counter design and its state. [Picture] Figure U5-26. Up/Down Counter Diagram The input signal dir determines the direction of the count. When dir is high, the count goes down one on each clock; when dir is low, the count goes up one on each clock. The clr signal performs a synchronous reset. Figure U5-27 shows the CUPL source file (COUNT10.PLD, provided in the CUPL package) that implements the design. ----------------------------------------------------------------- COUNT10.PLD Name Count10; Partno CA0018; Revision 02; Date 07/16/87; Designer Kahl; Company ATI; Location None; Assembly None; Device p16rp4; /***********************************************************/ /* */ /* Decade Counter */ /* This is a 4-bit up/down decade counter with */ /* synchronous clear capability. An asynchronous */ /* ripple carry output is provided for cascading */ /* multiple devices. CUPL state machine syntax */ /* is used */ /***********************************************************/ /* Allowable Target Device Types: PAL16RP4, GAL16V8, EP300 */ /************************************************************/ /** Inputs **/ Pin 1 = clk; /* counter clock */ Pin 2 = clr; /* counter clear input */ Pin 3 = dir; /* counter direction input */ Pin 11 = !oe; /* Register output enable */ /* Outputs */ Pin [14..17] = [Q3..0]; /* counter outputs */ Pin 18 = carry; /* ripple carry out */ /* Declarations and Intermediate Variable Definitions */ field count = [Q3..0]; /* declare counter bit field */ $define S0 'b'0000 $define S1 'b'0001 $define S2 'b'0010 $define S3 'b'0011 $define S4 'b'0100 $define S5 'b'0101 $define S6 'b'0110 $define S7 'b'0111 $define S8 'b'1000 $define S9 'b'1001 field node = [clr,dir]; /* declare filed node control */ up = mode:0; /* define count up mode */ down = mode:1; /* define count down mode */ clear = mode:2..3]; /* define count clear mode */ ----------------------------------------------------------------- Figure U5-27. Up/Down Counter Source File (COUNT10.PLD) Sheet 1 of 2 ----------------------------------------------------------------- /* Logic Equations */ sequence count { /* free running counter */ present S0 if up next S1; if down next S9; if clear next S0; present S1 if up next S2; if down next S0; if clear next S0; present S2 if up next S3; if down next S1; if clear next S0; present S3 if up next S4; if down next S2; if clear next S0; present S4 if up next S5; if down next S3; if clear next S0; present S5 if up next S6; if down next S4; if clear next S0; present S6 if up next S7; if down next S5; if clear next S0; present S7 if up next S8; if down next S6; if clear next S0; present S8 if up next S9; if down next S7; if clear next S0; present S9 if up next S0; if down next S8; if clear next S0; out carry; /* assert carry output */ ----------------------------------------------------------------- Figure U5-27. Sheet 2 of 2 The first part of the file provides archival information and a description of the intended function of the design, including compatible PLDs. Pin declarations are made corresponding to the inputs and outputs in the design diagram. The "Declarations and Intermediate Variable Definitions" section contains declarations that simplify the notation. The name "count" is assigned to the output variables Q3, Q2, Q1, and Q0. The $DEFINE command is used to assign names to ten binary states representing the state machine output. The state name can then be used in the logic equations to represent the corresponding binary number. The FIELD keyword is used to combine the clr and dir inputs into a set called mode. Mode is defined by the following equations: up = mode:0; down = mode:1; clear = mode[2..3]; Mode represents the inputs clr and dir, so the three equations above are equivalent to the following equations: up = !clr & !dir ; down = !clr & dir ; clear = (clr & !dir) # (clr & dir) ; The three modes are defined as follows: up - Both the dir and clr inputs are not asserted. down - The dir input is asserted and clr is not asserted. clear - The clr input is asserted and dir is either asserted or not asserted. The "Logic Equations" section contains the state machine syntax that specifies the states in the counter. In the first line, the SEQUENCE keyword identifies count (that is, Q3, Q2, Q1, and Q0) as the outputs to which the state values apply. Conditional statements have been written to specify the transition from each possible present state to a next state, for each of the three modes. For example, when the present state is S4, if the mode is up, the counter goes to S5; if the mode is down the counter goes to S3; or if the mode is clear, the counter goes to S0. As example 4 shows, one advantage of the state machine syntax is that it clearly documents the operation of the design. In Example 4, state 0 (binary value 0000) is defined, because it is the result of the clr signal. It is recommended that all designs have a valid 0000 defined to avoid being stuck at state 0. For example, in this design, if a state that hasn't been defined occurs at power-on, such as hexadecimal A-F, none of the conditions described in the equations is met, so the state goes to state 0 (hex value 0000). If 0000 has not been defined as a valid state, the counter stays at state 0. Figure U5-28 shows how this example could have been written as a virtual design. It is the same file, but it has been modified where necessary to show the difference between a virtual design and a device specific design. ----------------------------------------------------------------- COUNT10.PLD Name Count10; Partno CA0018; Revision 02; Date 07/16/87; Designer Kahl; Company ATI; Location None; Assembly None; Device VIRTUAL; /***********************************************************/ /* */ /* Decade Counter */ /* This is a 4-bit up/down decade counter with */ /* synchronous clear capability. An asynchronous */ /* ripple carry output is provided for cascading */ /* multiple devices. CUPL state machine syntax */ /* is used */ /***********************************************************/ /* Allowable Target Device Types: PAL16RP4, GAL16V8, EP300 */ /************************************************************/ /** Inputs **/ Pin = clk; /* counter clock */ Pin = clr; /* counter clear input */ Pin = dir; /* counter direction input */ Pin = !oe; /* Register output enable */ /* Outputs */ Pin = [Q3..0]; /* counter outputs */ Pin = carry; /* ripple carry out */ /* Declarations and Intermediate Variable Definitions */ field count = [Q3..0]; /* declare counter bit field */ $define S0 'b'0000 $define S1 'b'0001 $define S2 'b'0010 $define S3 'b'0011 $define S4 'b'0100 $define S5 'b'0101 $define S6 'b'0110 $define S7 'b'0111 $define S8 'b'1000 $define S9 'b'1001 field node = [clr,dir]; /* declare filed node control */ up = mode:0; /* define count up mode */ down = mode:1; /* define count down mode */ clear = mode:2..3]; /* define count clear mode */ ----------------------------------------------------------------- Figure U5-28. Up/Down Counter Source File (virtual) Sheet 1 of 2 ----------------------------------------------------------------- /* Logic Equations */ sequence count { /* free running counter */ present S0 if up next S1; if down next S9; if clear next S0; present S1 if up next S2; if down next S0; if clear next S0; present S2 if up next S3; if down next S1; if clear next S0; present S3 if up next S4; if down next S2; if clear next S0; present S4 if up next S5; if down next S3; if clear next S0; present S5 if up next S6; if down next S4; if clear next S0; present S6 if up next S7; if down next S5; if clear next S0; present S7 if up next S8; if down next S6; if clear next S0; present S8 if up next S9; if down next S7; if clear next S0; present S9 if up next S0; if down next S8; if clear next S0; out carry; /* assert carry output */ ----------------------------------------------------------------- Figure U5-28. Sheet 2 of 2 It is possible to use some of the features of the CUPL preprocessor to considerably shorten this PLD file. Figure U5-29 will show how this same file could be written with a .i.repeat;$REPEAT structure which reduces the file size considerably. ----------------------------------------------------------------- Name Count10; Partno CA0018; Revision 02; Date 07/16/87; Designer Kahl; Company ATI; Location None; Assembly None; Device VIRTUAL; /**********************************************************/ /* */ /* Decade Counter */ /* This is a 4-bit up/down decade counter with */ /* synchronous clear capability. An asynchronous */ /* ripple carry output is provided for cascading */ /* multiple devices. CUPL state machine syntax */ /* is used */ /***********************************************************/ /* Allowable Target Device Types: PAL16RP4, GAL16V8, EP300 */ /***********************************************************/ /** Inputs **/ Pin = clk; /* counter clock */ Pin = clr; /* counter clear input */ Pin = dir; /* counter direction input */ Pin = !oe; /* Register output enable */ /* Outputs */ Pin = [Q3..0]; /* counter outputs */ Pin = carry; /* ripple carry out */ /* Declarations and Intermediate Variable Definitions */ field count = [Q3..0]; /* declare counter bit field */ field node = [clr,dir]; /* declare filed node control */ up = mode:0; /* define count up mode */ down = mode:1; /* define count down mode */ clear = mode:2..3]; /* define count clear mode */ /* state machine description */ sequence count { present 0 if up & !clear next 1; if down & !clear next 9; if clear next 0; $REPEAT i=[1..9] present {i} if up & !clear next {(i+1)%10}; if down & !clear next {(i-1)%10}; if clear next 0; $REPEND ----------------------------------------------------------------- Figure U5-29. Up/Down Counter Source File (virtual) Sheet 1 of 2 In this variation, we removed the $DEFINE statements because we use the raw numbers instead. The most significant change is that we used a $REPEAT loop to define most of the states instead of defining each state individually. It is possible to do this because all the states are identical in the sense that all the next states can be calculated from the present state. State 0 is done separately because when counting down the next state is -1 modulo 10 which cannot be handled by the compiler. We, therefore, define state 0 by itself and then all the other states are defined in one $REPEAT loop. The $REPEAT loop expands upon compilation to give a definition for each state. Notice that the statement indicating the next state is given as a calculation from the repeat variable 'i'. In the loop, 'i' represents the number of the current state. The next state is therefore 'i+1'. This will work for all states except the last state. In the last state, the state machine must go back to state 0. To accomplish this, the formula to calculate the next state is given as '(i+1)%10'. This means 'i+1' `modulo 10. The number 10 represents the number of states. Therefore, when in state 9 the next state is calculated as 9+1 = 10 then modulo 10 which gives 0. A similar condition occurs in calculating the previous state except that we subtract 1 instead of adding it. You might have noticed that we defined state 0 separately. This was done because the $REPEAT variables can only handle positive numbers. If we had defined state 0 in the $REPEAT loop this would result in evaluating to next state -1 and the compiler would produce an unexpected result. o .c3.EXAMPLE 5. SEVEN-SEGMENT DISPLAY DECODER This example shows a hexadecimal-to-seven-segme nt decoder for driving common-anode LEDs. The design incorporates both a ripple-blanking input to inhibit the display of leading zeroes, and a ripple-blanking output for easy cascading of digits Figure U5-30 shows the segment display decoder. [Picture] Figure U5-30. Seven-Segment Display Decoder The segments in the display, labeled a-g, correspond to the outputs in the diagram. Figure U5-31 shows the source file (HEXDISP.PLD, provided with the CUPL package). ----------------------------------------------------------------- HEXDISP.PLD Name Hexdisp; Partno CA0007; Revision 02; Date 07/16/87; Designer T. Kahl; Company ATI; Location None; Assembly None; /******************************************************************/ /* */ /* a */ /* This is a hexadecimal-to-seven-segment ----- */ /* decoder capable of driving common-anode | | */ /* LEDs. It incorporates both a ripple- f| |b */ /* blanking input (to inhibit displaying | g | */ /* leading zeroes) and a ripple blanking output ----- */ /* to allow for easy cascading of digits | | */ /* e| |c */ /* | | */ /* ----- */ /* d */ /* */ /******************************************************************/ /* Allowable Target Device Types: 32 x 8 PROM (82S123 or */ /* equivalent */ /******************************************************************/ /** Input group (Note this is only a comment) **/ pin [10..13] = [D0..3]; /* data input lines to display */ pin 14 = !rbi; /* ripple blanking input */ /** Output Group ( Note this is only a comment ) **/ pin [7..1] = ![a,b,c,d,e,f,g]; /* Segment output lines */ pin 9 = !rbo; /* Ripple Blanking output */ /** Declarations and Intermedia te Variable Definitions */ field data = [D3..0]; /* hexadecimal input field */ field segment=[abcdefg]; /* Display segment field */ $define ON 'b'1 /* segment lit when logically"ON" */ $define OFF 'b'0 /* segment dark when logically "OFF" */ ----------------------------------------------------------------- Figure U5-31. Display Decoder Source File (HEXDISP.PLD) Sheet 1 of 2 The first part of the file provides archival information and a description of the intended function of the design, including compatible PLDs. Pin declarations are made corresponding to the inputs and outputs in the design diagram. In the "Declarations and Intermediate Variables" section, field assignments are made to group the input pins into a set named data and the output pins into a set named segment. ON and OFF are defined respectively as binary 1 and binary 0. ----------------------------------------------------------------- /** Logic Equations **/ /* a b c d e f g */ segment = /* 0 */ [ ON, ON, ON, ON, ON, ON, OFF] & data:0 & !rbi /* 1 */ # [OFF, ON, ON, OFF, OFF, OFF, OFF] & data:1 /* 2 */ # [ ON, ON, OFF, ON, ON, OFF, ON] & data:2 /* 3 */ # [ ON, ON, ON, ON, OFF, OFF, ON] & data:3 /* 4 */ # [OFF, ON, ON, OFF, OFF, ON, ON] & data:4 /* 5 */ # [ ON, OFF, ON, ON, OFF, ON, ON] & data:5 /* 6 */ # [ ON, OFF, ON, ON, ON, ON, ON] & data:6 /* 7 */ # [ ON, ON, ON, OFF, OFF, OFF, ON] & data:7 /* 8 */ # [ ON, ON, ON, ON, ON, ON, OFF] & data:8 /* 9 */ # [ ON, ON, ON, ON, OFF, ON, ON] & data:9 /* A */ # [ ON, ON, ON, OFF, ON, ON, ON] & data:A /* B */ # [OFF, OFF, ON, ON, ON, ON, ON] & data:B /* C */ # [ ON, OFF, OFF, ON, ON, ON, OFF] & data:C /* D */ # [OFF, ON, ON, ON, ON, OFF, ON] & data:D /* E */ # [ ON, OFF, OFF, ON, ON, ON, ON] & data:E /* F */ # [ ON, OFF, OFF, OFF, ON, ON, ON] & data:F; rbo = rbi & data:0; ----------------------------------------------------------------- Figure U5-31. Sheet 2 of 2 The logic equations are set up as a function table to describe the segments that are lit up by each input pattern. Comments create a header for the function table, listing the output segments across the top and the input numbers vertically down the side. Each line of the table describes a decoded hex value and the segments of the display that the hex value turns on or off. For example, the line for an input value of 4 is written as follows: [OFF, ON, ON, OFF, OFF, ON, ON] & data:4 The function table format expresses the intent of the design more clearly than equations; that is, the example above shows that an input value of 4 turns segment a off, segment b on, segment c on, and so on. o .c3.EXAMPLE 6. 4-BIT COUNTER WITH LOAD AND RESET This example will present a counter that can be loaded and reset. The design is done using the VIRTUAL device but it could easily be implemented in almost any PLD that has four or more registers. ----------------------------------------------------------------- Name Counter; Partno FL1201; Revision 01; Date 08/26/91; Designer RGT; Company LDI; Location None; Assembly None; Device VIRTUAL; /*******************************************/ /* 4-bit counter */ /*******************************************/ /** inputs **/ PIN = clk; /* clock signal for registers */ PIN = load;/* load signal */ PIN = !ClrFlag; PIN = [LoadPin0..3]; /* pins from which to load data */ /** outputs **/ PIN = [CountPin0..3];/* intermediate variables and fields */ field STATE_BITS = [Count0..3]; field LOAD_BUS = [LoadPin0..3];/** state machine definition **/ SequenceD STATE_BITS { /* build a repeated loop for the states */ $REPEAT i = [0..15] Present 'h'{i} /* go to state 0 if clear signal is true */ /* if the load signal is false go to the * * next state. Note that the next state * * is (current state + 1) modulo 16. * * This causes the counter to wrap back * * to 0 when in the last state */ If !load Next 'h'{(i+1)%16}; $REPEND /* Add the load capability by using the * * APPEND statement. This has the effect of * * adding more inputs to the OR gate for * * this output. This equation states that if * * the load signal is true then the counter * * registers are loaded with data from the * * load pins. This is why 'load' was used in * * the equations for the 'IF' statements in * * the state definitions. */ APPEND STATE_BITS.d = load & LOAD_BUS; ----------------------------------------------------------------- Figure U5-32. Counter With Reset and Load. Since this is a virtual design, pin numbering can be ignored. The signals to be used are declared without any pin numbers. When the load signal is asserted, the values at the load pins are fed into the state bit registers. When the 'Clear' signal is asserted, the state machine is forced to state 0. The $REPEAT loop is defined as [0 ..15]. Inside the loop, the present state is defined as 'h' {i}. This causes the numbers to be evaluated as hex numbers. The expansion that results from this is a state machine with 16 states ranging from 0 to F in hexadecimal. If the 'h' was left off, the states would have been expanded as 0 to 15 in decimal. The compiler would have interpreted these as hex anyway and states A-F would not have been defined. Additionally, State 10 in hex cannot exist with this number of statebits since that would require 5 statebits but all that we have is 4. Notice that all the IF statements are anded with "!load". This was done because we want to give loading the highest possible priority. Also this removes any possible conflict that could occur if load and some other signal were asserted at the same time. The next state is calculated as (present_state + 1) modulo 16. This causes the counter to wrap back to the zero state when it is in the last state. We use modulo 16 because this is the number of states in the state machine. The last part of this design involves adding the load capability to our design. For this we use the .i.append;APPEND statement. The append statement causes the expression given to be ORed to the variable specified. This entire state machine eventually becomes a set of equations for each of the state bits. Out intent is to add another condition where the registers are loaded with the value from a set of input pins. Remember that we used '!load' in all the IF statements. That was to make sure that the equations generated by those IF statements, would not conflict with the APPEND statement. CountPin0.d = !load & ???..... # !load & ???.....; Figure U5-33. Equations Before APPEND CountPin0.d = !load & ???..... # !load & ???..... # load & LoadPin0; Figure U5-34. Equations After APPEND As an exercise, try to add up/down capability to this example. Also, try implementing it into an actual device.