You are on page 1of 17

Verilog

Descriptions of
Digital Systems

Electronic Lock
//
// Electronic combinational lock
//
module lock(seg7,key, valid_key, col, row, mclk, resetL) ;
output
[0:6] seg7;
output
[0:3] col ;
output
[3:0] key ;
output
valid_key ;
input
resetL ,mclk ;
input
[0:3] row ;
wire

clk ;

// Divide master clock down to 100 Hz


// clock_divider u0(clk, mclk, resetL) ;
assign clk = mclk ;
// Keyboard scan
// When valid_key goes active, the key register contains last key entered
kb_scan

u1(key, valid_key, col, row, clk, resetL) ;

// Has someone entered a valid combination?


// User interface is a seven segment display
validate
endmodule

u2(seg7, key, valid_key, clk, resetL) ;

Keyboard Scanner Module

Kb_scan
//
// Module to scan matrix keyboard
// FSM to scan the keyboard
//
module kb_scan(key, valid_key, col, row, clk, resetL) ;
output
output
output
input
input

[3:0] key ;
valid_key ;
[0:3] col ;
[0:3] row ;
clk, resetL ;

reg
reg
reg
reg
reg

[0:3] row_reg;
[2:0] nstate, pstate ;
valid, valid_key ;
[3:0] key, key_code ;
[0:3] col ;

wire

kd ;

parameter

st_0 = 3'd0, st_1 = 3'd1, st_2 = 3'd2,


st_3 = 3'd3, st_4 = 3'd4, st_5 = 3'd5,
st_6 = 3'd6 ;

// synchronize row info with the clock


always @(negedge clk or negedge resetL) begin
if (~resetL) row_reg <= 4'b0000 ;
else row_reg <= row ;
end

Kb_scan (Continued)
// if any key is down, the kd signal will be high
assign

kd = | row_reg ;

// state register process for FSM


always @(negedge clk or negedge resetL) begin
if (~resetL) pstate <= st_0 ;
else pstate <= nstate ;
end
// state transition and output process
always @(kd or pstate) begin
valid = 0 ;
col = 4'b1111 ;
case (pstate)
st_0: if (~kd) nstate = st_0 ;
else begin
nstate = st_1 ;
col = 4'b1000 ;
end
st_1:

if (~kd) begin
nstate = st_2
col = 4'b0100
end
else begin
nstate = st_5
col = 4'b1000
valid = 1 ;
end

;
;
;
;

Kb_scan (Continued, more)


st_2:

st_3:

if (~kd) begin
nstate = st_3
col = 4'b0010
end
else begin
nstate = st_5
col = 4'b0100
valid = 1 ;
end
if (~kd) begin
nstate = st_4
col = 4'b0001
end
else begin
nstate = st_5
col = 4'b0010
valid = 1 ;
end

;
;

;
;
;
;

st_4:

if (~kd) nstate = st_0 ;


else begin
nstate = st_5 ;
col = 4'b0001 ;
valid = 1 ;
end

st_5:

if (kd) nstate = st_5 ;


else nstate = st_0 ;

default: nstate = st_0 ;


endcase
end

;
;

Kb_scan (Continued, even more)


// Encode key using row and col info
always @(row_reg or col) begin
casex ({row_reg, col})
8'b1xxx_1000 : key_code = 4'b0001
8'b1xxx_0100 : key_code = 4'b0010
8'b1xxx_0010 : key_code = 4'b0011
8'b1xxx_0001 : key_code = 4'b1010
8'b01xx_1000 : key_code = 4'b0100
8'b01xx_0100 : key_code = 4'b0101
8'b01xx_0010 : key_code = 4'b0110
8'b01xx_0001 : key_code = 4'b1011
8'b001x_1000 : key_code = 4'b0111
8'b001x_0100 : key_code = 4'b1000
8'b001x_0010 : key_code = 4'b1001
8'b001x_0001 : key_code = 4'b1100
8'b0001_1000 : key_code = 4'b1110
8'b0001_0100 : key_code = 4'b0000
8'b0001_0010 : key_code = 4'b1111
8'b0001_0001 : key_code = 4'b1101
default: key_code = 4'd0 ;
endcase
end

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

// Register the key_code


always @(posedge clk or negedge resetL) begin
if (~resetL) key <= 4'b0000;
else if (valid) key <= key_code ;
end
// Delay valid_key signal
always @(negedge clk or negedge resetL) begin
if (~resetL) valid_key <= 0 ;
else valid_key <= valid ;
end

Validate Module

Validate
//
// Module to validate entry code being entered
//
module validate(seg7, key, valid_key, clk, resetL) ;
output
[0:6] seg7 ;
input
valid_key, resetL, clk ;
input
[3:0] key ;
wire

pound_sign, Z, AeqB, EQ ;

reg
reg
reg
reg
reg
reg
reg

eqQ ;
[1:0]
[0:6]
[1:0]
[2:0]
[3:0]
[0:6]

pstate, nstate ;
seg7 ;
digit_sel ;
cnt ;
B ;
display_reg_inp ;

// control signals for data path


reg
reg

init, dec_cnt, ld_eq, ld_display ;


[1:0] display_sel ;

// some useful constants


parameter

st_0 = 2'b00, st_1 = 2'b01,


st_2 = 2'b10, st_3 = 2'b11 ;

Validate (Continued)
parameter

two = 4'b0010, zero = 4'b0000,


eight = 4'b1000, one = 4'b0001 ;

parameter

blank = 7'b0000000 ,
open = 7'b1110111 ,
error = 7'b1101101 ;

// generate pound_sign present signal


assign

pound_sign = (key == 4'b1111) ;

// mux stored digits in combination to be checked


always @(digit_sel) begin
case (digit_sel)
2'b00 : B = one ;
2'b01 : B = eight ;
2'b10 : B = zero ;
2'b11 : B = two ;
endcase
end
// Magnitude comparator
assign

AeqB = (key == B) ;

Validate (Continued, more)


// Equality checker
assign

EQ = AeqB & eqQ ;

always @(posedge clk or negedge resetL) begin


if (~resetL) eqQ <= 1 ;
else if (init) eqQ <= 1 ;
else if (ld_eq) eqQ <= EQ ;
end
// seven segment display MUX and register
always @(display_sel) begin
case (display_sel)
2'b00 : display_reg_inp
2'b01 : display_reg_inp
2'b10 : display_reg_inp
default: display_reg_inp
endcase
end

=
=
=
=

blank ;
open ;
error ;
blank ;

always @(posedge clk or negedge resetL) begin


if (~resetL) seg7 <= blank ;
else if (ld_display) seg7 <= display_reg_inp ;
end
// 3-bit counter and terminal count output
always @(negedge resetL or posedge clk) begin
if (~resetL) cnt <= 4 ;
else if (dec_cnt) cnt <= cnt - 1 ;
else if (init) cnt <= 4 ;
end
assign

Z = (cnt == 3'b000) ;

Validate (Continued, even more)


// Create digit select from cnt output
always @(cnt) begin
case (cnt)
4 : digit_sel = 2'b00 ;
3 : digit_sel = 2'b01 ;
2 : digit_sel = 2'b10 ;
1 : digit_sel = 2'b11 ;
default: digit_sel = 2'b00 ;
endcase
end
// state register process for FSM
always @(negedge clk or negedge resetL) begin
if (~resetL) pstate <= st_0 ;
else pstate <= nstate ;
end
// state transition process for FSM
always @(pstate or valid_key) begin
init = 0 ;
ld_eq = 0 ;
dec_cnt = 0 ;
ld_display = 0 ;
display_sel = 0 ;
case (pstate)
st_0 : begin
nstate = st_1 ;
ld_display = 1 ;
init = 1 ;
end

Validate (Continued, one more)


st_1 :

begin
if (Z) begin
nstate = st_3 ;
ld_display = 1 ;
if (eqQ) display_sel = 1 ;
else display_sel = 2 ;
end
else begin
if (valid_key) begin
ld_eq = 1 ;
nstate = st_2 ;
end
else nstate = st_1 ;
end
end

st_2 :

begin
nstate = st_1 ;
dec_cnt = 1 ;
end

st_3 :

if (pound_sign) nstate = st_0 ;


else nstate = st_3 ;
default: nstate = st_0 ;
endcase
end
endmodule

Lock Testbench
//
// Testbench for electronic combinational lock
//
`timescale
1 ms / 1 us
module lock_tb ;
wire
wire
wire

[0:6] seg7 ;
[0:3] col ;
[3:0] key ;

reg
reg
reg

[0:3] row ;
mclk ;
resetL ;

// Instantiate the lock


lock

uut(seg7, key, valid_key, col, row, mclk, resetL) ;

// Clock generator
// Clock period is 10 msec
initial begin
mclk = 1 ;
forever #10 mclk = ~mclk ;
end

Lock Testbench (Continued)


// Apply test vectors
initial begin
#0
begin
resetL = 0 ;
row = 4'b0000 ;
end
#10

resetL = 1 ;

// key stroke is (row #, col #)


// 1st key stroke (1,1) = "1"
#200
wait(col == 4'b1111) row = 4'b1000 ;
wait(col == 4'b1000) row = 4'b1000 ;

#200

row = 4'b0000 ;

// 2nd key stroke (3,2) = "8"


#200
wait(col == 4'b1111) row = 4'b0010 ;
wait(col == 4'b1000) row = 4'b0000 ;
wait(col == 4'b0100) row = 4'b0010 ;
#200

row = 4'b0000 ;

Lock Testbench (Continued, more)


// 3rd key stroke (4,2) = "0"
#200
wait(col == 4'b1111) row = 4'b0001 ;
wait(col == 4'b1000) row = 4'b0000 ;
wait(col == 4'b0100) row = 4'b0001 ;
#200

row = 4'b0000 ;

// 4th key stroke (1,2) = "2"


#200
wait(col == 4'b1111) row = 4'b1000 ;
wait(col == 4'b1000) row = 4'b0000 ;
wait(col == 4'b0100) row = 4'b1000 ;
#200

row = 4'b0000 ;

// 5th key stroke (4,3) = "#"


#200
wait(col
wait(col
wait(col
wait(col
#200

==
==
==
==

row = 4'b0000 ;

4'b1111)
4'b1000)
4'b0100)
4'b0010)

row
row
row
row

=
=
=
=

4'b0001
4'b0000
4'b0000
4'b0001

;
;
;
;

Lock Testbench (Continued, even more)


// Log signal info
//
//
//
//
//

initial begin
$dumpfile("./lock.dmp") ;
$dumpflush ;
$dumpvars(3, lock_tb) ;
end

// Print out key code whenver valid_key goes active


always @(posedge valid_key) begin
$strobe("Key is %b and seg7 is %b", key, seg7) ;
end
endmodule

You might also like