`timescale 1ns / 1ps
module clock_divider
#(parameter n = 25)(
input clk,
output clk_div
);
reg[n-1:0]num;
wire[n-1:0]next_num;
always@(posedge clk)begin
num <= next_num;
end
assign next_num = num + 1;
assign clk_div = num[n-1];
endmodule
module lab3_2(
input clk,
input rst,
input en,
input speed,
input dir,
output reg [15:0] led
);
parameter REGULAR_MODE = 0;
parameter ESCAPE_MODE = 1;
parameter SHINING_MODE = 2;
wire clk_div0, clk_div1, clk_div25, clk_div27;
reg [3:0] cnt;
reg [3:0] next_cnt;
reg [1:0] mode;
reg [1:0] next_mode;
reg [3:0] round;
clock_divider #(25) div1(.clk(clk), .clk_div(clk_div25));
clock_divider #(27) div2(.clk(clk), .clk_div(clk_div27));
assign clk_div0 = (speed)? clk_div25 : clk_div27;
//change speed by switch
// led display according to mode
always @(posedge clk_div0 or posedge rst) begin
if(rst) begin
led <= 0;
end
else begin
if (en) begin
if(mode == REGULAR_MODE) begin
case (cnt)
4'b0000: led <= 16'b0000000000000000;
4'b0001: led <= 16'b1000100010001000;
4'b0010: led <= 16'b1110111011101110;
4'b0011: led <= 16'b1111111111111111;
default: led <= 16'b0000000000000000;
endcase
end
else if(mode == ESCAPE_MODE) begin
case (cnt)
4'b0000: led <= 16'b1111111111111111;
4'b0001: led <= 16'b0011111111111111;
4'b0010: led <= 16'b0000111111111111;
4'b0011: led <= 16'b0000001111111111;
4'b0100: led <= 16'b0000000011111111;
4'b0101: led <= 16'b0000000000111111;
4'b0110: led <= 16'b0000000000001111;
4'b0111: led <= 16'b0000000000000011;
4'b1000: led <= 16'b0000000000000000;
default: led <= 16'b0000000000000000;
endcase
end
else begin
case (cnt)
4'b0000: led <= 16'b1111111111111111;
4'b0001: led <= 16'b0000000000000000;
default: led <= 16'b0000000000000000;
endcase
end
end
else
led <= led;
end
end
// update current cnt and mode
always @(posedge clk_div0 or posedge rst) begin
if(rst) begin
cnt <= 0;
mode <= 0;
end
else begin
cnt <= next_cnt;
mode <= next_mode;
end
end
// update the value of next_cnt and round
always @(*) begin
case(mode)
REGULAR_MODE: begin
if(cnt == 4'b0101) begin
next_cnt = 0;
round = round + 1;
end
else
next_cnt = cnt + 1;
end
ESCAPE_MODE: begin
if(cnt == 4'b1000 && dir == 1) begin
next_cnt = 0;
round = round + 1;
end
else if(cnt == 4'b000 && dir == 0) begin
next_cnt = 4'b1000;
round = round + 1;
end
else
next_cnt = cnt + 1;
end
SHINING_MODE: begin
if(cnt == 4'b0010) begin
next_cnt = 0;
round = round + 1;
end
else
next_cnt = cnt + 1;
end
endcase
end
// mode transtion
always @(*) begin
case(mode)
REGULAR_MODE: begin
if(round == 2)
next_mode = ESCAPE_MODE;
else
next_mode = REGULAR_MODE;
end
ESCAPE_MODE: begin
if(round == 3 && dir == 1)
next_mode = SHINING_MODE;
else if(round == 3 && dir == 0)
next_mode = REGULAR_MODE;
else
next_mode = ESCAPE_MODE;
end
SHINING_MODE: begin
if(round == 8)
next_mode = REGULAR_MODE;
else
next_mode = SHINING_MODE;
end
endcase
end
endmodule