Search code examples
verilogfpgakeypad

4X4 Keypad on a Spartan6 FPGA


I've been stuck on this for awhile. For my project, I'm trying to make a digital lock with keypad entry. I have a 4X4 keypad, but I'm only using 3 of the columns. Currently, I'm just trying to get the keypad to work properly. When I compile it, my default case works but nothing will change when i press any of the buttons.

`timescale 1ns / 1ps

module KeypadShit(input  M_CLOCK,     // FPGA clock
        input ROW1, ROW2, ROW3, ROW4, COL1, COL2, COL3, 
       output [3:0] IO_SSEGD, // IO Board Seven Segment Digits          
       output reg [7:0] IO_SSEG,  // 7=dp, 6=g, 5=f,4=e, 3=d,2=c,1=b, 0=a
       output IO_SSEG_COL);   // Seven segment column

assign IO_SSEGD = 4'b0111;      
assign IO_SSEG_COL = 1; // deactivate the column displays

reg [4:0] state;
reg R1, R2, R3, R4, C1, C2, C3;

initial
begin
R1 = 1;
R2 = 1;
R3 = 1;
R4 = 1;
C1 = 1;
C2 = 1;
C3 = 1;
end

always @* 
begin
R1 = ROW1;
R2 = ROW2;
R3 = ROW3;
R4 = ROW4;
C1 = COL1;
C2 = COL2;
C3 = COL3;
end


//////keypad reads 0s so set all to default 1, and send 0's to row and read columns
always @(*)
begin
if( (R1==0) && (C1==0))
state <= 1; //1
else if( (R1==0) && (C2==0))
state <= 2; //2
else if( (R1==0) && (C3==0))
state <= 3;//3
//////////
else if( (R2==0) && (C1==0))
state <= 4; //4
else if( (R2==0) && (C2==0))
state <= 5;//5
else if( (R2==0) && (C3==0))
state <= 6;//6
/////////////
else if( (R3==0) && (C1==0))
state <= 7;//7
else if( (R3==0) && (C2==0))
state <= 8;//8
else if( (R3==0) && (C3==0))
state <= 9;//9
////////////
else if( (R4==0) && (C2==0))
state <= 0;//0
//////////////
else state <= 15;
end

always @(state)
begin

case (state)
0:IO_SSEG = 7'b1000000;//0 
1:IO_SSEG = 7'b1111001;//1
2:IO_SSEG = 7'b0100100;//2
3:IO_SSEG = 7'b0110000;//3
4:IO_SSEG = 7'b0011001;//4
5:IO_SSEG = 7'b0010010;//5
6:IO_SSEG = 7'b0000010;//6
7:IO_SSEG = 7'b1111000;//7
8:IO_SSEG = 7'b0000000;//8
9:IO_SSEG = 7'b0011000;//9
15:IO_SSEG = 7'b0101010;//default random light sequence

endcase
end


endmodule

and my .ucf file:

# IO Board Display Segment a
NET "IO_SSEG<0>" LOC = P102; #a
NET "IO_SSEG<1>" LOC = P105; #b
NET "IO_SSEG<2>" LOC = P101; #c
NET "IO_SSEG<3>" LOC = P97;  #d
NET "IO_SSEG<4>" LOC = P98;  #e
NET "IO_SSEG<5>" LOC = P100; #f
NET "IO_SSEG<6>" LOC = P104; #g
#NET    "IO_SSEG<7>" LOC = P99;  #decimal point

#====================================================
# IO Board Seven Segment Digits
#NET    "IO_SSEGD<0>"   LOC = P92; 
#NET    "IO_SSEGD<1>"   LOC = P93;
#NET    "IO_SSEGD<2>"   LOC = P84;
#NET    "IO_SSEGD<3>"   LOC = P88;
#====================================================
# IO Board Seven Segment Display Colon
NET "IO_SSEG_COL"   LOC = P87; 
#====================================================
# IO Board Pushbutton Switches 
# Pushbutton Determines which Digit to Enable
#NET    "IO_PB<3>"      LOC = P80   |  PULLUP; 
#NET    "IO_PB<2>"      LOC = P81   |  PULLUP; 
#NET    "IO_PB<1>"      LOC = P78   |  PULLUP;
#NET    "IO_PB<0>"      LOC = P79   |  PULLUP;

#====================================================
# IO Board Dip Switchs
#NET    "IO_DSW<7>"     LOC = P55   |  PULLUP; 
#NET    "IO_DSW<6>"     LOC = P56   |  PULLUP;
#NET    "IO_DSW<5>"     LOC = P57   |  PULLUP;
#NET    "IO_DSW<4>"     LOC = P58   |  PULLUP;
#NET    "IO_DSW<3>"     LOC = P61   |  PULLUP;
#NET    "IO_DSW<2>"     LOC = P62   |  PULLUP;
#NET    "IO_DSW<1>"     LOC = P66   |  PULLUP;
#NET    "IO_DSW<0>"     LOC = P67   |  PULLUP;
#====================================================
# Clock signal 
NET "M_CLOCK" LOC = P123;

NET "ROW1" LOC = P118; // 0N0
NET "ROW2" LOC = P120; // 0N1
NET "ROW3" LOC = P126; // 0N2
NET "ROW4" LOC = P131; // 0N3
NET "COL1" LOC = P133   |  PULLUP; // 0N4 
NET "COL2" LOC = P137   |  PULLUP; // 0N5
NET "COL3" LOC = P139   |  PULLUP; // 0N6

I'm using a .ucf file from another one of my projects, which is why there's so much commented out.

In my head, my code works as follows:

R1-R4 and C1-C3 are variables that start out as 1s, because the keyboard scans for shorted pins. Those variables are set equal to ROW1-4 and COL1-3, because I can't set inputs to have initial values obviously. Then I have an always block that checks to see which pins are shorted, and sets the state according to which button that should be.

Then the finite state machine checks the state and displays the number pressed to the 7segment on my IO board.

In my ucf file, I have some set to be pullups, as my professor told me that was necessary but I have no idea what that actually changes. At one point he mentioned that some of the rows or columns need to be set as inputs and some as outputs, but again I have no idea what to do with that information, and I can't find much that is helping me wrap my head around this.

Thanks in advance for any help.

Cody

Can anyone figure out what I'm doing wrong?


Solution

  • The finite state machine can never change own state, because clock signal is missing.

    Please see example: https://www.altera.com/support/support-resources/design-examples/design-software/verilog/ver_statem.html

    ...
    always @(posedge clk //ATTENTION
    if ...
      state <= 1
    else
      state <=2
    ...