1 | /* |
---|
2 | * This code implements a game of ping pong (table tennis) between 2 players, with |
---|
3 | * a slight twist: each player puts a ball into play at the same time. There can |
---|
4 | * be an indefinite delay from the time one player hits a ball until the time that |
---|
5 | * the other player returns it. If both balls are in play, then both players |
---|
6 | * always hit each ball at the same instant. |
---|
7 | * |
---|
8 | * While both balls are in play, exactly one player may choose not to return his |
---|
9 | * ball. This leaves one ball in play. If just one ball is in play, the ball |
---|
10 | * should remain in play forever. |
---|
11 | */ |
---|
12 | |
---|
13 | typedef enum {BALL, NO_BALL} player_status; |
---|
14 | typedef enum {HIT, NO_HIT} action_type; |
---|
15 | |
---|
16 | module ping_pong(clk); |
---|
17 | input clk; |
---|
18 | |
---|
19 | /* signal declarations */ |
---|
20 | action_type wire action_A, action_B; |
---|
21 | player_status wire state_A, state_B; |
---|
22 | |
---|
23 | /* the ping pong players */ |
---|
24 | player player_A(clk, action_B, action_A, state_A); |
---|
25 | player player_B(clk, action_A, action_B, state_B); |
---|
26 | |
---|
27 | never_no_balls nnb(clk, state_A, state_B); |
---|
28 | infinitely_often_hit ioh(clk, action_A); |
---|
29 | |
---|
30 | endmodule |
---|
31 | |
---|
32 | |
---|
33 | /* |
---|
34 | * Two state process. If the player doesn't have the ball (state NO_BALL) and the |
---|
35 | * opponent hits the ball, then go to state BALL. If the player has the ball, then |
---|
36 | * if he doesn't hit the ball, then he remains in state BALL. If he hits the ball, |
---|
37 | * and the opponent doesn't also hit the ball, then go to state NO_BALL. |
---|
38 | */ |
---|
39 | module player(clk, opponent, me, state); |
---|
40 | input clk; |
---|
41 | input opponent; |
---|
42 | output me; |
---|
43 | output state; |
---|
44 | |
---|
45 | action_type wire opponent, me, random; |
---|
46 | player_status reg state; |
---|
47 | |
---|
48 | initial state = BALL; |
---|
49 | |
---|
50 | /* set the value of the output of the player */ |
---|
51 | |
---|
52 | assign random = $ND(HIT, NO_HIT); |
---|
53 | assign me = (state == BALL) ? random : NO_HIT; |
---|
54 | |
---|
55 | always @(posedge clk) begin |
---|
56 | case(state) |
---|
57 | BALL: |
---|
58 | begin |
---|
59 | if ((me == HIT) && (opponent == NO_HIT)) |
---|
60 | state = NO_BALL; |
---|
61 | end |
---|
62 | |
---|
63 | NO_BALL: |
---|
64 | begin |
---|
65 | if (opponent == HIT) |
---|
66 | state = BALL; |
---|
67 | end |
---|
68 | |
---|
69 | default:; |
---|
70 | endcase; |
---|
71 | end |
---|
72 | endmodule |
---|
73 | |
---|
74 | /* |
---|
75 | * If it's ever the case that neither player has a ball, then go to state BAD |
---|
76 | * and stay there. |
---|
77 | */ |
---|
78 | typedef enum {GOOD, BAD} prop1_status; |
---|
79 | |
---|
80 | module never_no_balls(clk, state_A, state_B); |
---|
81 | input clk; |
---|
82 | input state_A; |
---|
83 | input state_B; |
---|
84 | |
---|
85 | player_status wire state_A, state_B; |
---|
86 | prop1_status reg state; |
---|
87 | |
---|
88 | initial state = GOOD; |
---|
89 | |
---|
90 | always @(posedge clk) begin |
---|
91 | case(state) |
---|
92 | GOOD: |
---|
93 | begin |
---|
94 | if ((state_A == NO_BALL) && (state_B == NO_BALL)) |
---|
95 | state = BAD; |
---|
96 | end |
---|
97 | |
---|
98 | BAD: |
---|
99 | begin |
---|
100 | state = BAD; |
---|
101 | end |
---|
102 | |
---|
103 | default:; |
---|
104 | endcase; |
---|
105 | end |
---|
106 | endmodule |
---|
107 | |
---|
108 | |
---|
109 | /* |
---|
110 | * If player does not hit the ball now, then he will sometime in the future. |
---|
111 | */ |
---|
112 | typedef enum {OKAY, PENDING} prop2_status; |
---|
113 | |
---|
114 | module infinitely_often_hit(clk, player_action); |
---|
115 | input clk; |
---|
116 | input player_action; |
---|
117 | |
---|
118 | action_type wire player_action; |
---|
119 | prop2_status reg state; |
---|
120 | |
---|
121 | initial state = OKAY; |
---|
122 | |
---|
123 | always @(posedge clk) begin |
---|
124 | case(state) |
---|
125 | OKAY: |
---|
126 | begin |
---|
127 | if (player_action == NO_HIT) |
---|
128 | state = PENDING; |
---|
129 | end |
---|
130 | |
---|
131 | PENDING: |
---|
132 | begin |
---|
133 | if (player_action == HIT) |
---|
134 | state = OKAY; |
---|
135 | end |
---|
136 | |
---|
137 | default:; |
---|
138 | endcase; |
---|
139 | end |
---|
140 | endmodule |
---|
141 | |
---|