Untitled
unknown
verilog
2 years ago
3.3 kB
13
Indexable
`timescale 1ps/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 = 2'b00;
parameter Escape = 2'b01;
parameter Shining = 2'b10;
wire clk_used, clk_div_24, clk_div_26;
reg [3:0] cnt, nxt_cnt;
reg [2:0] state, nxt_state;
reg [15:0] nxt_led;
reg [3:0] reg_tmp;
//directly use two clock in our mudule
clock_divider #(24) div1(.clk(clk), .clk_div(clk_div_24));
clock_divider #(26) div2(.clk(clk), .clk_div(clk_div_26));
//change speed by switch
assign clk_used = (!speed) ? clk_div_26 : clk_div_24;
// Use a counter to deal with the light;
always @(posedge clk_used, posedge rst) begin
if(rst) cnt <= 0;
else if(en) cnt <= nxt_cnt;
else cnt <= cnt;
end
always @(*) begin
if(nxt_state != state) nxt_cnt = 0;
else nxt_cnt = cnt + 1;
end
// State transition
always @(posedge clk_used, posedge rst) begin
if(rst) state <= Regular;
else state <= nxt_state;
end
always @(*) begin
case (state)
Regular: begin
if(cnt == 4'b1110) nxt_state = Escape;
else nxt_state = Regular;
end
Escape: begin
if(led == 16'b0000000000000000 && dir == 0) nxt_state = Shining;
else if(led == 16'b1111111111111111 && dir == 1) nxt_state = Regular;
else nxt_state = Escape;
end
Shining: begin
if(cnt == 4'b1001) nxt_state = Regular;
else nxt_state = Shining;
end
default: nxt_state = state;
endcase
end
// Deal with the output
always @(posedge clk_used, posedge rst) begin
if(rst) begin
led <= 16'b0000000000000000;
end
else if(en) begin
if(state == Regular) begin
reg_tmp = cnt % 5;
case(reg_tmp)
4'b0000: led <= 16'b0000000000000000;
4'b0001: led <= 16'b1000100010001000;
4'b0010: led <= 16'b1100110011001100;
4'b0011: led <= 16'b1110111011101110;
4'b0100: led <= 16'b1111111111111111;
default: led <= 16'b1111111111111111;
endcase
end
else led <= nxt_led;
end
else led <= led;
end
reg [15:0] led_tmp;
always @(*) begin
case(state)
Escape: begin
if(dir == 0) begin
nxt_led = led >> 2;
end
else begin
led_tmp = led;
nxt_led = (led << 2) | led_tmp;
end
end
Shining: begin
if(led == 16'b1111111111111111) nxt_led = 16'b0000000000000000;
else nxt_led = 16'b1111111111111111;
end
default: nxt_led = led;
endcase
end
endmoduleEditor is loading...