246 lines
7.9 KiB
Verilog
246 lines
7.9 KiB
Verilog
`timescale 1ns / 1ps
|
|
|
|
|
|
module bullet_control(
|
|
input clk,
|
|
input reset_n,
|
|
input start,
|
|
input [ 2: 0 ] mode,
|
|
input [ 10: 0 ] tank_H,
|
|
input [ 10: 0 ] tank_V,
|
|
input tank_en,
|
|
input [ 1: 0 ] tank_dir,
|
|
input tank_fire,
|
|
input player_enermy, //player is 0 and enermy is 1
|
|
|
|
input [ 10: 0 ] vgaH,
|
|
input [ 10: 0 ] vgaV,
|
|
input ready,
|
|
input item_faster,
|
|
output [ 11: 0 ] bulletData,
|
|
output reg [ 10: 0 ] bullet_H_feedback,
|
|
output reg [ 10: 0 ] bullet_V_feedback,
|
|
output reg [ 2: 0 ] bullet_direction
|
|
);
|
|
|
|
parameter BULLET_LONGER = 10;
|
|
parameter BULLET_SHORTER = 5;
|
|
parameter BULLET_LONGER_CENTER = 5;
|
|
parameter BULLET_SHORTER_CENTER = 2;
|
|
parameter HEIGHT = 480;
|
|
parameter WIDTH = 640;
|
|
parameter TANK_V_CENTER = 16;
|
|
parameter TANK_H_CENTER = 16;
|
|
parameter TANK_HEIGHT = 32, TANK_WIDTH = 32;
|
|
|
|
localparam
|
|
UP = 3'd0,
|
|
DOWN = 3'd1,
|
|
LEFT = 3'd2,
|
|
RIGHT = 3'd3,
|
|
WAIT = 3'd4,
|
|
READY = 3'd5;
|
|
|
|
reg counter_en;
|
|
reg [ 31: 0 ] counter;
|
|
reg [ 2: 0 ] current_state, next_state;
|
|
|
|
always @( posedge clk ) begin:state_flip_flop
|
|
if ( !reset_n ) begin
|
|
current_state <= WAIT;
|
|
end
|
|
else if ( !tank_en ) begin
|
|
current_state <= WAIT;
|
|
end
|
|
else begin
|
|
current_state <= next_state;
|
|
end
|
|
end
|
|
|
|
always @( * ) begin: state_table
|
|
case ( current_state )
|
|
WAIT:
|
|
next_state = start ? READY : WAIT;
|
|
READY: begin
|
|
if ( !tank_fire ) begin
|
|
next_state = READY;
|
|
end
|
|
else begin
|
|
case ( tank_dir )
|
|
2'b00:
|
|
next_state = UP;
|
|
2'b01:
|
|
next_state = DOWN;
|
|
2'b10:
|
|
next_state = LEFT;
|
|
2'b11:
|
|
next_state = RIGHT;
|
|
endcase
|
|
end
|
|
end
|
|
UP:
|
|
next_state = ready ? READY : UP;
|
|
DOWN:
|
|
next_state = ready ? READY : DOWN;
|
|
LEFT:
|
|
next_state = ready ? READY : LEFT;
|
|
RIGHT:
|
|
next_state = ready ? READY : RIGHT;
|
|
default:
|
|
next_state = READY;
|
|
endcase
|
|
end
|
|
|
|
always @( * ) begin: bullet_logic
|
|
case ( current_state )
|
|
READY: begin
|
|
counter_en = 0;
|
|
bullet_direction = 3'b111;
|
|
end
|
|
UP: begin
|
|
counter_en = 1;
|
|
bullet_direction = 3'b000;
|
|
end
|
|
DOWN: begin
|
|
counter_en = 1;
|
|
bullet_direction = 3'b001;
|
|
end
|
|
LEFT: begin
|
|
counter_en = 1;
|
|
bullet_direction = 3'b010;
|
|
end
|
|
RIGHT: begin
|
|
counter_en = 1;
|
|
bullet_direction = 3'b011;
|
|
end
|
|
default : begin
|
|
counter_en = 0;
|
|
bullet_direction = 3'b111;
|
|
end
|
|
|
|
endcase
|
|
end
|
|
|
|
reg bullet_move_en;
|
|
wire [ 31: 0 ] bullet_speed;
|
|
assign bullet_speed = item_faster ? 600_000 : 1_000_000;
|
|
always @( posedge clk ) begin: counter_logic
|
|
if ( !reset_n ) begin
|
|
counter <= 0;
|
|
bullet_move_en <= 0;
|
|
end
|
|
else if ( counter == bullet_speed ) begin
|
|
counter <= 0;
|
|
bullet_move_en <= 1;
|
|
end
|
|
else if ( counter_en == 0 ) begin
|
|
counter <= 0;
|
|
bullet_move_en <= 0;
|
|
end
|
|
else begin
|
|
counter <= counter + 1;
|
|
bullet_move_en <= 0;
|
|
end
|
|
end
|
|
|
|
always @( posedge clk ) begin: bullet_move
|
|
if ( bullet_direction[ 2 ] ) begin //if no direction
|
|
case ( tank_dir )
|
|
2'b00: begin
|
|
bullet_H_feedback <= tank_H + TANK_H_CENTER - BULLET_SHORTER_CENTER;
|
|
bullet_V_feedback <= ( ( tank_V >= BULLET_LONGER ) ? ( tank_V - BULLET_LONGER ) : 0 );
|
|
end
|
|
2'b01: begin
|
|
bullet_H_feedback <= tank_H + TANK_H_CENTER - BULLET_SHORTER_CENTER;
|
|
bullet_V_feedback <= ( ( tank_V + TANK_HEIGHT + BULLET_LONGER <= HEIGHT ) ? ( tank_V + TANK_HEIGHT + BULLET_LONGER ) : HEIGHT );
|
|
end
|
|
2'b10: begin
|
|
bullet_H_feedback <= ( ( tank_H >= BULLET_LONGER ) ? ( tank_H - BULLET_LONGER ) : 0 );
|
|
bullet_V_feedback <= tank_V + TANK_V_CENTER - BULLET_SHORTER_CENTER;
|
|
end
|
|
2'b11: begin
|
|
bullet_H_feedback <= ( ( tank_H + BULLET_LONGER + TANK_WIDTH <= WIDTH ) ? ( tank_H + BULLET_LONGER + TANK_WIDTH ) : WIDTH ) ;
|
|
bullet_V_feedback <= tank_V + TANK_V_CENTER - BULLET_SHORTER_CENTER;
|
|
end
|
|
endcase
|
|
end
|
|
else if ( bullet_move_en ) begin
|
|
case ( bullet_direction[ 1: 0 ] )
|
|
2'b00: begin
|
|
bullet_V_feedback <= bullet_V_feedback - 1;
|
|
bullet_H_feedback <= bullet_H_feedback;
|
|
end
|
|
|
|
2'b01: begin
|
|
bullet_V_feedback <= bullet_V_feedback + 1;
|
|
bullet_H_feedback <= bullet_H_feedback;
|
|
end
|
|
2'b10: begin
|
|
bullet_H_feedback <= bullet_H_feedback - 1;
|
|
bullet_V_feedback <= bullet_V_feedback;
|
|
end
|
|
2'b11: begin
|
|
bullet_H_feedback <= bullet_H_feedback + 1;
|
|
bullet_V_feedback <= bullet_V_feedback;
|
|
end
|
|
endcase
|
|
end
|
|
else begin
|
|
bullet_H_feedback <= bullet_H_feedback;
|
|
bullet_V_feedback <= bullet_V_feedback;
|
|
end
|
|
end
|
|
|
|
wire [ 11: 0 ] UP_data, DOWN_data, LEFT_data, RIGHT_data;
|
|
wire [ 7: 0 ] bulletAddr;
|
|
reg bullet_bound;
|
|
|
|
always @( * ) begin
|
|
case ( bullet_direction[ 1: 0 ] )
|
|
2'b00: begin
|
|
bullet_bound <= ( bullet_H_feedback <= vgaH && bullet_H_feedback > vgaH - BULLET_SHORTER && bullet_V_feedback <= vgaV && bullet_V_feedback > vgaV - BULLET_LONGER ) ? 1 : 0;
|
|
end
|
|
2'b01: begin
|
|
bullet_bound <= ( bullet_H_feedback <= vgaH && bullet_H_feedback > vgaH - BULLET_SHORTER && bullet_V_feedback <= vgaV && bullet_V_feedback > vgaV - BULLET_LONGER ) ? 1 : 0;
|
|
end
|
|
2'b10: begin
|
|
bullet_bound <= ( bullet_H_feedback <= vgaH && bullet_H_feedback > vgaH - BULLET_LONGER && bullet_V_feedback > vgaV - BULLET_SHORTER && bullet_V_feedback <= vgaV ) ? 1 : 0;
|
|
end
|
|
2'b11: begin
|
|
bullet_bound <= ( bullet_H_feedback <= vgaH && bullet_H_feedback > vgaH - BULLET_LONGER && bullet_V_feedback <= vgaV && bullet_V_feedback > vgaV - BULLET_SHORTER ) ? 1 : 0;
|
|
end
|
|
endcase
|
|
end
|
|
reg [ 5: 0 ] bullet_addr;
|
|
always @( * ) begin
|
|
case ( bullet_direction[ 1: 0 ] )
|
|
2'b00: begin
|
|
bullet_addr <= bullet_bound ? ( ( vgaV - bullet_V_feedback ) * BULLET_SHORTER + ( vgaH - bullet_H_feedback ) ) : 15;
|
|
end
|
|
2'b01: begin
|
|
bullet_addr <= bullet_bound ? ( ( vgaV - bullet_V_feedback ) * BULLET_SHORTER + ( vgaH - bullet_H_feedback ) ) : 15;
|
|
end
|
|
2'b10: begin
|
|
bullet_addr <= bullet_bound ? ( ( vgaV - bullet_V_feedback ) * BULLET_LONGER + ( vgaH - bullet_H_feedback ) ) : 15;
|
|
end
|
|
2'b11: begin
|
|
bullet_addr <= bullet_bound ? ( ( vgaV - bullet_V_feedback ) * BULLET_LONGER + ( vgaH - bullet_H_feedback ) ) : 15;
|
|
end
|
|
endcase
|
|
|
|
end
|
|
|
|
wire [ 11: 0 ] outData;
|
|
|
|
bullet_left_img left( .addra( bullet_addr ), .clka( clk ), .douta( LEFT_data ), .ena( 1'b1 ) );
|
|
bullet_right_img right( .addra( bullet_addr ), .clka( clk ), .douta( RIGHT_data ), .ena( 1'b1 ) );
|
|
bullet_up_img up( .addra( bullet_addr ), .clka( clk ), .douta( UP_data ), .ena( 1'b1 ) );
|
|
bullet_down_img down( .addra( bullet_addr ), .clka( clk ), .douta( DOWN_data ), .ena( 1'b1 ) );
|
|
|
|
tank_data_selector bullet_selector( .clk( clk ), .UP( UP_data ), .DOWN( DOWN_data ), .LEFT( LEFT_data ),
|
|
.RIGHT( RIGHT_data ), .Dir( bullet_direction[ 1: 0 ] ), .tankData( outData ) );
|
|
|
|
assign bulletData = ( ~ready & bullet_bound && ( mode == 3'b010 || mode == 3'b001 ) ) ? outData : 0;
|
|
|
|
endmodule
|