209 lines
5.1 KiB
Verilog
209 lines
5.1 KiB
Verilog
module Simon_Game (
|
|
input i_Clk,
|
|
|
|
input i_Switch_1,
|
|
input i_Switch_2,
|
|
input i_Switch_3,
|
|
input i_Switch_4,
|
|
|
|
output reg [3:0] o_Score,
|
|
|
|
output o_LED_1,
|
|
output o_LED_2,
|
|
output o_LED_3,
|
|
output o_LED_4
|
|
);
|
|
parameter CLKS_PER_SECOND = 25000000;
|
|
parameter GAME_LIMIT = 6;
|
|
|
|
localparam START = 3'd0;
|
|
localparam PATTERN_OFF = 3'd1;
|
|
localparam PATTERN_SHOW = 3'd2;
|
|
localparam WAIT_PLAYER = 3'd3;
|
|
localparam INCREMENT_SCORE = 3'd4;
|
|
localparam PLAYER_LOST = 3'd5;
|
|
localparam PLAYER_WON = 3'd6;
|
|
|
|
reg [2:0] r_currentState;
|
|
|
|
// count and toggle results
|
|
wire w_IncomingDelay;
|
|
reg r_DelayCompleted;
|
|
wire w_EnableCounter;
|
|
|
|
// user input handling
|
|
reg r_Switch_1, r_Switch_2, r_Switch_3, r_Switch_4;
|
|
reg r_Button_notDown;
|
|
reg [1:0] r_currentButtonDown;
|
|
|
|
// game pattern & construction
|
|
reg [1:0] r_LEDPattern [0:10];
|
|
wire [21:0] w_LFSR_Data;
|
|
reg [$clog2(GAME_LIMIT)-1:0] r_currentLEDPattern;
|
|
|
|
always @(posedge i_Clk) begin
|
|
if (i_Switch_1 & i_Switch_2) begin
|
|
r_currentState <= START;
|
|
end else begin
|
|
case (r_currentState)
|
|
START:
|
|
begin
|
|
if (!i_Switch_1 & !i_Switch_2 & r_Button_notDown) begin
|
|
o_Score <= 0;
|
|
r_currentLEDPattern <= 0;
|
|
r_currentState <= PATTERN_OFF;
|
|
end
|
|
end
|
|
|
|
PATTERN_OFF:
|
|
begin
|
|
if (!w_IncomingDelay & r_DelayCompleted) begin
|
|
r_currentState <= PATTERN_SHOW;
|
|
end
|
|
end
|
|
|
|
PATTERN_SHOW:
|
|
begin
|
|
if (!w_IncomingDelay & r_DelayCompleted) begin
|
|
// this limits the number of
|
|
if (o_Score == r_currentLEDPattern) begin
|
|
r_currentLEDPattern <= 0;
|
|
r_currentState <= WAIT_PLAYER;
|
|
end else begin
|
|
r_currentLEDPattern <= r_currentLEDPattern + 1;
|
|
r_currentState <= PATTERN_OFF;
|
|
end
|
|
end
|
|
end
|
|
|
|
WAIT_PLAYER:
|
|
begin
|
|
if (r_Button_notDown) begin
|
|
if (
|
|
r_LEDPattern[r_currentLEDPattern] == r_currentButtonDown &&
|
|
o_Score == r_currentLEDPattern
|
|
) begin
|
|
r_currentLEDPattern <= 0;
|
|
r_currentState <= INCREMENT_SCORE;
|
|
end else if (
|
|
r_LEDPattern[r_currentLEDPattern] != r_currentButtonDown
|
|
) begin
|
|
r_currentState <= PLAYER_LOST;
|
|
end else begin
|
|
r_currentLEDPattern <= r_currentLEDPattern + 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
INCREMENT_SCORE:
|
|
begin
|
|
o_Score <= o_Score + 1;
|
|
if (o_Score == GAME_LIMIT - 1) begin
|
|
r_currentState <= PLAYER_WON;
|
|
end else begin
|
|
r_currentState <= PATTERN_OFF;
|
|
end
|
|
end
|
|
|
|
PLAYER_WON:
|
|
begin
|
|
o_Score <= 4'hA;
|
|
end
|
|
|
|
PLAYER_LOST:
|
|
begin
|
|
o_Score <= 4'hF;
|
|
end
|
|
|
|
default:
|
|
begin
|
|
r_currentState <= START;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
always @(posedge i_Clk) begin
|
|
if (r_currentState == START) begin
|
|
r_LEDPattern[0] <= w_LFSR_Data[1:0];
|
|
r_LEDPattern[1] <= w_LFSR_Data[3:2];
|
|
r_LEDPattern[2] <= w_LFSR_Data[5:4];
|
|
r_LEDPattern[3] <= w_LFSR_Data[7:6];
|
|
r_LEDPattern[4] <= w_LFSR_Data[9:8];
|
|
r_LEDPattern[5] <= w_LFSR_Data[11:10];
|
|
r_LEDPattern[6] <= w_LFSR_Data[13:12];
|
|
r_LEDPattern[7] <= w_LFSR_Data[15:14];
|
|
r_LEDPattern[8] <= w_LFSR_Data[17:16];
|
|
r_LEDPattern[9] <= w_LFSR_Data[19:18];
|
|
r_LEDPattern[10] <= w_LFSR_Data[21:20];
|
|
end
|
|
end
|
|
|
|
assign o_LED_1 = (
|
|
(r_currentState == PATTERN_SHOW && r_LEDPattern[r_currentLEDPattern] == 0) ?
|
|
1 :
|
|
i_Switch_1
|
|
);
|
|
|
|
assign o_LED_2 = (
|
|
(r_currentState == PATTERN_SHOW && r_LEDPattern[r_currentLEDPattern] == 1) ?
|
|
1 :
|
|
i_Switch_2
|
|
);
|
|
|
|
assign o_LED_3 = (
|
|
(r_currentState == PATTERN_SHOW && r_LEDPattern[r_currentLEDPattern] == 2) ?
|
|
1 :
|
|
i_Switch_3
|
|
);
|
|
|
|
assign o_LED_4 = (
|
|
(r_currentState == PATTERN_SHOW && r_LEDPattern[r_currentLEDPattern] == 3) ?
|
|
1 :
|
|
i_Switch_4
|
|
);
|
|
|
|
always @(posedge i_Clk) begin
|
|
r_DelayCompleted <= w_IncomingDelay;
|
|
r_Switch_1 <= i_Switch_1;
|
|
r_Switch_2 <= i_Switch_2;
|
|
r_Switch_3 <= i_Switch_3;
|
|
r_Switch_4 <= i_Switch_4;
|
|
|
|
if (r_Switch_1 && !i_Switch_1) begin
|
|
r_Button_notDown <= 1;
|
|
r_currentButtonDown <= 0;
|
|
end else if (r_Switch_2 && !i_Switch_2) begin
|
|
r_Button_notDown <= 1;
|
|
r_currentButtonDown <= 1;
|
|
end else if (r_Switch_3 && !i_Switch_3) begin
|
|
r_Button_notDown <= 1;
|
|
r_currentButtonDown <= 2;
|
|
end else if (r_Switch_4 && !i_Switch_4) begin
|
|
r_Button_notDown <= 1;
|
|
r_currentButtonDown <= 3;
|
|
end else begin
|
|
r_Button_notDown <= 0;
|
|
r_currentButtonDown <= 0;
|
|
end
|
|
end
|
|
|
|
assign w_EnableCounter = (r_currentState == PATTERN_SHOW || r_currentState == PATTERN_OFF);
|
|
|
|
Count_And_Toggle #(
|
|
.COUNT_LIMIT(CLKS_PER_SECOND/4)
|
|
) Counter (
|
|
.i_Clk(i_Clk),
|
|
.i_Enable(w_EnableCounter),
|
|
.o_Toggle(w_IncomingDelay)
|
|
);
|
|
|
|
LFSR #(
|
|
.SIZE(22)
|
|
) MyLFSR (
|
|
.i_Clk(i_Clk),
|
|
.o_LFSR_Data(w_LFSR_Data),
|
|
.o_LFSR_Done()
|
|
);
|
|
endmodule
|