module allofit (clock, btn1, btn3, btn4, ledout, ledenable, count) ;

input clock,btn1,btn3,btn4;
output [15:0] count;
output [2:0] ledout;
output ledenable;

reg [2:0] original;
reg [2:0] current;
reg on;

// continuously check for a match!
wire match = (original == current) && on;

//internal control singals
wire restart,measuring,rolling,pause; 

// random number generator
reg [15:0] X;
always @(posedge clock) begin
	if (btn3) X <= 0;
	else X <= {X[14:0],(X[10]^X[8]^X[6])};
end

// timer/counter
// counts up for timer purposes
// counts down for delay purposes, reloads when zero (timesUp)
reg [15:0] count;
wire [15:0] reload;
wire timesUp = (count == 0) && rolling;
always @(posedge clock) begin
	if (!(measuring | rolling)) count <= 0; // serves as a reset
	else if (measuring) count <= count + 1;  // ignoring overflow
	else begin // must be rolling
	     if (timesUp) count <= reload; 
	     else if (!pause) count <= count - 1;
	end
end

// reload random if currently on, one sec if currently off
assign reload = (on|restart) ? X : `ONE_SECOND; 
// random light/delay process
always @(posedge clock) begin
	if (restart | !(measuring | rolling)) on <= 0;
	else if (timesUp) begin 
		if (!on) current <= X[2:0]; // load a random value
		on <= ~on; 
	end
end

// LED output control
reg [2:0] ledout;
assign ledenable = pause | on;
always @(posedge clock) begin
	if (pause) ledout <= original;
	else if (on) ledout <= current;
end

// master controller
`define LOSE 0
`define WIN 1
`define ROLL 2
`define PAUSE 3
`define MEASURE 4
reg [2:0] state;
always @(posedge clock) begin
  // reset w/ btn3
  if (btn3) state <= `LOSE;
  // LOSE state transitions
  if ((state == `LOSE) && btn4) state <= `ROLL;
  // ROLL state transitions
  if ((state == `ROLL) && btn1) state <= `LOSE;
  else if ((state == `ROLL) && match) state <= `MEASURE;
  else if ((state == `ROLL) && btn4) state <= `PAUSE;
  // PAUSE state transitions
  if ((state == `PAUSE) && !btn4) state <= `ROLL;
  // MEASURE state transitions
  if ((state == `MEASURE) && btn1) state <= `WIN;
  // WIN transitions
  if ((state == `WIN) && btn4) state <= `ROLL;
end

//  outputs  (Moore and Mealy)
assign restart = (state == `WIN || state == `LOSE) && btn4;
assign rolling = restart || ((state == `ROLL) && !btn1);
assign measuring = state == `MEASURE;
assign pause = (state == `PAUSE);

endmodule