Vous êtes sur la page 1sur 28

MIDDLE EAST TECHNICAL UNIVERSITY

DEPARTMENT OF ELECTRICAL AND


ELECTRONICS ENGINEERING
EE 314 DIGITAL ELECTRONICS LABORATORY

PROJECT FINAL REPORT


AIR HOCKEY

Fatih GKMENOLU - 1814136

Arif Can GNGR - 1814219

Assistant: zlem Tufe DEMR


1. Introduction
As the term project of Digital Electronics laboratory, we have chosen Air-Hockey game.
Air-Hockey is a well-known game that has two player-held mullets which are controlled by
two players and a puck. In this project a 2D surface was used for the implementation of the
game.

For the project, as it was required, we did use Verilog to code our game. For
implementation we utilized the FPGAs in our laboratory. Since we are already well aware of
Verilog and FPGAs thanks to the laboratory sessions, we were able focus on the game design
more.

At the beginning, we constructed more basic structures to understand the project in


detail. Afterwards, we started coding our game on our own with the help our previous
knowledge including laboratory experience, geometry and dynamics.

Details of our source code along with some screenshots from the gameplay can be
found in the following sections.

2. Verilog Code Parts


2.1. Defining Variables
At the beginning of coding, we considered what kind of variables we need to use.
Taking into account our available space, we carefully defined our variables. For instance, we
used a [8:0] register for our county variable because we have 480 pixels on the Y axis. We did
strictly avoid using unnecessarily large variables in our source code.

The code segment that includes our variable definitions is given below.

module direngezi(kontrol, clk_in, vga_h_sync, vga_v_sync, vga_R, vga_G,


vga_B, vga_R2, vga_G2, vga_B2,vga_R1, vga_G1, vga_B1, l1, l2, r1, r2, u1,
u2, d1, d2, ses);

input kontrol, clk_in, l1, l2, r1, r2, u1, u2, d1, d2;
output vga_h_sync, vga_v_sync, vga_R, vga_G, vga_B, vga_R2, vga_G2,
vga_B2,vga_R1, vga_G1, vga_B1, ses;

reg clk, klk, saat, ses, ses1, ses2, ses3;


reg ml1, ml2, mr1, mr2, mu1, mu2, md1, md2;
reg [1:0] counter;
reg [23:0] ctr, ctra, ctrb, ctrc, cnr;
reg [9:0] countx;
reg [8:0] county;
reg vga_h, vga_v;
reg [3:0] sag_mal;
reg [3:0] sol_mal;
reg ber, sol, sag, alert, biter, kontrol2;
reg [3:0] aa,bb,cc;
reg [9:0] topx;
reg [8:0] topy;
reg [3:0] topyh;
reg [3:0] topxh;
reg [9:0] m1x;
reg [8:0] m1y;
reg [9:0] m2x;
reg [8:0] m2y;
reg a1,a2,a3,a4,a5,a6,a7;
reg b1,b2,b3,b4,b5,b6,b7;
reg c1,c2,c3,c4,c5,c6,c7;
reg w1,w2,w3,w4,w5,w6,w7;
reg e1,e2,e3,e4,e5,e6,e7;
reg vga_R, vga_B, vga_G, vga_R1, vga_B1, vga_G1, vga_R2, vga_B2, vga_G2;

2.2. Initializations
Upon defining our variables, we initialized the variables that need proper values
before getting processed. For this purpose, we did use an initial block. The related source
code can be seen as follows;

// All Initializations
initial
begin
topyh=1; //2: up ,1:down
topxh=1; //2: left , 1:right
m1x= 7;
m1y= 199;
m2x = 552;
m2y= 201;
topx = 50;
topy = 200;
ml1=0;
ml2=0;
mr1=0;
mr2=0;
mu1=0;
mu2=0;
md1=0;
md2=0;
ses=0;
sag_mal=0;
sol_mal=0;
clk=0;
klk=0;
saat=0;
ses1=0;
ses2=0;
ses3=0;
counter=0;
ctr=0;
ctrc=0;
ctrb=0;
ctra=0;
cnr=0;
alert=0;
biter=0;
aa = 2;
bb = 0;
cc = 3;
kontrol2 = 0;
end
2.3. Frequency Divider (User Defined Clocks)
The FPGA board that we used in the laboratory has a 100 MHz internal clock. However,
to be able to achieve vertical and horizontal synchronization, we had to divide it to get a
frequency of 25 MHz Furthermore; we did define other clocks such as klk, ses1 for the
convenience of gameplay and for specific sounds. Source code for the clocks that we defined
is given below.
// All clock divisions
// 25MHz , gaming clock(250Hz), real time clock (1Hz), sound effects

// 25 Mhz
always @ (posedge clk_in)
begin
counter = counter+1;
if (counter ==2)
begin
clk=~clk;
counter=0;
end
end
// Gaming clock (klk 250Hz)
always @ (posedge clk)
begin
if (kontrol==0&&kontrol2==0)
begin
ctr = ctr+1;
if (ctr == 50000)
begin
klk=~klk;
ctr=0;
end
end
else if (kontrol==1||kontrol2==1)
begin klk=0; end
end
// Sound Effect 1
always @ (posedge clk)
begin
ctra = ctra+1;
if (ctra == 5000)
begin
ses1=~ses1;
ctra=0;
end
end
// Sound Effect 2
always @ (posedge clk)
begin
ctrb = ctrb+1;
if (ctrb == 2500)
begin
ses2=~ses2;
ctrb=0;
end
end
// Sound Effect 3
always @ (posedge clk)
begin
ctrc = ctrc+1;
if (ctrc == 7500)
begin
ses3=~ses3;
ctrc=0;
end
end

// Real Time Clock (1 Hz)


always @ (posedge klk)
begin
cnr = cnr+1;
if (cnr == 125)
begin
saat=~saat;
cnr=0;
end
end

2.4. Counters and Synchronizations


In order to display the drawings on the screen, we need to achieve necessary
horizontal and vertical synchronizations. For this purpose, we did use counters that we
defined previously. In the following code, countx begins increasing by one until it reaches
the end of the current line. Then it reset to zero, and county increases by one. At the end,
we are able to scan all the pixels on the screen.

// VGA Synchronizations
always @ (posedge clk)
begin
if (countx<799)
countx=countx+1;
else
begin
countx=0;
if (county< 520)
county=county+1;
else
county=0;
end

if (countx>655 & countx<751)


vga_h = 0;
else
vga_h = 1;

if (county>489 & county<491)


vga_v = 0;
else
vga_v = 1;
end

assign vga_h_sync=vga_h;
assign vga_v_sync=vga_v;
2.5. Borders
We created our game screen considering 640x480 display resolution. When we create
the gameplay area, we left a place for countdown and scoreboard parts at the bottom of the
screen and all the mullets and the ball are restricted by the borders of the air hockey field.
The borders are created by the following code segment:
wire
border=(county==0)||(county==400)||(((county<140)||(county>260))&&((countx=
=0)||(countx==559)))||((countx==279)&&((county>0)||(county<400)));

Here we set up and down borders by a straightforward manner. On the other hand,
for the left and right parts we also considered goal areas. The borders are displayed in white
color in normal game play.

2.6. Ball & Mullets


In a typical air hockey game, there are generally two mullets defending their goal
areas and one puck. In our project we performed the same strategy. We created two mullets
which are rectangular and a ball which is circular. The mullets are created in different colors,
one is blue the other one is green, as colored mullets were required. And the ball is in white
color. In order to use the positions of these mullets and the ball when we consider
interactions, we kept their midpoint information. In other words, the x-axis and y-axis
midpoint information are stored in registers and according to these midpoints we formed
the ball and the mullets with the following code segment:
wire top=(((countx-topx)*(countx-topx)+(county-topy)*(county-topy))<= 100);
wire m1 = ( m1x-3<countx & countx<m1x+3 & county>m1y-30 & county<m1y+30 );
wire m2 = ( m2x-3<countx & countx<m2x+3 & county>m2y-30 & county<m2y+30 );

Here, top stands for the ball, m1 and m2 stand for the mullets. The ball is a round shaped
with radius=10pixels. Mullets are rectangular with 60x6 pixels dimensions. topx , topy,
m1x, m1y, m2x, m2y are the registers that store the midpoint information of the ball,
mullet1 and mullet2.

2.7. Collisions and Movements


In an air hockey game there are a moving ball and a lot of interactions. Ball bounces
back from all the mullets and the border, in other words, it cannot go beyond the borders
and it cannot pass inside of the mullets. Also mullets need to be controllable externally. That
is why we needed to consider a lot of cases defining these movement and interactions.
Actually this part is the main part of the project.
For the border & ball interactions algorithm was simple. When the midpoint of the
ball is closer to one of the border more than the radius of the ball, the ball changes its
direction. For example, when the midpoint of the ball is too close to upper border, its
direction on y-axis flips and it preserves the direction on x axis. If the ball is closer to the left
border more than its radius, its direction on x axis flips and it does not change its y axis
movement.

For the mullet & ball interactions algorithm is almost the same as ball & border
interactions. The code checks the location of the midpoints at every gaming clock and
decides whether the ball is one of the interaction zones. There are four zones for each
mullet: upper-left, upper-right, lower-left, lower-right. For example, if the ball comes from
the upper-right of the one of the mullet it bounces back, preserving its y-directional speed
and inverts x-directional speed.

For the mullet movements, we are required to move each mullet to the four
directions by external commands. We assigned 8 pins on the fpga board as our inputs. These
pins send up, down, left, right commands for each mullet. When there is a command to the
mullet the midpoint of the mullet moves accordingly. We adjusted our game so that the
mullet cannot pass the midline of the game field as well as the borders.

We created all these movement and interaction code in one always block with some
clock signal. The clock signal of this part klk is determines the gaming speed, that is why we
used another divided clock with 250Hz. In this part of the code we also added an external
control to pause the game when the value of this pause pin is high then 0 is assigned to klk
signal and the whole game and the countdown is stopped.

In the following code segment you can see a few conditions on the interaction and
movements. The whole code block can be reached from the Appendix C. Here, topxh and
topyh are the information about the balls movement, i.e. the directional speed or the goal
situation. l1, l2, u1 are the inputs for the mullets and m1x, m1y, m2x, m2y are the
midpoint information for mullets.

// ALL INTERACTIONS in this always block


always @ (posedge klk)
begin
if ((topy == 389)&(topyh==1)) // lower border interaction
begin topyh <= 2 ; topxh <= topxh; end

// mullet1 & ball interactions


else if ( ((topx-m1x<=12)) &((m1y<=topy)&(topy<m1y+38) )&
((topxh==2)||(topxh==0) ) )
begin topxh<=1; topyh<=topyh; end // upper-right

// mullet2 & ball interactions


else if ( ((topx-m2x<=12)) &((m2y<topy)&(topy<m2y+38) )&
((topxh==2)||(topxh==0)))
begin topxh<=1; topyh<=topyh; end // upper-right

// ball directions
case (topyh)
1: topy<=topy+1; // goes down
2: topy<=topy-1; // goes up
0: topy<=topy; // no change
3: topy<=201; // after goal initialization
4: topy<=201; // after goal initialization
endcase
case (topxh)
1: topx<= topx+1; // goes right
2: .

// mullet inputs
ml1<=l1;
ml2<=l2;

// mullet 1 movements
if ((ml1==1)&(m1x>8)) begin m1x<=m1x-1; end // goes left

// mullet 2 movements
if ((ml2==1)&(m2x>284)) begin m2x<=m2x-1; end // goes left

end

2.8. Goal
The main purpose of the game is to score goals in order to win the game, beat the
opponent. For this purpose, we need to let goals to be scored when ball comes some specific
areas. These goal areas were defined when we created the borders.

When there is a goal, the display under the mullet which scores the goal increases by
one. Also, when a mullet concedes a goal the ball appears right in front of it, as it was
required. After a goal mullet locations are also initialized. And then the mullet who conceded
a goal starts the game. The related code segment is this;

// GOAL!
if ((topx==3)&((topy<260)&(topy>140))) // goal to the left side
begin sag_mal<=sag_mal+1; topxh<=3; topyh<=3; m1x<=7; m2x<=552;
m1y<=201; m2y<=201; end

else if ((topx==558)&(topy<260)&(topy>140)) // goal to the right side


begin sol_mal<=sol_mal+1; topxh<=4; topyh<=4; m1x<=7; m2x<=552;
m1y<=201; m2y<=201; end

Here, sol_mal and sag_mal are the scores of the mullets. This score information is
stored in registers. By controlling topxh, topyh the reappearing of the ball in from of the
mullet is also provided. This segment is also located in the always block that we considered
the interactions and movements.
2.9. Scoreboard
We created one digit seven-segment-like displays to shows the score. There are two
such displays under the each mullet showing the score of the mullet. After each goal the
display under the mullet which scores increases by one. These displays are also colored with
the some color of each mullet. At the end of the game the winner is decided by considering
these scores.

The code of these displays can be reached from the whole project code that is
available in the Appendix C. We created all numbers pixel by pixels with case function in
Verilog and assigned each of them to vga output according to their desired colors.

2.10. Timing
We were required to create a countdown to indicate time left until the end of the
game. For this purpose we created three more seven segment-like displays. Our countdown
counts in seconds from an initial value to 0. The initial value can easily be adjusted from 0
to 999. To count in 1Hz rate (real timing frequency) we created another clock signal saat by
dividing the internal clock. And then in an always block controlled by this saat signal, we
made assignments of the digits and adjusted a nice countdown in real time.

The related code part is as follows:


always @ (posedge saat)
begin
if ((aa!=0)&(biter==0))
begin aa<=aa-1; end
else if((aa==0)&(bb!=0)&(biter==0))
begin aa<=9; bb<=bb-1; end
else if ((aa==0)&(bb==0)&(biter==0))
begin aa<=9; bb<=9; end
if ((bb==0)&(cc!=0)&(aa==0)&(biter==0))
begin bb<=9; cc<=cc-1; end
else if ((bb==0)&(aa==0)&(cc==0)&(biter==0))
begin bb<=9; cc<=0; end
end

Here, aa, bb, cc are the three digits of the time left from least significant to most
significant. For example, when cc=2, bb=6, aa=4, the time left is 264 seconds. And each digit
is displayed with 7-segment-like displays on the screen. The code of these 7segment-like
displays can be reached from the Appendix C.

2.11. End of Game


First of all when time part reaches 010 that is the time left is ten seconds, in order
to indicate the game is about the finish the borders and the ball change color, they turn into
red (see Appendix A, Figure 2). Also there is a continuous sound effect which is heard when
the time left is less than ten seconds.
When the time reaches 000, that is the Time is up. condition. Game ends and this
ended situation is stored in a register named biter. The winner mullet is decided
considering their scores at the end. If the blue one wins then whole game screen turns into
blue (see Appendix A, Figure 3) and an indicator sound is also heard. If the green mullet
wins, then the screen turns into green (see Appendix A, Figure 4) and another indicator
sound is heard. If the scores are even, there is no winner and the screen turns into sea-blue
(see Appendix A, Figure 5) (green+blue) at the end as an indication. Also again by assigning
0 to klk signal the movements are stopped when biter=1 and kontrol2=1. The colorful
indicators are adjusted by the following code segment;
if (biter==1 & sol_mal>sag_mal)
begin sol <= (county>0)&(county<400)& (countx>0) &(countx<559);
ses<=ses1; kontrol2<=1; end //the mullet on the left won
if (biter==1 & sol_mal<sag_mal)
begin sag <= (county>0)&(county<400)& (countx>0) &(countx<559);
ses<=ses2; kontrol2<=1; end // the mullet on the rigth won
if (biter==1 & sol_mal==sag_mal)
begin ber <= (county>0)&(county<400)& (countx>0) &(countx<559);
kontrol2<=1; end

Here, sol_mal and sag_mal are the scored goal numbers of the each mullet. sol,
sag, ber indicates the winner mullet and accordingly the sound and screen colorings are
made.

2.12. Sound Effects


Sound effect for some specific cases is bonus objective of the project. We have
achieved this objective by making some more clock divisions and utilizing a speaker. Humans
can hear the frequencies between 20-20000Hz. Therefore, to obtain a hearable signal we
divided our initial clock signal to the hearable range. By doing so, we created 3 more signals,
i.e. 3 distinct sounds.

We assigned out sound signals to an output pin available on the fpga board and we
connected a speaker to that pin in order to hear those signals.

When a goal is scored one the sound signals is heard until the mullet which conceded
the goal starts the game. The same sound is also heard when the time left is less than 10
seconds as an alert.

The other two distinct sounds are heard at the end of the game indicating the winner.
We adjusted one signal for blue wins case and the other signal to green wins case.
3. Conclusion
In this project, we learned lots of thing about digital electronics, logic design, FPGA and
Verilog coding. We made research on arcade games and Verilog and gained insight into
Verilog coding as well as FPGA. This project is an implementation of the topics covered
during this semester in the digital electronics and logic design lectures and digital electronics
laboratory. Actually, the whole project was enjoyable to deal with. We have successfully
managed to solve the problems we faced during the project. We learnt how to drive a VGA
monitor by using FPGA. Then, we learnt drawing images on the screen using Verilog codes.
We created our code step by step and block by block and design summary of our project can
be seen from Appendix B.

Fortunately, we have reached a good final. Our project satisfies all the requirements
introduced: Two different colored mullet, time limitation and countdown, scoreboard,
disappeared puck when the goal is scored. Also we have created sound affects for some
specific cases as bonus objective.
4. Appendix

4.1. Appendix A

Figure 1. The Gameplay of Air-Hockey

Figure 2. The Last 10 Seconds of the Game

Figure 3. Blue Mullet Won


Figure 4. Green Mullet Won

Figure 5. The Scores Are Even


4.2. Appendix B
Design summary of the project is given below.

4.3 Appendix C
The whole Air-Hockey Project Code can be seen below.

// Arif Can Gngr - Fatih Gkmenolu


// EE 314 - Term Project
// Air Hockey
`timescale 1ns / 1ps

module direngezi(kontrol, clk_in, vga_h_sync, vga_v_sync, vga_R, vga_G,


vga_B, vga_R2, vga_G2, vga_B2,vga_R1, vga_G1, vga_B1, l1, l2, r1, r2, u1,
u2, d1, d2, ses);

input kontrol, clk_in, l1, l2, r1, r2, u1, u2, d1, d2;
output vga_h_sync, vga_v_sync, vga_R, vga_G, vga_B, vga_R2, vga_G2,
vga_B2,vga_R1, vga_G1, vga_B1, ses;

reg clk, klk, saat, ses, ses1, ses2, ses3;


reg ml1, ml2, mr1, mr2, mu1, mu2, md1, md2;
reg [1:0] counter;
reg [23:0] ctr, ctra, ctrb, ctrc, cnr;
reg [9:0] countx;
reg [8:0] county;
reg vga_h, vga_v;
reg [3:0] sag_mal;
reg [3:0] sol_mal;
reg ber, sol, sag, alert, biter, kontrol2;
reg [3:0] aa,bb,cc;
reg [9:0] topx;
reg [8:0] topy;
reg [3:0] topyh;
reg [3:0] topxh;
reg [9:0] m1x;
reg [8:0] m1y;
reg [9:0] m2x;
reg [8:0] m2y;
reg a1,a2,a3,a4,a5,a6,a7;
reg b1,b2,b3,b4,b5,b6,b7;
reg c1,c2,c3,c4,c5,c6,c7;
reg w1,w2,w3,w4,w5,w6,w7;
reg e1,e2,e3,e4,e5,e6,e7;
reg vga_R, vga_B, vga_G, vga_R1, vga_B1, vga_G1, vga_R2, vga_B2, vga_G2;

// All Initializations
initial
begin
topyh=1; //2: up ,1:down
topxh=1; //2: left , 1:right
m1x= 7;
m1y= 199;
m2x = 552;
m2y= 201;
topx = 50;
topy = 200;
ml1=0;
ml2=0;
mr1=0;
mr2=0;
mu1=0;
mu2=0;
md1=0;
md2=0;
ses=0;
sag_mal=0;
sol_mal=0;
clk=0;
klk=0;
saat=0;
ses1=0;
ses2=0;
ses3=0;
counter=0;
ctr=0;
ctrc=0;
ctrb=0;
ctra=0;
cnr=0;
alert=0;
biter=0;
aa = 2;
bb = 0;
cc = 3;
kontrol2 = 0;
end
// All clock divisions
// 25MHz , gaming clock(250Hz), real time clock (1Hz), sound effects

// 25 Mhz
always @ (posedge clk_in)
begin
counter = counter+1;
if (counter ==2)
begin
clk=~clk;
counter=0;
end
end

// VGA Synchronizations
always @ (posedge clk)
begin
if (countx<799)
countx=countx+1;
else
begin
countx=0;
if (county< 520)
county=county+1;
else
county=0;
end

if (countx>655 & countx<751)


vga_h = 0;
else
vga_h = 1;

if (county>489 & county<491)


vga_v = 0;
else
vga_v = 1;
end

assign vga_h_sync=vga_h;
assign vga_v_sync=vga_v;

// Gaming clock (klk 250Hz)


always @ (posedge clk)
begin
if (kontrol==0&&kontrol2==0)
begin
ctr = ctr+1;
if (ctr == 50000)
begin
klk=~klk;
ctr=0;
end
end
else if (kontrol==1||kontrol2==1)
begin klk=0; end
end

// Sound Effect 1
always @ (posedge clk)
begin
ctra = ctra+1;
if (ctra == 5000)
begin
ses1=~ses1;
ctra=0;
end
end

// Sound Effect 2
always @ (posedge clk)
begin
ctrb = ctrb+1;
if (ctrb == 2500)
begin
ses2=~ses2;
ctrb=0;
end
end

// Sound Effect 3
always @ (posedge clk)
begin
ctrc = ctrc+1;
if (ctrc == 7500)
begin
ses3=~ses3;
ctrc=0;
end
end

// Real Time Clock (1 Hz)


always @ (posedge klk)
begin
cnr = cnr+1;
if (cnr == 125)
begin
saat=~saat;
cnr=0;
end
end

// border , ball , mullet drawings


wire
border=(county==0)||(county==400)||(((county<140)||(county>260))&&((countx=
=0)||(countx==559)))||((countx==279)&&((county>0)||(county<400)));
wire top=(((countx-topx)*(countx-topx)+(county-topy)*(county-topy))<= 100);
wire m1 = ( m1x-3<countx & countx<m1x+3 & county>m1y-30 & county<m1y+30 );
wire m2 = ( m2x-3<countx & countx<m2x+3 & county>m2y-30 & county<m2y+30 );

// ALL INTERACTIONS in this always block


always @ (posedge klk)
begin
if ((topy == 389)&(topyh==1) ) // lower border interaction
begin topyh <= 2 ; topxh <= topxh; end

else if ((topy == 11)&(topyh==2) ) // upper border interaction


begin topyh <= 1 ;topxh <= topxh; end
else if ((topx >= 548)&(topxh==1)&((topy<140)||(topy>260)) ) // right
border interaction
begin topxh <= 2 ; topyh<=topyh; end

else if ((topx <= 11)&(topxh==2)&((topy<140)||(topy>260)) ) // left


border interaction
begin topxh <= 1 ; topyh<=topyh; end

// mullet1 & ball interactions


else if ( ((topx-m1x<=12)) &((m1y<=topy)&(topy<m1y+38) )&
((topxh==2)||(topxh==0) ) )
begin topxh<=1; topyh<=topyh; end // upper-right

else if ( ((topx-m1x<=12)) &((m1y<=topy)&(topy<m1y+38) )&


((topxh==3)||(topxh==4) ) )
begin topxh<=1; topyh<=1; end // upper-right after goal

else if ( ((topx-m1x<=12)) &((m1y-38<=topy)&(topy<m1y) )&


((topxh==2)||(topxh==0) ))
begin topxh<=1; topyh<=topyh; end // lower-right

else if ( ((topx-m1x<=12)) &((m1y-38<=topy)&(topy<m1y) )&


((topxh==3)||(topxh==4) ))
begin topxh<=1; topyh<=2; end // lower-right after goal

else if ( ((m1x-topx<=12)) &((m1y<topy)&(topy<=m1y+38))& ((topxh==1)


||(topxh==0) ))
begin topxh<=2; topyh<=topyh; end // upper-left

else if ( ((m1x-topx<=12)) &((m1y-38<=topy)&(topy<m1y) )&


(((topxh==1)||(topxh==0) ) ) )
begin topxh<=2; topyh<=topyh; end // lower-left

// mullet2 & ball interactions


else if ( ((topx-m2x<=12)) &((m2y<topy)&(topy<m2y+38) )&
((topxh==2)||(topxh==0)))
begin topxh<=1; topyh<=topyh; end // upper-right

else if ( ((topx-m2x<=12)) &((m2y-38<topy)&(topy<m2y) )& ((topxh==2)


||(topxh==0)))
begin topxh<=1; topyh<=topyh; end // lower-right

else if ( ((m2x-topx<=12)) &((m2y<topy)&(topy<m2y+38))& ((topxh==1)


||(topxh==0)))
begin topxh<=2; topyh<=topyh; end // upper-left

else if ( ((m2x-topx<=12)) &((m2y<=topy)&(topy<=m2y+38))& ((topxh==3)


||(topxh==4)))
begin topxh<=2; topyh<=1; end // upper-left after goal

else if ( ((m2x-topx<=12)) &((m2y-38<=topy)&(topy<m2y) )&


((topxh==1)||(topxh==0)) )
begin topxh<=2; topyh<=topyh; end // lower-left

else if ( ((m2x-topx<=12)) &((m2y-38<=topy)&(topy<m2y) )&


((topxh==3)||(topxh==4) ) )
begin topxh<=2; topyh<=2; end // lower-left after goal

// GOAL!
if ((topx==3)&((topy<260)&(topy>140)))
begin sag_mal<=sag_mal+1; topxh<=3; topyh<=3; m1x<=7; m2x<=552;
m1y<=201; m2y<=201; end

else if ( (topx==558) & (topy<260) & (topy>140) )


begin sol_mal<=sol_mal+1; topxh<=4; topyh<=4; m1x<=7; m2x<=552;
m1y<=201; m2y<=201; end

// ball directions
case (topyh)
1: topy<=topy+1; // goes down
2: topy<=topy-1; // goes up
0: topy<=topy; // no change
3: topy<=201; // after goal initialization
4: topy<=201; // after goal initialization
endcase

case (topxh)
1: topx<= topx+1; // goes right
2: topx<= topx-1; // goes left
0: topx<= topx; // no change
3: topx<= 50; // after goal initialization
4: topx<= 509; // after goal initialization
endcase
// mullet inputs
ml1<=l1;
ml2<=l2;
mr1<=r1;
mr2<=r2;
mu1<=u1;
mu2<=u2;
md1<=d1;
md2<=d2;
// mullet 1 movements
if ((ml1==1)&(m1x>8)) begin m1x<=m1x-1; end // goes left
if ((mr1==1)&(m1x<275)) begin m1x<=m1x+1; end // goes right
if ((mu1==1)&(m1y>40)) begin m1y<=m1y-1; end // goes up
if ((md1==1)&(m1y<360)) begin m1y<=m1y+1; end // goes down
// mullet 2 movements
if ((ml2==1)&(m2x>284)) begin m2x<=m2x-1; end // goes left
if ((mr2==1)&(m2x<551)) begin m2x<=m2x+1; end // goes right
if ((mu2==1)&(m2y>40)) begin m2y<=m2y-1; end // goes up
if ((md2==1)&(m2y<360)) begin m2y<=m2y+1; end // goes down
end
// End of the Interaction and Movements

// Countdown
always @ (posedge saat)
begin
if ((aa!=0)&(biter==0))
begin aa<=aa-1; end
else if((aa==0)&(bb!=0)&(biter==0))
begin aa<=9; bb<=bb-1; end
else if ((aa==0)&(bb==0)&(biter==0))
begin aa<=9; bb<=9; end
if ((bb==0)&(cc!=0)&(aa==0)&(biter==0))
begin bb<=9; cc<=cc-1; end
else if ((bb==0)&(aa==0)&(cc==0)&(biter==0))
begin bb<=9; cc<=0; end
end
/// The End of the Game and the Sound Effects
always @ (posedge clk)
begin
if (biter==1 & sol_mal>sag_mal)
begin sol <= (county>0)&(county<400)& (countx>0) &(countx<559);
ses<=ses1; kontrol2<=1; end //the mullet on the left won
if (biter==1 & sol_mal<sag_mal)
begin sag <= (county>0)&(county<400)& (countx>0) &(countx<559);
ses<=ses2; kontrol2<=1; end // the mullet on the right won
if (biter==1 & sol_mal==sag_mal)
begin ber <= (county>0)&(county<400)& (countx>0) &(countx<559);
kontrol2<=1; end // no winner, score is even
if((topx==50&topy==201&biter==0)||(topx==509& topy==201&biter==0))
begin ses<=ses3; end
if(((topx!=50 & topy!=201) || (topx!=509 & topy!=201))&(biter==0))
begin ses<=0; end
if ((cc==0)&(bb<=0)&((aa<=9)||(aa>=0))& biter==0)
begin alert=(((county>410)||(county<430))&
((countx>220)||(countx<320))); ses<=ses3; end
if(aa==0&bb==0&cc==0)
begin biter<=1; end
end

// Seven Segment Displays

// Countdown cc_bb_aa
always @ (posedge clk)
begin
case (aa)
0: begin
a1 = (county==435 && (countx>330&&countx<345));
a2 = (countx==345 && (county>435&&county<450));
a3 = (countx==345 && (county>450&&county<465));
a4 = (county==465 && (countx>330&&countx<345));
a5 = (countx==330 && (county<465&&county>450));
a6 = (countx==330 && (county<450&&county>435));
a7 = 0;
end
1: begin
a1 = 0;
a2 = (countx==345 && (county>435&&county<450));
a3 = (countx==345 && (county>450&&county<465));
a4 = 0;
a5 = 0;
a6 = 0;
a7 = 0;
end
2: begin
a1 = (county==435 && (countx>330&&countx<345));
a2 = (countx==345 && (county>435&&county<450));
a3 = 0;
a4 = (county==465 && (countx>330&&countx<345));
a5 = (countx==330 && (county<465&&county>450));
a6 = 0;
a7 = (county==450 && (countx>330&&countx<345));
end
3: begin
a1 = (county==435 && (countx>330&&countx<345));
a2 = (countx==345 && (county>435&&county<450));
a3 = (countx==345 && (county>450&&county<465));
a4 = (county==465 && (countx>330&&countx<345));
a5 = 0;
a6 = 0;
a7 = (county==450 && (countx>330&&countx<345));
end
4: begin
a1 = 0;
a2 = (countx==345 && (county>435&&county<450));
a3 = (countx==345 && (county>450&&county<465));
a4 = 0;
a5 = 0;
a6 = (countx==330 && (county<450&&county>435));
a7 = (county==450 && (countx>330&&countx<345));
end
5: begin
a1 = (county==435 && (countx>330&&countx<345));
a2 = 0;
a3 = (countx==345 && (county>450&&county<465));
a4 = (county==465 && (countx>330&&countx<345));
a5 = 0;
a6 = (countx==330 && (county<450&&county>435));
a7 = (county==450 && (countx>330&&countx<345));
end
6: begin
a1 = (county==435 && (countx>330&&countx<345));
a2 = 0;
a3 = (countx==345 && (county>450&&county<465));
a4 = (county==465 && (countx>330&&countx<345));
a5 = (countx==330 && (county<465&&county>450));
a6 = (countx==330 && (county<450&&county>435));
a7 = (county==450 && (countx>330&&countx<345));
end
7: begin
a1 = (county==435 && (countx>330&&countx<345));
a2 = (countx==345 && (county>435&&county<450));
a3 = (countx==345 && (county>450&&county<465));
a4 = 0;
a5 = 0;
a6 = 0;
a7 = 0;
end
8: begin
a1 = (county==435 && (countx>330&&countx<345));
a2 = (countx==345 && (county>435&&county<450));
a3 = (countx==345 && (county>450&&county<465));
a4 = (county==465 && (countx>330&&countx<345));
a5 = (countx==330 && (county<465&&county>450));
a6 = (countx==330 && (county<450&&county>435));
a7 = (county==450 && (countx>330&&countx<345));
end
9: begin
a1 = (county==435 && (countx>330&&countx<345));
a2 = (countx==345 && (county>435&&county<450));
a3 = (countx==345 && (county>450&&county<465));
a4 = (county==465 && (countx>330&&countx<345));
a5 = 0;
a6 = (countx==330 && (county<450&&county>435));
a7 = (county==450 && (countx>330&&countx<345));
end
endcase
end
always @ (posedge clk)
begin
case (bb)
0: begin
b1 = (county==435 && (countx>305&&countx<320));
b2 = (countx==320 && (county>435&&county<450));
b3 = (countx==320 && (county>450&&county<465));
b4 = (county==465 && (countx>305&&countx<320));
b5 = (countx==305 && (county<465&&county>450));
b6 = (countx==305 && (county<450&&county>435));
b7 = 0;
end
1: begin
b1 = 0;
b2 = (countx==320 && (county>435&&county<450));
b3 = (countx==320 && (county>450&&county<465));
b4 = 0;
b5 = 0;
b6 = 0;
b7 = 0;
end
2: begin
b1 = (county==435 && (countx>305&&countx<320));
b2 = (countx==320 && (county>435&&county<450));
b3 = 0;
b4 = (county==465 && (countx>305&&countx<320));
b5 = (countx==305 && (county<465&&county>450));
b6 = 0;
b7 = (county==450 && (countx>305&&countx<320));
end
3: begin
b1 = (county==435 && (countx>305&&countx<320));
b2 = (countx==320 && (county>435&&county<450));
b3 = (countx==320 && (county>450&&county<465));
b4 = (county==465 && (countx>305&&countx<320));
b5 = 0;
b6 = 0;
b7 = (county==450 && (countx>305&&countx<320));
end
4: begin
b1 = 0;
b2 = (countx==320 && (county>435&&county<450));
b3 = (countx==320 && (county>450&&county<465));
b4 = 0;
b5 = 0;
b6 = (countx==305 && (county<450&&county>435));
b7 = (county==450 && (countx>305&&countx<320));
end
5: begin
b1 = (county==435 && (countx>305&&countx<320));
b2 = 0;
b3 = (countx==320 && (county>450&&county<465));
b4 = (county==465 && (countx>305&&countx<320));
b5 = 0;
b6 = (countx==305 && (county<450&&county>435));
b7 = (county==450 && (countx>305&&countx<320));
end
6: begin
b1 = (county==435 && (countx>305&&countx<320));
b2 = 0;
b3 = (countx==320 && (county>450&&county<465));
b4 = (county==465 && (countx>305&&countx<320));
b5 = (countx==305 && (county<465&&county>450));
b6 = (countx==305 && (county<450&&county>435));
b7 = (county==450 && (countx>305&&countx<320));
end
7: begin
b1 = (county==435 && (countx>305&&countx<320));
b2 = (countx==320 && (county>435&&county<450));
b3 = (countx==320 && (county>450&&county<465));
b4 = 0;
b5 = 0;
b6 = 0;
b7 = 0;
end
8: begin
b1 = (county==435 && (countx>305&&countx<320));
b2 = (countx==320 && (county>435&&county<450));
b3 = (countx==320 && (county>450&&county<465));
b4 = (county==465 && (countx>305&&countx<320));
b5 = (countx==305 && (county<465&&county>450));
b6 = (countx==305 && (county<450&&county>435));
b7 = (county==450 && (countx>305&&countx<320));
end
9: begin
b1 = (county==435 && (countx>305&&countx<320));
b2 = (countx==320 && (county>435&&county<450));
b3 = (countx==320 && (county>450&&county<465));
b4 = (county==465 && (countx>305&&countx<320));
b5 = 0;
b6 = (countx==305 && (county<450&&county>435));
b7 = (county==450 && (countx>305&&countx<320));
end
endcase
end

always @ (posedge clk)


begin
case (cc)
0: begin
c1 = (county==435 && (countx>280&&countx<295));
c2 = (countx==295 && (county>435&&county<450));
c3 = (countx==295 && (county>450&&county<465));
c4 = (county==465 && (countx>280&&countx<295));
c5 = (countx==280 && (county<465&&county>450));
c6 = (countx==280 && (county<450&&county>435));
c7 = 0;
end
1: begin
c1 = 0;
c2 = (countx==295 && (county>435&&county<450));
c3 = (countx==295 && (county>450&&county<465));
c4 = 0;
c5 = 0;
c6 = 0;
c7 = 0;
end
2: begin
c1 = (county==435 && (countx>280&&countx<295));
c2 = (countx==295 && (county>435&&county<450));
c3 = 0;
c4 = (county==465 && (countx>280&&countx<295));
c5 = (countx==280 && (county<465&&county>450));
c6 = 0;
c7 = (county==450 && (countx>280&&countx<295));
end
3: begin
c1 = (county==435 && (countx>280&&countx<295));
c2 = (countx==295 && (county>435&&county<450));
c3 = (countx==295 && (county>450&&county<465));
c4 = (county==465 && (countx>280&&countx<295));
c5 = 0;
c6 = 0;
c7 = (county==450 && (countx>280&&countx<295));
end
4: begin
c1 = 0;
c2 = (countx==295 && (county>435&&county<450));
c3 = (countx==295 && (county>450&&county<465));
c4 = 0;
c5 = 0;
c6 = (countx==280 && (county<450&&county>435));
c7 = (county==450 && (countx>280&&countx<295));
end
5: begin
c1 = (county==435 && (countx>280&&countx<295));
c2 = 0;
c3 = (countx==295 && (county>450&&county<465));
c4 = (county==465 && (countx>280&&countx<295));
c5 = 0;
c6 = (countx==280 && (county<450&&county>435));
c7 = (county==450 && (countx>280&&countx<295));
end
6: begin
c1 = (county==435 && (countx>280&&countx<295));
c2 = 0;
c3 = (countx==295 && (county>450&&county<465));
c4 = (county==465 && (countx>280&&countx<295));
c5 = (countx==280 && (county<465&&county>450));
c6 = (countx==280 && (county<450&&county>435));
c7 = (county==450 && (countx>280&&countx<295));
end
7: begin
c1 = (county==435 && (countx>280&&countx<295));
c2 = (countx==295 && (county>435&&county<450));
c3 = (countx==295 && (county>450&&county<465));
c4 = 0;
c5 = 0;
c6 = 0;
c7 = 0;
end
8: begin
c1 = (county==435 && (countx>280&&countx<295));
c2 = (countx==295 && (county>435&&county<450));
c3 = (countx==295 && (county>450&&county<465));
c4 = (county==465 && (countx>280&&countx<295));
c5 = (countx==280 && (county<465&&county>450));
c6 = (countx==280 && (county<450&&county>435));
c7 = (county==450 && (countx>280&&countx<295));
end
9: begin
c1 = (county==435 && (countx>280&&countx<295));
c2 = (countx==295 && (county>435&&county<450));
c3 = (countx==295 && (county>450&&county<465));
c4 = (county==465 && (countx>280&&countx<295));
c5 = 0;
c6 = (countx==280 && (county<450&&county>435));
c7 = (county==450 && (countx>280&&countx<295));
end
endcase
end

// The Scores sol_mal and sag_mal


always @ (posedge clk)
begin
case (sol_mal)
0: begin
w1 = (county==435 && (countx>10&&countx<25));
w2 = (countx==25 && (county>435&&county<450));
w3 = (countx==25 && (county>450&&county<465));
w4 = (county==465 && (countx>10&&countx<25));
w5 = (countx==10 && (county<465&&county>450));
w6 = (countx==10 && (county<450&&county>435));
w7 = 0;
end
1: begin
w1 = 0;
w2 = (countx==25 && (county>435&&county<450));
w3 = (countx==25 && (county>450&&county<465));
w4 = 0;
w5 = 0;
w6 = 0;
w7 = 0;
end
2: begin
w1 = (county==435 && (countx>10&&countx<25));
w2 = (countx==25 && (county>435&&county<450));
w3 = 0;
w4 = (county==465 && (countx>10&&countx<25));
w5 = (countx==10 && (county<465&&county>450));
w6 = 0;
w7 = (county==450 && (countx>10&&countx<25));
end
3: begin
w1 = (county==435 && (countx>10&&countx<25));
w2 = (countx==25 && (county>435&&county<450));
w3 = (countx==25 && (county>450&&county<465));
w4 = (county==465 && (countx>10&&countx<25));
w5 = 0;
w6 = 0;
w7 = (county==450 && (countx>10&&countx<25));
end
4: begin
w1 = 0;
w2 = (countx==25 && (county>435&&county<450));
w3 = (countx==25 && (county>450&&county<465));
w4 = 0;
w5 = 0;
w6 = (countx==10 && (county<450&&county>435));
w7 = (county==450 && (countx>10&&countx<25));
end
5: begin
w1 = (county==435 && (countx>10&&countx<25));
w2 = 0;
w3 = (countx==25 && (county>450&&county<465));
w4 = (county==465 && (countx>10&&countx<25));
w5 = 0;
w6 = (countx==10 && (county<450&&county>435));
w7 = (county==450 && (countx>10&&countx<25));
end
6: begin
w1 = (county==435 && (countx>10&&countx<25));
w2 = 0;
w3 = (countx==25 && (county>450&&county<465));
w4 = (county==465 && (countx>10&&countx<25));
w5 = (countx==10 && (county<465&&county>450));
w6 = (countx==10 && (county<450&&county>435));
w7 = (county==450 && (countx>10&&countx<25));
end
7: begin
w1 = (county==435 && (countx>10&&countx<25));
w2 = (countx==25 && (county>435&&county<450));
w3 = (countx==25 && (county>450&&county<465));
w4 = 0;
w5 = 0;
w6 = 0;
w7 = 0;
end
8: begin
w1 = (county==435 && (countx>10&&countx<25));
w2 = (countx==25 && (county>435&&county<450));
w3 = (countx==25 && (county>450&&county<465));
w4 = (county==465 && (countx>10&&countx<25));
w5 = (countx==10 && (county<465&&county>450));
w6 = (countx==10 && (county<450&&county>435));
w7 = (county==450 && (countx>10&&countx<25));
end
9: begin
w1 = (county==435 && (countx>10&&countx<25));
w2 = (countx==25 && (county>435&&county<450));
w3 = (countx==25 && (county>450&&county<465));
w4 = (county==465 && (countx>10&&countx<25));
w5 = 0;
w6 = (countx==10 && (county<450&&county>435));
w7 = (county==450 && (countx>10&&countx<25));
end
endcase
end

always @ (posedge clk)


begin
case (sag_mal)
0: begin
e1 = (county==435 && (countx>535&&countx<550));
e2 = (countx==550 && (county>435&&county<450));
e3 = (countx==550 && (county>450&&county<465));
e4 = (county==465 && (countx>535&&countx<550));
e5 = (countx==535 && (county<465&&county>450));
e6 = (countx==535 && (county<450&&county>435));
e7 = 0;
end
1: begin
e1 = 0;
e2 = (countx==550 && (county>435&&county<450));
e3 = (countx==550 && (county>450&&county<465));
e4 = 0;
e5 = 0;
e6 = 0;
e7 = 0;
end
2: begin
e1 = (county==435 && (countx>535&&countx<550));
e2 = (countx==550 && (county>435&&county<450));
e3 = 0;
e4 = (county==465 && (countx>535&&countx<550));
e5 = (countx==535 && (county<465&&county>450));
e6 = 0;
e7 = (county==450 && (countx>535&&countx<550));
end
3: begin
e1 = (county==435 && (countx>535&&countx<550));
e2 = (countx==550 && (county>435&&county<450));
e3 = (countx==550 && (county>450&&county<465));
e4 = (county==465 && (countx>535&&countx<550));
e5 = 0;
e6 = 0;
e7 = (county==450 && (countx>535&&countx<550));
end
4: begin
e1 = 0;
e2 = (countx==550 && (county>435&&county<450));
e3 = (countx==550 && (county>450&&county<465));
e4 = 0;
e5 = 0;
e6 = (countx==535 && (county<450&&county>435));
e7 = (county==450 && (countx>535&&countx<550));
end
5: begin
e1 = (county==435 && (countx>535&&countx<550));
e2 = 0;
e3 = (countx==550 && (county>450&&county<465));
e4 = (county==465 && (countx>535&&countx<550));
e5 = 0;
e6 = (countx==535 && (county<450&&county>435));
e7 = (county==450 && (countx>535&&countx<550));
end
6: begin
e1 = (county==435 && (countx>535&&countx<550));
e2 = 0;
e3 = (countx==550 && (county>450&&county<465));
e4 = (county==465 && (countx>535&&countx<550));
e5 = (countx==535 && (county<465&&county>450));
e6 = (countx==535 && (county<450&&county>435));
e7 = (county==450 && (countx>535&&countx<550));
end
7: begin
e1 = (county==435 && (countx>535&&countx<550));
e2 = (countx==550 && (county>435&&county<450));
e3 = (countx==550 && (county>450&&county<465));
e4 = 0;
e5 = 0;
e6 = 0;
e7 = 0;
end
8: begin
e1 = (county==435 && (countx>535&&countx<550));
e2 = (countx==550 && (county>435&&county<450));
e3 = (countx==550 && (county>450&&county<465));
e4 = (county==465 && (countx>535&&countx<550));
e5 = (countx==535 && (county<465&&county>450));
e6 = (countx==535 && (county<450&&county>435));
e7 = (county==450 && (countx>535&&countx<550));
end
9: begin
e1 = (county==435 && (countx>535&&countx<550));
e2 = (countx==550 && (county>435&&county<450));
e3 = (countx==550 && (county>450&&county<465));
e4 = (county==465 && (countx>535&&countx<550));
e5 = 0;
e6 = (countx==535 && (county<450&&county>435));
e7 = (county==450 && (countx>535&&countx<550));
end
endcase
end

// Color Outputs
wire
R=border||top||a1||a2||a3||a4||a5||a6||a7||b1||b2||b3||b4||b5||b6||b7||c1||
c2||c3||c4||c5||c6||c7;
wire
R1=border||top||a1||a2||a3||a4||a5||a6||a7||b1||b2||b3||b4||b5||b6||b7||c1|
|c2||c3||c4||c5||c6||c7;
wire
R2=border||top||a1||a2||a3||a4||a5||a6||a7||b1||b2||b3||b4||b5||b6||b7||c1|
|c2||c3||c4||c5||c6||c7;

wire G = border||m1||top||w1||w2||w3||w4||w5||w6||w7||sol||ber;
wire G1= border||m1||top||w1||w2||w3||w4||w5||w6||w7||sol||ber;
wire
G2=border||m1||top||alert||a1||a2||a3||a4||a5||a6||a7||b1||b2||b3||b4||b5||
b6||b7||c1||c2||c3||c4||c5||c6||c7||w1||w2||w3||w4||w5||w6||w7;

wire B = border||m2||top||e1||e2||e3||e4||e5||e6||e7||sag||ber;
wire B1= border||m2||top||e1||e2||e3||e4||e5||e6||e7||sag||ber;
wire
B2=border||m2||top||alert||a1||a2||a3||a4||a5||a6||a7||b1||b2||b3||b4||b5||
b6||b7||c1||c2||c3||c4||c5||c6||c7||e1||e2||e3||e4||e5||e6||e7;

always @ (posedge clk)


begin
vga_R <= R;
vga_R1 <= R1;
vga_R2 <= R2;
vga_G <= G;
vga_G1 <= G1;
vga_G2 <= G2;
vga_B <= B;
vga_B1 <= B1;
vga_B2 <= B2;
end
endmodule

/// FINISH

Vous aimerez peut-être aussi