/*
*
*	University of Oregon PHYS 432 - Lab 5 PAL Example
*	This example shows how CUPL can be used to create
*       non-trivial decoders and other combinatoric logic.
*
*	This program implements a state machine to provide
*       an internal 3-bit counter to drive an LED bar display.
*
*/

Name            ledcnt2;
Partno          PHYS432;
Revision        01;
Date            20/03/2006;
Designer        E. Torrence;
Company         University of Oregon;
Location        None;
Assembly        None;
Device          g16v8;

/** Inputs **/

pin  1 = clk;			/* Counter clock */

/** Outputs **/

/* We're driving LEDs and need a low voltage to make them light up.
   So make all the outputs active low */
pin [16..19] = ![led0..3];	/* Output LED lines */

/* Also output the register bits (counter value) */
pin [12..15] = [q0..3];

/* Declarations and Intermediate Variable Definitions */

/* Note I have defined these MSB -> LSB */
field output = [led3,led2,led1,led0];	/* Shorthand for output lines */

/* Define the state machine values */
field counter = [q3..0];	/* Define "count" as the three counter bits */
$define s0 'b'0000		/* Define the values of the counter bits in */
$define s1 'b'0001		/* each of the eight counter states */
$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
$define s10 'b'1010
$define s11 'b'1011
$define s12 'b'1100
$define s13 'b'1101
$define s14 'b'1110
$define s15 'b'1111

/** Logic Equations **/

/* 3-bit counter */

/* We don't need to define a clock since all the registers in the g16v8 are
   permanently connected to pin one where we will put in our clock */

sequence counter {		/* Describe the action of the state machine */
  present s0 next s1;
  present s1 next s2;
  present s2 next s3;
  present s3 next s4;
  present s4 next s5;
  present s5 next s6;
  present s6 next s7;
  present s7 next s8;
  present s8 next s9;
  present s9 next s10;
  present s10 next s11;
  present s11 next s12;
  present s12 next s13;
  present s13 next s14;
  present s14 next s15;
  present s15 next s0;
}

/* Define the decoder operations by anding specific count patterns
* with the desired output pattern.  By ORing together all possibilities,
* we get the correct output code depending upon the input received.
*/

$define on  'b'1
$define off 'b'0

output = 
	[ off, off, off, off ] & counter:0 #
	[ off, off, off,  on ] & counter:1 #
	[ off, off,  on,  on ] & counter:2 #
	[ off,  on,  on,  on ] & counter:3 #
	[  on,  on,  on,  on ] & counter:4 #
	[ off,  on,  on,  on ] & counter:5 #
	[ off, off,  on,  on ] & counter:6 #
	[ off, off, off,  on ] & counter:7 #
	[ off, off, off, off ] & counter:8 #
	[  on, off, off, off ] & counter:9 #
	[  on,  on, off, off ] & counter:A #
	[  on,  on,  on, off ] & counter:B #
	[  on,  on,  on,  on ] & counter:C #
	[  on,  on,  on, off ] & counter:D #
	[  on,  on, off, off ] & counter:E #
	[  on, off, off, off ] & counter:F;