Following code may be useful for students or enthusiasts who are trying to design a voting machine. It has been successfully simulated as well as implemented on Spartan 3 xc3s400 FPGA. If you are having any doubts regarding following code then post a comment. I will try my best to answer the questions.
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Chaitannya Supe
// Create Date: 09:31:19 03/08/2015
// Design Name: Electronic Voting Machine
// Module Name: evm
// Target Devices: Xilinx Spartan 3 XCS400-PQ208
// Tool versions: Xilinx ISE 12.2, 14.7
// Description: This is simple Voting machine code in which total 3 partys were considered.
// A voter can vote to any of the parties only one at a time. If a voter votes two parties
// at a time then that vote will be invalid. This code has been successfully simulated as well as
// implemented on Spartan 3 xc3s400-4pq208 device.
//
// Additional Comments: To register a vote, operate a voter_switch and then press push button to register
// a vote. This operation was chosen to simplify a coding and get better understanding
// of a voting machine on FPGA.
//////////////////////////////////////////////////////////////////////////////////
module evm(clk,voter_switch,PB,voting_en,opled,invalid,dout);
input voting_en,PB,clk;//voting process will start when vote_en is on
input [2:0]voter_switch;
output [6:0]dout;//Max no. of votes = 127
output reg [2:0]opled;//opled[0]=party1 led, opled[1]=party2 led, opled[2]=party3 led
output reg invalid;//invalid vote indicator led
//counters to count each party votes
reg [6:0]cnt_reg1=0;//party1
reg [6:0]cnt_nxt1=0;//party1
reg [6:0]cnt_reg2=0;//party2
reg [6:0]cnt_nxt2=0;//party2
reg [6:0]cnt_reg3=0;//party3
reg [6:0]cnt_nxt3=0;//party3
reg PB_reg1;
reg PB_reg2;
reg [15:0] PB_cnt;
reg PB_state;
//debounce circuit to detect only one rising edge of push button PB(Refer http://www.fpga4fun.com/Debouncer2.html for more information on debounce circuit)
always @(posedge clk)
PB_reg1 <= PB;
always @(posedge clk)
PB_reg2 <= PB_reg1;
wire PB_idle = (PB_state==PB_reg2);
wire PB_cnt_max = &PB_cnt; // true when all bits of PB_cnt are 1's
always @(posedge clk)
if(PB_idle)
PB_cnt <= 0; // idle state i.e. PB_cnt will not increment
else
begin
PB_cnt <= PB_cnt + 16'd1;
if(PB_cnt_max)
PB_state <= ~PB_state; // if the counter is maximum, PB changes
end
assign PB_down = ~PB_idle & PB_cnt_max & ~PB_state;
//counter for party1 votes
always@(posedge PB_down)
if(voter_switch == 3'b001 && voting_en == 1'b1)
begin
cnt_reg1 <= cnt_nxt1;
end
always@(*)
begin
cnt_nxt1 = cnt_reg1 + 1;
end
//Counter for party2 votes
always@(posedge PB_down)
if(voter_switch == 3'b010 && voting_en == 1'b1)
begin
cnt_reg2 <= cnt_nxt2;
end
always@(*)
begin
cnt_nxt2 = cnt_reg2 + 1;
end
//Counter for party3 votes
always@(posedge PB_down)
if(voter_switch == 3'b100 && voting_en == 1'b1)
begin
cnt_reg3 <= cnt_nxt3;
end
always@(*)
begin
cnt_nxt3 = cnt_reg3 + 1;
end
//Final count i.e. total number of votes
assign dout = cnt_reg1 + cnt_reg2 + cnt_reg3;
//relation of "voter_switch" with "opled" & "invalid"
always@(*)
if(voting_en)
case(voter_switch)
3'b100 : begin
opled = 3'b100;
invalid = 1'b0;
end
3'b010 : begin
opled = 3'b010;
invalid = 1'b0;
end
3'b001 : begin
opled = 3'b001;
invalid = 1'b0;
end
3'b011 : begin
opled = 3'b000;
invalid = 1'b1;
end
3'b110 : begin
opled = 3'b000;
invalid = 1'b1;
end
3'b101 : begin
opled = 3'b000;
invalid = 1'b1;
end
3'b111 : begin
opled = 3'b000;
invalid = 1'b1;
end
3'b000 : begin
opled = 3'b000;
invalid = 1'b0;
end
default : begin
opled = 3'b000;
invalid = 1'b0;
end
endcase
endmodule