Untitled

mail@pastecode.io avatar
unknown
verilog
7 months ago
5.1 kB
3
Indexable
Never
`timescale 1ns / 1ps
module clock_divider(clk,clk_div);
    input clk;
    output clk_div;
    parameter n = 25;
    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
);
// add your design here
wire clk_div,clk_div24,clk_div26;
reg [1:0] state,next_state; 
reg [1:0] regular_repeat,next_regular_repeat;
reg[2:0]shining_repeat,next_shining_repeat;
reg [15:0] next_led;
reg change_state;

parameter regular_mode = 2'b00;
parameter esscape_mode_down = 2'b01;
parameter esscape_mode_up = 2'b10;
parameter shining_mode = 2'b11;

clock_divider #(24) div1(.clk(clk), .clk_div(clk_div24));
clock_divider #(26) div2(.clk(clk), .clk_div(clk_div26));

assign clk_div = (speed)?clk_div24 : clk_div26;

always@(posedge clk_div , posedge rst ,posedge change_state)begin
    if(rst)begin
        state <= regular_mode;
    end
    else if (change_state)begin
        state <= next_state;
        change_state <= 0;
    end
    else begin
        state <= next_state;
    end
end

always@(*)begin
    if(!en)
        next_state <= state;
    else if(state == regular_mode & regular_repeat == 2'b11 & dir == 0 & led == 16'b1111111111111111)begin
        next_state <= esscape_mode_down;
    end
    else if(state == regular_mode & regular_repeat == 2'b11 & dir == 1 & led == 16'b1111111111111111)begin
        next_state <= esscape_mode_up;
    end
    else if(state == esscape_mode_down & dir == 1)begin
        next_state <= esscape_mode_up;
        change_state <= 1;
    end
    else if(state == esscape_mode_up & dir == 0)begin
        next_state <= esscape_mode_down;
        change_state <= 1;
    end
    else if(state == esscape_mode_down & led == 16'b0000000000000000)begin
        next_state <= shining_mode;
    end
    else if(state == esscape_mode_up & led == 16'b1111111111111111)begin
        next_state <= regular_mode;
    end
    else if(state == shining_mode & shining_repeat == 3'b100 & led == 16'b1111111111111111)begin
        next_state <= regular_mode;
    end
    else 
        next_state <= state;
end

always@(posedge clk_div , posedge rst)begin
    if(rst)begin
        regular_repeat <= 2'b00;
    end
    else begin
        regular_repeat <= next_regular_repeat;
    end
end

always @(*) begin
    if(!en)
        next_regular_repeat <= regular_repeat;
    else if(regular_repeat == 2'b11)
        next_regular_repeat <= 2'b00;
    else if(state == regular_mode & led == 16'b1110111011101110)
        next_regular_repeat <= regular_repeat + 2'b01;
    else
        next_regular_repeat <= regular_repeat;
end 

always@(posedge clk_div , posedge rst)begin
    if(rst)begin
        shining_repeat <= 3'b000;
    end
    else begin
        shining_repeat <= next_shining_repeat;
    end
end

always @(*) begin
    if(!en)
        next_shining_repeat <= shining_repeat;
    else if(shining_repeat == 3'b101)
        next_shining_repeat <= 3'b000;
    else if(state == shining_mode & led == 16'b1111111111111111)
        next_shining_repeat <= shining_repeat + 3'b001;
    else 
        next_shining_repeat <= shining_repeat;
end 

always@(posedge clk_div , posedge rst)begin
    if(rst)begin
        led <= 16'b0000000000000000;
    end
    else if (change_state)begin
        led <= next_led;
        change_state <= 0;
    end
    else begin
        led <= next_led;
    end
end

always @(*)begin
    if(!en)
        next_led <= led;
    else if(state == regular_mode )begin
        if(led == 16'b0000000000000000)
            next_led <= 16'b1000100010001000;
        else if(led == 16'b1000100010001000)
            next_led <= 16'b1100110011001100;
        else if(led == 16'b1100110011001100)
            next_led <= 16'b1110111011101110;
        else if(led == 16'b1110111011101110)
            next_led <= 16'b1111111111111111;
        else if(led == 16'b1111111111111111 & regular_repeat == 2'b11)
            next_led <= 16'b1111111111111111; 
        else if(led == 16'b1111111111111111)
            next_led <= 16'b0000000000000000; 
    end
    else if(state == esscape_mode_down)begin
        if(dir)
            next_led <= led * 4 + 3;
        else
            next_led <= led >> 2;
    end
    else if(state == esscape_mode_up)begin
        if(dir)
            next_led <= led * 4 + 3;
        else
            next_led <= led >> 2;
    end
    else if(state == shining_mode)begin
        if(led == 16'b1111111111111111)
            next_led <= 16'b0000000000000000;
        else if(led == 16'b0000000000000000 && shining_repeat == 3'b101)
            next_led <= 16'b1000100010001000;
        else if(led == 16'b0000000000000000)
            next_led <= 16'b1111111111111111;
    end
    else 
        next_led <= led;
end


endmodule