/*
 * This module makes a shifting pattern across the 7-segment displays and
 * LEDR lights.  Starting from HEX7, the pattern on the 7-segment displays traces 
 * through the digit 2, 5, 2, 5, 2, 5, 2, 5, repeat.
 *
 * inputs:
 * 	KEY0		reset
 * 	KEY1		x2 the speed of shifting
 * 	KEY2		/2 the speed of shifting
 * 	SW[0]		enables shifting to the right
 * 	SW[1]		enables shifting to the left; SW[0] overrides SW[1]
 * 	SW[2]		shifts additional 1's into the HEX displays
 * 	SW[3]		shifts additional 0's into the HEX displays
 *
 * outputs:
 * 	LEDR		shifting lights
 * 	HEX7-0	shifting pattern
 * 	LEDG		shifting speed (from 0 to 9)
*/
module seg_shift (	CLOCK_50, KEY, SW, HEX3, HEX2, HEX1,
					HEX0, LEDR, LEDG);
	
	/*****************************************************************************
 	*                  Module Parameters, Inputs and Outputs                     *
 	*****************************************************************************/
				
	parameter M = 23;

	input CLOCK_50;
	input [2:0] KEY;
	input [3:0] SW; 
	output [6:0] HEX3, HEX2, HEX1, HEX0;
	output [9:0] LEDR;
	output [0:7] LEDG;

 	/*****************************************************************************
 	*                               Local Wires                                  *
 	*****************************************************************************/

	reg [M-1:0] slow_count;	// counter variable
	wire [7:0] mask;	// used to mask upper counter bits
	wire z;				// used to enable shifting

	wire [9:0] LED_sr;	// shift register displayed on LEDs
	wire [19:0] HEX_sr;	// shift register displayed on 7-seg displays

	wire fast, slow;		// used to speed up and slow down shifting

	/*****************************************************************************
 	*                         Finite State Machine                              *
 	*****************************************************************************/
	// these FSMs are used to produce a one-clock-cycle pulse when a KEY is pressed
	pulse_FSM fast_FSM (CLOCK_50, KEY[0], ~KEY[1], fast); 
	pulse_FSM slow_FSM (CLOCK_50, KEY[0], ~KEY[2], slow); 
		
	// a large counter to produce an approx .25 second delay 
	always @(posedge CLOCK_50)
		slow_count <= slow_count + 1'b1;
	
	// Shift register to be used as a mask for upper counter bits.  Initialized to 
	// 10000000, which represents the second-slowest shifting speed.
	shift_rot_lr U_mask_sr(3'b100, ~KEY[0], (fast | slow), CLOCK_50, fast, slow, fast, 1'b0, mask);
		defparam U_mask_sr.M = 8;
	assign LEDG = mask;	// this assignment places mask[7:0] onto LEDG [0:7]
	
	// z is 1 when the counter hits 0. Upper counter bits may be masked
	assign z = ~|{(~mask & slow_count[M-1:M-8]),slow_count[M-9:0]};
	// shift register connected to red LEDs
	shift_rot_lr U_LED_sr(3'b100, ~KEY[0], z, CLOCK_50, SW[0], SW[1], SW[2], ~(SW[2] | SW[3]), LEDR);
	// shift register connected to 7-seg displays. Initialized to display 3-segment pattern
	shift_rot_lr U_HEX_sr(3'b111, ~KEY[0], z, CLOCK_50, SW[0], SW[1], SW[2], ~(SW[2] | SW[3]), HEX_sr);
		defparam U_HEX_sr.M = 20;

	hex_pattern h3 (HEX_sr[19:15], HEX3);
		defparam h3.PATTERN = 0;
	hex_pattern h2 (HEX_sr[14:10], HEX2);
		defparam h2.PATTERN = 1;
	hex_pattern h1 (HEX_sr[9:5], HEX1);
		defparam h1.PATTERN = 0;
	hex_pattern h0 (HEX_sr[4:0], HEX0);
		defparam h0.PATTERN = 1;
endmodule


