Verilog Dice Game (Craps) on a BASYS 2 Board Craps is a dice game in which players roll a pair of dice and bet on the outcome of the roll or a series of rolls. The main idea behind this t his Verilog electronic version of craps is to have two counters that are used to simulate the roll of the dice. Each one o ne of these counters counts in the sequence 1, 2, 3, 4, 5, 6 and then keeps repeating this pattern. After the roll of the dice, the values va lues in the two counters which ranges between 2 and 12 is summed up. Using this sum and a set of rules for the game, a winner w inner can be determined. In order to win on the first roll, roll, a player p layer must obtain a sum of 7 or 11. Otherwise, if a sum of 2, 3, o r 12 is obtained, the player loses and all other sums become the ³point´. If the sum equals the ³point´ on the second or o r subsequent roll, then the player wins. Otherwise, the player loses if the sum equals 7. The game is then continued in this fashion until the p layer wins or loses. The inputs to the dice game come from two push buttons, a roll button and a reset button. The reset button is used to initiate a new game g ame and pushing the ro ll button after a reset mimics the rolling of the dice. The ro lling lling of the dice d ice is synchronously triggered using a clock pu lse generated by the BASYS 2 board. The frequency of the clock provided on the BASYS 2 board on which this game was tested had a frequency of 50 MHz. This frequency was scaled down using a clock divider resulting in a per iod of 6.4 ms During each roll, the face values va lues obtained are multiplexed onto two t wo 7-segment Light Emitting Diode (LED) displays on the BASYS 2 board. In the event that a player loses after a roll, an ³L´ is displayed. Otherwise, a ³U´ is displayed to indicate a win. If the player doesn¶t win or o r lose during the first or subsequent rolls, an ³A´ is d isplayed to indicate that the player p layer can roll again. If the game is reset, a ³0´ is displayed. In addition to displaying a ll these different states, the 7segment LEDS are multiplexed to display the face values of the dice during dur ing and after a roll. Game Flow chart (image credit: Jim Plusquellic): Plusquellic):
Top level module: module Crap_shoot(out1, out2, clk, reset, point, roll, win, match, lose, roll_again, rolling, blank, D_left, D_right, sum, segments, digit); input clk, reset, roll;
output output output output output
win, lose, match, roll_again, rolling, blank; [3:0] point; [2:0] D_left, D_right; [3:0] sum; reg [3:0] out1, out2;
reg [7:0] worl; output reg [7:0] segments; output reg [3:0] digit; reg le; wire [2:0] lsb; wire [2:0] msb; parameter parameter parameter parameter parameter parameter wire reg wire reg reg reg wire
S_idle = 0; S_rolling = 1; S_pause = 2; S_repeat = 3; S_lose = 4; S_win = 5;
match, rolling, roll_again, win, lose, save_point; [2:0] D_left, D_right; [3:0] sum = D_left + D_right; [2:0] state, next_state; [3:0] point; [1:0] choice; clk_segments;
initial begin choice <= 0; le <= 1; end latch latch
my_latch_1(lsb, D_right, le); my_latch_2(msb, D_left, le);
always @( posedge clk_segments or posedge reset ) if (reset) begin D_left <= 1; D_right <= 1; end else begin if (D_left < 6) D_left <= D_left + 1; else D_left <= 1; if (D_left == 6 && D_right < 6) D_right <= D_right + 1; else if (D_left == 6 && D_right == 6) D_right <= 1; end
// Rolling
assign match = (sum == point); // Scoring assign roll_again = (state == S_pause && !roll); assign rolling = ((state == S_rolling && roll) || (state == S_repeat && roll)); assign save_point = ((state == S_rolling) && !roll && sum != 2 && sum != 3 && sum != 12 && sum != 7 && sum != 11);
assign win = (state == S_win); assign lose = (state == S_lose); assign blank = (point < 2); always @( posedge save_point or posedge reset ) if (reset) point <= 0; else point <= sum;
// Control
always @(posedge clk_segments or posedge reset) begin le <= 1; if (!roll && !reset) le <= 0; if (reset) begin worl <= 8'b00000011; state <= S_idle; le <= 1; end else begin state <= next_state; if (next_state == S_win) begin worl <= 8'b10000011; le <= 0; end else if (next_state == S_lose) begin worl <= 8'b11100011; le <= 0; end else if(next_state == S_pause) worl <= 8'b00010001; else worl <= 8'b00010001; end end
//multiplexor clock_divider divider(.cin(clk), .cout(clk_segments)); always @ (posedge clk_segments) begin case (choice) 0: begin choice <= 1; digit <= 4'b0111; segments <= worl; end 1: begin choice <= 2; digit <= 4'b1101; case (lsb) 1 : begin segments <= 8'b10011111; end 2 : begin segments <= 8'b00100101; end 3 : begin segments <= 8'b00001101; end 4 : begin segments <= 8'b10011001;
end 5 : begin segments end 6 : begin segments end default : segments end endcase end
<= 8'b01001001;
<= 8'b01000001; begin <= 8'b11111101;
2: begin choice <= 0; digit <= 4'b1110; case (msb) 1 : begin segments <= 8'b10011111; end 2 : begin segments <= 8'b00100101; end 3 : begin segments <= 8'b00001101; end 4 : begin segments <= 8'b10011001; end 5 : begin segments <= 8'b01001001; end 6 : begin segments <= 8'b01000001; end default : begin segments <= 8'b11111101; end endcase end endcase end //always //end multiplexor always @(state or sum or roll or match) case (state) S_idle: if (roll) next_state <= S_rolling; else next_state <= S_idle; S_rolling: if (roll) next_state <= S_rolling; else if (sum == 2 || sum == 3 || sum == 12) next_state <= S_lose; else
if (sum == 7 || sum == 11) next_state <= S_win; else next_state <= S_pause; S_pause: if (roll) next_state <= S_repeat; else next_state <= S_pause; S_repeat: if (roll) next_state <= S_repeat; else if (match) next_state <= S_win; else if (sum == 7) next_state <= S_lose; else next_state <= S_pause; S_win:
next_state <= S_win;
S_lose: next_state <= S_lose; endcase endmodule //latch to latch face-values of dice module latch(dout, din, le); input [2:0] din; output [2:0] dout; input le; // latch enable reg dout; always @(din or le) if (le == 1'b1) dout = din; endmodule // latch
Clock divider: module
clock_divider ( cin, cout );
input cin; output cout; parameter timeconst = 20;//constant integer count0; integer count1; integer count2; integer count3; reg d; reg cout; always @ (posedge cin ) begin begin count0 <= (count0 + 1); if ((count0 == timeconst)) begin count0 <= 0; count1 <= (count1 + 1);
end else if ((count1 == timeconst)) begin count1 <= 0; count2 <= (count2 + 1); end else if ((count2 == timeconst)) begin count2 <= 0; count3 <= (count3 + 1); end else if ((count3 == timeconst)) begin count3 <= 0; d <= ~ (d); end end cout <= d; end endmodule
User Constraint File (UCF): ################################################### #turns on each digit NET 'digit<3>' LOC = 'F12'; NET 'digit<2>' LOC = 'J12'; NET 'digit<1>' LOC = 'M13'; NET 'digit<0>' LOC = 'K14'; #turns on each segment NET 'segments<7>' LOC = 'L14'; NET 'segments<6>' LOC = 'H12'; NET 'segments<5>' LOC = 'N14'; NET 'segments<4>' LOC = 'N11'; NET 'segments<3>' LOC = 'P12'; NET 'segments<2>' LOC = 'L13'; NET 'segments<1>' LOC = 'M12'; NET 'segments<0>' LOC = 'N13'; #reset button NET 'reset' LOC = 'C11'; #roll button NET 'roll' LOC = 'G12'; #clock NET 'clk' LOC = 'B8'; ###################################################