Untitled
unknown
plain_text
3 years ago
12 kB
10
Indexable
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
Editor is loading...