Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
12 kB
2
Indexable
Never
module clock_divider #(parameter n = 25)(
    input clk,
    output clk_div
);
    reg [n-1:0] num = 0;
    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 freeze,
    output reg [15:0] led
);  
    wire clk24;
    wire clk27;
    reg current_clk;
    reg [3:0]counter_car, next_counter_car;
    reg [3:0]counter_motor, next_counter_motor;
    reg [2:0] state, next_state;
    reg [15:0] car_pos, next_car_pos;
    reg [15:0] motor_pos, next_motor_pos;
    reg [2:0] car_score, next_car_score;
    reg [2:0] motor_score, next_motor_score;
    reg turbo_times, next_turbo_times;
    reg turbo_on;
    reg [2:0]turbo_counter, next_turbo_counter;
    integer i;
    clock_divider #(
    .n(24)
    ) clkdiv24 (
    .clk(clk),
    .clk_div(clk24)
    );
    clock_divider #(
    .n(27)
    ) clkdiv27 (
    .clk(clk),
    .clk_div(clk27)
    );
    parameter ALL_INIT = 3'd0;
    parameter ROUND_INIT = 3'd1;
    parameter RACING = 3'd2;
    parameter ROUND_FINISH = 3'd3;
    parameter CAR_WIN = 3'd4;
    parameter MOTOR_WIN = 3'd5;
   
    integer i;
    // state
    always@(posedge clk24, posedge rst) begin
        if(rst) begin
            state <= ALL_INIT;
        end
        else begin
            state <= next_state;
        end
    end

    always@(*) begin
        case(state)
            ALL_INIT:begin
                next_state = ROUND_INIT;
            end
            ROUND_INIT:begin
                next_state = RACING;
            end
            RACING:begin
                if(led[2] == 1) begin
                    next_state = ROUND_FINISH;
                end
                else begin
                    next_state = RACING;
                end
            end
            ROUND_FINISH:begin
                if(motor_score == 4) begin
                    next_state = MOTOR_WIN;
                end
                else if(car_score == 4) begin
                    next_state = CAR_WIN;
                end
                else begin
                    next_state = ROUND_INIT;
                end
            end
            CAR_WIN:begin
                next_state = ALL_INIT;
            end
            MOTOR_WIN:begin
                next_state = ALL_INIT;
            end
        endcase
    end
    //turbo control
    always@(*) begin
        if(turbo_on == 1) begin
            current_clk = clk24;
        end
        else begin
            current_clk = clk27;
        end
    end

    always@(*)begin
        if(rst)begin
            turbo_on = 0;
        end
        else begin
            case(state)
            RACING:begin
                if((speed == 1 && turbo_times == 0) ||  (turbo_counter > 0 && turbo_counter < 5))begin
                    turbo_on = 1;
                end
            end
            default:
                turbo_on = 0;
        endcase
        end
        
        
    end
    always@(current_clk) begin
        if(rst) begin
            turbo_counter <= 0;
            turbo_times <= 0;
        end
        else begin
            turbo_counter <= next_turbo_counter;
            turbo_times <= next_turbo_times;
        end
    end
    always@(*)begin
        case(state)
            ROUND_INIT:begin
                next_turbo_counter = 0;
                next_turbo_times = 0;
            end
            RACING:begin
                if(turbo_on == 1)begin
                    next_turbo_counter = turbo_counter + 1;
                    next_turbo_times = 1;
                end
                else begin
                    next_turbo_counter = turbo_counter;
                    next_turbo_times = turbo_times;
                end
            end
            default:begin
                next_turbo_counter = 0;
                next_turbo_times = 0;
            end
        endcase
    end
    //car position led
    always@(posedge current_clk, posedge rst) begin
        if(rst) begin
            for(i = 0; i < 16; i = i+1) begin
                    car_pos[i] <= 0;
            end
        end
        else begin
            car_pos <= next_car_pos;
        end
    end

    always@(*) begin
        case(state) 
            ALL_INIT:begin
                for(i = 0; i < 16; i = i+1) begin
                    next_car_pos[i] = 0;
                end
                next_car_pos[13] = 1;
                next_car_pos[12] = 1;
            end
            ROUND_INIT: begin
                for(i = 0; i < 14; i = i+1) begin
                    next_car_pos[i] = 0;
                end
                next_car_pos[13] = 1;
                next_car_pos[12] = 1;
            end
            RACING: begin
                for(i = 0; i < 14; i = i+1) begin
                    next_car_pos[i] <= 0;
                end
                next_car_pos[counter_car] = 1;
                next_car_pos[counter_car - 1] = 1;
            end
            ROUND_FINISH:begin
                case(car_score) 
                    3'd0:begin
                        next_car_pos[15] = 0;
                        next_car_pos[14] = 0;
                    end
                    3'd1:begin
                        next_car_pos[15] = 0;
                        next_car_pos[14] = 1;
                    end
                    3'd2:begin
                        next_car_pos[15] = 1;
                        next_car_pos[14] = 0;
                    end
                    3'd3:begin
                        next_car_pos[15] = 1;
                        next_car_pos[14] = 1;
                    end
                    3'd4:begin
                        next_car_pos[15] = 1;
                        next_car_pos[14] = 1;
                    end
                    default:begin
                        
                    end
                endcase
            end
            CAR_WIN:begin
                for(i = 2; i < 16; i = i+1) begin
                    next_car_pos[i] = 1;
                end 
                next_car_pos[0] = 0;
                next_car_pos[1] = 0;
            end
            MOTOR_WIN:begin
                for(i = 0; i < 16; i = i+1) begin
                    next_car_pos[i] = 0;
                end 
            end
        endcase
    end
    
    //car_score
    always@(posedge clk24, posedge rst)begin
        if(rst) begin
            car_score <= 0;
        end
        else begin
            car_score <= next_car_score;
        end
    end
    always@(*) begin
        case(state)
            ALL_INIT:begin
                next_car_score = 0;
            end
            ROUND_INIT:begin
                next_car_score = 0;
            end
            ROUND_FINISH:begin
                if(car_pos[2] == 1 && motor_pos[2] == 0)begin
                    next_car_score = car_score + 1;
                end
                else begin
                    next_car_score = car_score;
                end
            end
        endcase  
    end
    //counter_car
    always@(*) begin
        if(rst) begin
            counter_car = 4'd13;
        end
        else begin
            counter_car = next_counter_car;
        end
    end

    always@(posedge current_clk)begin
        case(state)
            ROUND_INIT:begin
                next_counter_car <= 0;
            end
            RACING:begin
                if(en ==1 )begin
                    next_counter_car <= counter_car + 1;
                end
                else begin
                    next_counter_car <= counter_car;
                end
            end
            default:
                next_counter_car <= counter_car;
        endcase
    end
    ///////////////////////////////////////////////////////////////////////
    //motor position led
    always@(posedge clk24, posedge rst) begin
        if(rst) begin
            for(i = 0; i < 16; i = i+1) begin
                    motor_pos[i] <= 0;
            end
        end
        else begin
            motor_pos <= next_motor_pos;
        end
    end

    always@(*) begin
        case(state) 
            ALL_INIT:begin
                for(i = 0; i < 16; i = i+1) begin
                    next_motor_pos[i] = 0;
                end
                next_motor_pos[10] = 1;
           
            end
            ROUND_INIT: begin
                for(i = 2; i < 16; i = i+1) begin
                    next_motor_pos[i] = 0;
                end
                next_motor_pos[10] = 1;
            end
            RACING: begin
                for(i = 2; i < 16; i = i+1) begin
                    next_motor_pos[i] <= 0;
                end
                next_motor_pos[counter_motor] = 1;
                next_motor_pos[counter_motor - 1] = 1;
            end
            ROUND_FINISH:begin
                case(motor_score) 
                    3'd0:begin
                        next_motor_pos[1] = 0;
                        next_motor_pos[0] = 0;
                    end
                    3'd1:begin
                        next_motor_pos[1] = 0;
                        next_motor_pos[0] = 1;
                    end
                    3'd2:begin
                        next_motor_pos[1] = 1;
                        next_motor_pos[0] = 0;
                    end
                    3'd3:begin
                        next_motor_pos[1] = 1;
                        next_motor_pos[0] = 1;
                    end
                    3'd4:begin
                        next_motor_pos[1] = 1;
                        next_motor_pos[0] = 1;
                    end
                    default:begin
                        
                    end
                endcase
            end
            CAR_WIN:begin
                for(i = 0; i < 16; i = i+1) begin
                    next_motor_pos[i] = 0;
                end 
                
            end
            MOTOR_WIN:begin
                for(i = 0; i < 14; i = i+1) begin
                    next_motor_pos[i] = 1;
                end 
                next_motor_pos[15] = 0;
                next_motor_pos[14] = 0;
            end
        endcase
    end
    
    //motor_score
    always@(posedge clk24, posedge rst)begin
        if(rst) begin
            motor_score <= 0;
        end
        else begin
            motor_score <= next_motor_score;
        end
    end
    always@(*) begin
        case(state)
            ALL_INIT:begin
                next_motor_score = 0;
            end
            ROUND_INIT:begin
                next_motor_score = 0;
            end
            ROUND_FINISH:begin
                if(motor_pos[2] == 1)begin
                    next_motor_score = motor_score + 1;
                end
                else begin
                    next_motor_score = motor_score;
                end
            end
        endcase  
    end
    //counter_motor
    always@(*) begin
        if(rst) begin
            counter_motor = 4'd13;
        end
        else begin
            counter_motor = next_counter_motor;
        end
    end

    always@(posedge clk27)begin
        case(state)
            ROUND_INIT:begin
                next_counter_motor <= 0;
            end
            RACING:begin
                if(freeze == 1) begin
                    next_counter_motor <= counter_motor;
                end
                else if(en ==1 )begin
                    next_counter_motor <= counter_motor + 1;
                end
                else begin
                    next_counter_motor <= counter_motor;
                end
            end
            default:
                next_counter_motor <= counter_motor;
        endcase
    end
    //output
    always@(clk24) begin
        led <= car_pos | motor_pos;
    end
endmodule