至(zhì)簡設計(jì)系(xì)列_電(diàn)子密碼鎖
--作者(zhě):肖肖肖
--案(àn)例作者(zhě):WB_Yih
本(běn)文(wén)为(wèi)明(míng)德揚原創及(jí)录(lù)用(yòng)文(wén)章(zhāng),轉(zhuǎn)载請注明(míng)出(chū)处!
1.1 總(zǒng)體(tǐ)設計(jì)
1.1.1 概述
随着生(shēng)活質(zhì)量(liàng)的(de)不(bù)斷提(tí)高(gāo),加強(qiáng)家(jiā)庭防盜安(ān)全(quán)變(biàn)得非(fēi)常重(zhòng)要(yào),但傳統機(jī)械鎖的(de)構造过(guò)于(yú)簡單,很容易被(bèi)打(dǎ)開(kāi),從而(ér)降低了(le)安(ān)全(quán)性(xìng)。數字(zì)密碼鎖因(yīn)为(wèi)它(tā)的(de)保密性(xìng)很高(gāo),安(ān)全(quán)系(xì)數也(yě)非(fēi)常高(gāo),再加上(shàng)其不(bù)需要(yào)攜带(dài)避免了(le)丢失的(de)可(kě)能(néng),省(shěng)去(qù)了(le)因(yīn)鑰匙丢失而(ér)需要(yào)換鎖的(de)麻(má)煩,受到(dào)了(le)越来(lái)越多(duō)的(de)人(rén)的(de)欢迎。随看(kàn)人(rén)们(men)对(duì)高(gāo)科技産品也(yě)越来(lái)越推崇,在(zài)當今社会(huì)科技的(de)高(gāo)度(dù)集中(zhōng)和(hé)創新,人(rén)们(men)对(duì)日(rì)常生(shēng)活中(zhōng)保護自(zì)身(shēn)及(jí)财産安(ān)全(quán)的(de)物(wù)品非(fēi)常追捧,对(duì)其安(ān)全(quán)性(xìng)的(de)要(yào)求也(yě)非(fēi)常的(de)高(gāo)。为(wèi)了(le)达(dá)到(dào)人(rén)们(men)对(duì)鎖具安(ān)全(quán)性(xìng)的(de)高(gāo)要(yào)求,加強(qiáng)鎖具的(de)安(ān)全(quán)保密性(xìng),用(yòng)密碼鎖来(lái)取(qǔ)代(dài)傳統機(jī)械鎖的(de)鎖具是(shì)必然趨勢。數字(zì)密碼鎖比傳統機(jī)械鎖具更(gèng)加的(de)安(ān)全(quán)。在(zài)本(běn)案(àn)例的(de)設計(jì)过(guò)程中(zhōng),應(yìng)用(yòng)了(le)至(zhì)簡設計(jì)法、狀态機(jī)模板應(yìng)用(yòng)等,在(zài)經(jīng)过(guò)逐步改進(jìn)、調試等一(yī)系(xì)列工作之後(hòu),最(zuì)終(zhōng)达(dá)到(dào)了(le)設計(jì)目标(biāo)。
基于(yú)明(míng)德揚至(zhì)簡設計(jì)法和(hé)明(míng)德揚設計(jì)規範,設計(jì)一(yī)个(gè)基于(yú)FPGA的(de)密碼鎖、并将數值顯示在(zài)數碼管(guǎn)上(shàng),然後(hòu)根(gēn)據(jù)輸入(rù)的(de)鍵值判斷密碼是(shì)否正(zhèng)确。
1.1.2 設計(jì)目标(biāo)
实現(xiàn)電(diàn)子密碼鎖的(de)功能(néng),具體(tǐ)功能(néng)要(yào)求如(rú)下(xià):
1. 密碼4位,初始密碼2345。
2. 密碼鎖狀态:LOCKED和(hé)OPEN,初始狀态为(wèi)LOCKED。
1) 當在(zài)LOCKED狀态时(shí),連(lián)續两(liǎng)次(cì)輸入(rù)正(zhèng)确密碼,狀态變(biàn)为(wèi)OPEN狀态。當輸入(rù)錯誤密碼时(shí)(包(bāo)括第(dì)一(yī)次(cì)就(jiù)輸入(rù)錯誤;或(huò)者(zhě)第(dì)一(yī)次(cì)輸入(rù)正(zhèng)确,第(dì)二(èr)次(cì)輸入(rù)錯誤的(de)情(qíng)況),數碼管(guǎn)顯示ERROR 2秒(miǎo)後(hòu)重(zhòng)新顯示原来(lái)的(de)狀态(LOCKED)。
2) 當在(zài)OPEN狀态时(shí),一(yī)次(cì)輸入(rù)錯誤密碼,狀态變(biàn)为(wèi)LOCKED狀态。當輸入(rù)正(zhèng)确密碼时(shí),數碼管(guǎn)无顯示,10秒(miǎo)後(hòu)重(zhòng)新顯示原来(lái)的(de)狀态(OPEN)。
3) 不(bù)管(guǎn)在(zài)何狀态,當輸入(rù)4位密碼或(huò)者(zhě)某幾(jǐ)位密碼,但未按下(xià)确認鍵,并超过(guò)10S时(shí),返回(huí)原来(lái)的(de)狀态。(即輸入(rù)密碼超时(shí),返回(huí)原狀态)
对(duì)于(yú)點(diǎn)撥開(kāi)發(fà)板,使用(yòng)矩阵(zhèn)按鍵輸入(rù)(本(běn)文(wén)以(yǐ)點(diǎn)撥603開(kāi)發(fà)板为(wèi)例)。
对(duì)于(yú)Mp801開(kāi)發(fà)板,密碼顯示及(jí)确認:无論在(zài)OPEN,還(huán)是(shì)LOCKED狀态下(xià),均可(kě)以(yǐ)通(tòng)过(guò)撥碼開(kāi)關(guān)輸入(rù)密碼。當有(yǒu)撥碼開(kāi)關(guān)撥動(dòng)时(shí),數碼管(guǎn)當前(qián)顯示的(de)OPEN或(huò)LOCKED消失,并顯示當前(qián)輸入(rù)的(de)密碼,暫未輸入(rù)的(de)密碼位不(bù)顯示。4位密碼輸入(rù)完畢後(hòu),再撥動(dòng)撥碼開(kāi)關(guān)时(shí)視为(wèi)无效輸入(rù),當前(qián)顯示的(de)密碼不(bù)改變(biàn)。4位密碼輸入(rù)完畢後(hòu),按下(xià)确認鍵後(hòu),系(xì)統判斷密碼是(shì)否正(zhèng)确。
撥碼開(kāi)關(guān)及(jí)按鍵:初始狀态下(xià),撥碼開(kāi)關(guān)全(quán)部(bù)往下(xià)撥。當撥碼開(kāi)關(guān)向(xiàng)上(shàng)撥後(hòu),再向(xiàng)下(xià)撥(回(huí)到(dào)初始狀态),表(biǎo)示一(yī)个(gè)數字(zì)的(de)有(yǒu)效輸入(rù)。按鍵每按下(xià)一(yī)次(cì)(会(huì)自(zì)動(dòng)弹起),为(wèi)一(yī)次(cì)有(yǒu)效輸入(rù)(複位/确認)。
1.1.3 系(xì)統結構框图(tú)
系(xì)統結構框图(tú)如(rú)下(xià)图(tú)所(suǒ)示:
1.1.4模块(kuài)功能(néng)按鍵檢测模块(kuài)实現(xiàn)功能(néng)
1、 檢测按鍵的(de)數值
控制模块(kuài)实現(xiàn)功能(néng)
1、 对(duì)接收(shōu)到(dào)的(de)按鍵數值進(jìn)行判斷和(hé)控制对(duì)應(yìng)的(de)密碼鎖狀态,实現(xiàn)对(duì)輸入(rù)密碼的(de)正(zhèng)誤判斷和(hé)对(duì)密碼鎖的(de)開(kāi)啟和(hé)閉合控制。
數碼管(guǎn)顯示模块(kuài)实現(xiàn)功能(néng)
1、 顯示輸入(rù)的(de)密碼數值;
2、 顯示當前(qián)密碼鎖的(de)狀态(開(kāi)啟狀态或(huò)者(zhě)閉鎖狀态);
3、 提(tí)示密碼輸入(rù)錯誤的(de)狀态。
1.1.5頂层信(xìn)号(hào)
1.1.6參考代(dài)碼
下(xià)面(miàn)是(shì)使用(yòng)工程的(de)頂层代(dài)碼:
module top_mdyPwdlock_keyscan( clk , rst_n , key_col , key_row , seg_sel , segment ); input clk ; input rst_n ; input [3:0] key_col ; output[5:0] seg_sel ; output[7:0] segment ; output[3:0] key_row ; wire [5:0] seg_sel ; wire [7:0] segment ; wire [3:0] key_row ; wire [3:0] key_out ; wire key_vld ; wire [6*5-1:0] seg_dout ; wire [5:0] seg_dout_vld ; key_scan u_key_scan( .clk (clk ), .rst_n (rst_n ), .key_col (key_col ), .key_row (key_row ), .key_out (key_out ), .key_vld (key_vld ) ); control u_ctrl( .clk (clk ), .rst_n (rst_n ), .key_num (key_out ), .key_vld (key_vld ), .seg_dout (seg_dout ), .seg_dout_vld (seg_dout_vld ) ); seg_display u_segment( .clk (clk ), .rst_n (rst_n ), .din (seg_dout ), .din_vld (seg_dout_vld ), .segment (segment ), .seg_sel (seg_sel ) ); endmodule
1.2.1接口(kǒu)信(xìn)号(hào)
1.2.2 設計(jì)思(sī)路(lù)
在(zài)前(qián)面(miàn)的(de)案(àn)例中(zhōng)已經(jīng)有(yǒu)矩阵(zhèn)按鍵檢测模块(kuài)的(de)介紹,所(suǒ)以(yǐ)这(zhè)里(lǐ)不(bù)在(zài)过(guò)多(duō)介紹,詳细(xì)介紹請看(kàn)下(xià)方(fāng)鍊(liàn)接:
http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=310&highlight=%BE%D8%D5%F3
其中(zhōng),按鍵的(de)功能(néng)面(miàn)板如(rú)下(xià)图(tú)所(suǒ)示:
1.2.3參考代(dài)碼
module key_scan(
clk ,
rst_n ,
key_col,
key_row,
key_out,
key_vld
);
parameter KEY_W = 4 ;
parameter CHK_COL = 0 ;
parameter CHK_ROW = 1 ;
parameter DELAY = 2 ;
parameter WAIT_END = 3 ;
parameter COL_CNT = 16;
parameter TIME_20MS= 1000000;
input clk ;
input rst_n ;
input [3:0] key_col;
output key_vld;
output[3:0] key_out;
output[KEY_W-1:0] key_row;
reg [3:0] key_out;
reg [KEY_W-1:0] key_row;
reg key_vld;
reg [3:0] key_col_ff0;
reg [3:0] key_col_ff1;
reg [1:0] key_col_get;
wire shake_flag ;
reg shake_flag_ff0;
reg[3:0] state_c;
reg [19:0] shake_cnt;
reg[3:0] state_n;
reg [1:0] row_index;
reg[15:0] row_cnt;
wire chk_col2chk_row ;
wire chk_row2delay ;
wire delay2wait_end ;
wire wait_end2chk_col;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
key_col_ff0 <= 4'b1111;
key_col_ff1 <= 4'b1111;
end
else begin
key_col_ff0 <= key_col ;
key_col_ff1 <= key_col_ff0;
end
end
wire add_shake_cnt ;
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
shake_cnt <= 0;
end
else if(add_shake_cnt) begin
if(shake_flag)
shake_cnt <= 0;
else
shake_cnt <= shake_cnt+1 ;
end
end
assign add_shake_cnt = key_col_ff1!=4'hf;
assign shake_flag = add_shake_cnt && shake_cnt == TIME_20MS-1 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
state_c <= CHK_COL;
end
else begin
state_c <= state_n;
end
end
always @(*)begin
case(state_c)
CHK_COL: begin
if(shake_flag && shake_flag_ff0==1'b0)begin
state_n = CHK_ROW;
end
else begin
state_n = CHK_COL;
end
end
CHK_ROW: begin
if(row_index==3 && row_cnt==0)begin
state_n = DELAY;
end
else begin
state_n = CHK_ROW;
end
end
DELAY : begin
if(row_cnt==0)begin
state_n = WAIT_END;
end
else begin
state_n = DELAY;
end
end
WAIT_END: begin
if(key_col_ff1==4'hf)begin
state_n = CHK_COL;
end
else begin
state_n = WAIT_END;
end
end
default: state_n = CHK_COL;
endcase
end
assign chk_col2chk_row = shake_flag && shake_flag_ff0 ==1'b0;
assign chk_row2delay = row_index==3 && row_cnt==0;
assign delay2wait_end = row_cnt==0;
assign wait_end2chk_col= key_col_ff1==4'hf;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
key_row <= 4'b0;
end
else if(state_c==CHK_ROW)begin
key_row <= ~(1'b1 << row_index);
end
else begin
key_row <= 4'b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
row_index <= 0;
end
else if(state_c==CHK_ROW)begin
if(row_cnt==0)begin
if(row_index==3)
row_index <= 0;
else
row_index <= row_index + 1;
end
end
else begin
row_index <= 0;
end
end
wire add_row_cnt ;
wire end_row_cnt ;
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
row_cnt <= COL_CNT;
end
else if(add_row_cnt) begin
if(end_row_cnt)
row_cnt <= COL_CNT;
else
row_cnt <= row_cnt-1 ;
end
else begin
row_cnt <= COL_CNT;
end
end
assign add_row_cnt = state_c==CHK_ROW || state_c==DELAY;
assign end_row_cnt = add_row_cnt && row_cnt == 0 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
shake_flag_ff0 <= 1'b0;
end
else begin
shake_flag_ff0 <= shake_flag;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
key_col_get <= 0;
end
else if(state_c==CHK_COL && shake_flag==1'b1 && shake_flag_ff0==1'b0) begin
if(key_col_ff1==4'b1110)
key_col_get <= 0;
else if(key_col_ff1==4'b1101)
key_col_get <= 1;
else if(key_col_ff1==4'b1011)
key_col_get <= 2;
else
key_col_get <= 3;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
key_out <= 0;
end
else if(state_c==CHK_ROW && row_cnt==0)begin
key_out <= {row_index,key_col_get};
end
else begin
key_out <= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
key_vld <= 1'b0;
end
else if(state_c==CHK_ROW && row_cnt==0 && key_col_ff1[key_col_get]==1'b0)begin
key_vld <= 1'b1;
end
else begin
key_vld <= 1'b0;
end
end
endmodue
1.3 控制模块(kuài)設計(jì)
1.3.1接口(kǒu)信(xìn)号(hào)
1.3.2設計(jì)思(sī)路(lù)
- 狀态機(jī)架構
本(běn)模块(kuài)的(de)主(zhǔ)要(yào)功能(néng)是(shì)根(gēn)據(jù)輸入(rù)的(de)按鍵信(xìn)息進(jìn)行不(bù)同(tóng)狀态的(de)判斷和(hé)切(qiè)換當前(qián)工作狀态。根(gēn)據(jù)項目功能(néng)要(yào)求,一(yī)共(gòng)有(yǒu)四(sì)種(zhǒng)工作狀态:密碼鎖開(kāi)啟狀态(open)、密碼鎖閉合狀态(clocked)、輸入(rù)密碼狀态(password)和(hé)提(tí)示輸入(rù)錯誤狀态(error)。
以(yǐ)下(xià)为(wèi)本(běn)模块(kuài)的(de)狀态跳轉(zhuǎn)图(tú):
複位後(hòu),狀态機(jī)進(jìn)入(rù)LOCKED的(de)狀态,即初始狀态为(wèi)LOCKED;
在(zài)LOCKED狀态下(xià):
A. 有(yǒu)按鍵按下(xià),跳到(dào)PASSWORD狀态;
B. 否則,保持(chí)LOCKED狀态不(bù)變(biàn);
在(zài)OPEN狀态下(xià):
A. 有(yǒu)按鍵按下(xià),跳到(dào)PASSWORD狀态;
B. 否則,保持(chí)OPEN狀态不(bù)變(biàn);
在(zài)PASSWORD狀态下(xià):
A. 有(yǒu)密碼輸入(rù)但超过(guò)10秒(miǎo)沒(méi)有(yǒu)确認,跳到(dào)原来(lái)的(de)LOCKED狀态或(huò)者(zhě)OPEN狀态;
B. 密碼正(zhèng)确輸入(rù)并确認两(liǎng)次(cì),跳到(dào)OPEN狀态;
C. 密碼錯誤輸入(rù)并确認,跳到(dào)ERROR狀态;
D. 否則,保持(chí)PASSWORD狀态不(bù)變(biàn);
在(zài)ERROR狀态下(xià):
A. 提(tí)示輸入(rù)錯誤2秒(miǎo),跳到(dào)LOCKED狀态;
B. 否則,保持(chí)ERROR狀态不(bù)變(biàn);
无論當前(qián)处于(yú)什麼(me)狀态,只(zhī)要(yào)不(bù)滿足狀态間(jiān)的(de)跳轉(zhuǎn)条(tiáo)件(jiàn)就(jiù)跳到(dào)LOCKED狀态。
- 計(jì)數器架構
本(běn)模块(kuài)的(de)某些狀态跳轉(zhuǎn)之間(jiān)存在(zài)一(yī)定(dìng)的(de)时(shí)間(jiān)間(jiān)隔,根(gēn)據(jù)項目功能(néng)要(yào)求,一(yī)共(gòng)有(yǒu)两(liǎng)種(zhǒng)时(shí)間(jiān)的(de)間(jiān)隔:10秒(miǎo)的(de)等待輸入(rù)时(shí)間(jiān)間(jiān)隔和(hé)2秒(miǎo)的(de)顯示提(tí)示时(shí)間(jiān)間(jiān)隔。
以(yǐ)下(xià)为(wèi)計(jì)數器的(de)架構示意(yì)图(tú):
10秒(miǎo)計(jì)數器cnt_10s_nvld:用(yòng)于(yú)計(jì)算10秒(miǎo)的(de)时(shí)間(jiān)。加一(yī)条(tiáo)件(jiàn)为(wèi)state_c==PASSWORD,表(biǎo)示進(jìn)入(rù)密碼輸入(rù)狀态就(jiù)開(kāi)始計(jì)數。結束(shù)条(tiáo)件(jiàn)为(wèi)數500_000_000个(gè),系(xì)統时(shí)鐘(zhōng)为(wèi)50M,一(yī)个(gè)时(shí)鐘(zhōng)周期(qī)为(wèi)20ns,500_000_000个(gè)时(shí)鐘(zhōng)周期(qī)就(jiù)是(shì)10秒(miǎo)。
2秒(miǎo)計(jì)數器cnt_2s:用(yòng)于(yú)計(jì)算2秒(miǎo)的(de)时(shí)間(jiān)。加一(yī)条(tiáo)件(jiàn)为(wèi)state_c==ERROR,表(biǎo)示進(jìn)入(rù)提(tí)示輸入(rù)錯誤狀态就(jiù)開(kāi)始計(jì)數。結束(shù)条(tiáo)件(jiàn)为(wèi)數100_000_000个(gè),系(xì)統时(shí)鐘(zhōng)为(wèi)50M,一(yī)个(gè)时(shí)鐘(zhōng)周期(qī)为(wèi)20ns,100_000_000个(gè)时(shí)鐘(zhōng)周期(qī)就(jiù)是(shì)2秒(miǎo)。
1.3.3參考代(dài)碼
module control(
clk ,
rst_n ,
key_num ,
key_vld ,
seg_dout ,
seg_dout_vld
);
parameter PASSWORD_INI = 16'h2345 ;
parameter CHAR_O = 5'h10 ;
parameter CHAR_P = 5'h11 ;
parameter CHAR_E = 5'h12 ;
parameter CHAR_N = 5'h13 ;
parameter CHAR_L = 5'h14 ;
parameter CHAR_C = 5'h15 ;
parameter CHAR_K = 5'h16 ;
parameter CHAR_D = 5'h17 ;
parameter CHAR_R = 5'h18 ;
parameter NONE_DIS = 5'h1F ;
parameter C_10S_WID = 29 ;
parameter C_10S_NUM = 500_000_000 ;
parameter C_2S_WID = 27 ;
parameter C_2S_NUM = 100_000_000 ;
parameter C_PWD_WID = 3 ;
input clk ;
input rst_n ;
input [3:0] key_num ;
input key_vld ;
output[6*5-1:0] seg_dout ;
output[5:0] seg_dout_vld ;
reg [6*5-1:0] seg_dout ;
wire [5:0] seg_dout_vld ;
reg [1:0] state_c ;
reg [1:0] state_n ;
reg lock_stata_flag ;
reg password_correct_twice ;
reg [C_2S_WID-1:0] cnt_2s ;
reg [C_10S_WID-1:0] cnt_10s_nvld ;
reg [C_PWD_WID-1:0] cnt_password ;
reg [15:0] password ;
parameter LOCKED = 2'b00 ;
parameter OPEN = 2'b01 ;
parameter PASSWORD = 2'b10 ;
parameter ERROR = 2'b11 ;
//current state
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state_c <= LOCKED;
end
else begin
state_c <= state_n;
end
end
//next state and the condition of state LOCKEDtransition
always@(*)begin
case(state_c)
LOCKED:begin
if(locked2password_switch)begin
state_n = PASSWORD;
end
else begin
state_n = state_c;
end
end
OPEN:begin
if(open2password_switch)begin
state_n = PASSWORD;
end
else begin
state_n = state_c;
end
end
PASSWORD:begin
if(password2locked_switch0)begin
state_n = LOCKED;
end
else if(password2open_switch0 || password2open_switch1)begin
state_n = OPEN;
end
else if(password2error_switch || password2locked_switch1)begin
state_n = ERROR;
end
else begin
state_n = state_c;
end
end
ERROR:begin
if(error2locked_switch0 )begin
state_n = LOCKED;
end
else begin
state_n = state_c;
end
end
default:begin
state_n = LOCKED;
end
endcase
end
assign locked2password_switch = state_c==LOCKED && lock_stata_flag && key_num<10 && key_vld;
assign open2password_switch = state_c==OPEN && !lock_stata_flag && key_num<10 && key_vld;
assign password2locked_switch0 = state_c==PASSWORD && lock_stata_flag && end_cnt_10s_nvld;
assign password2locked_switch1 = state_c==PASSWORD && lock_stata_flag && confirm && password!=PASSWORD_INI ;//TO ERROR
assign password2open_switch0 = state_c==PASSWORD && lock_stata_flag && confirm && password==PASSWORD_INI && password_correct_twice;
assign password2open_switch1 = state_c==PASSWORD && !lock_stata_flag && end_cnt_10s_nvld;
assign password2error_switch = state_c==PASSWORD && !lock_stata_flag && confirm && password!=PASSWORD_INI;
assign error2locked_switch0 = state_c==ERROR && end_cnt_2s;
//lock_stata_flag
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
lock_stata_flag <= 1;
end
else if(password2locked_switch0 || password2locked_switch1 || error2locked_switch0)begin
lock_stata_flag <= 1;
end
else if(password2open_switch0 || password2open_switch1 )begin
lock_stata_flag <= 0;
end
end
//cnt_10s_nvld
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt_10s_nvld <= 0;
end
else if(end_cnt_10s_nvld)begin
cnt_10s_nvld <= 0;
end
else if(add_cnt_10s_nvld)begin
cnt_10s_nvld <= cnt_10s_nvld + 1;
end
end
assign add_cnt_10s_nvld = state_c==PASSWORD;
assign end_cnt_10s_nvld = add_cnt_10s_nvld && cnt_10s_nvld==C_10S_NUM-1;
//confirm
assign confirm = key_num==10 && key_vld;
//password_correct_twice
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
password_correct_twice <= 0;
end
else if(state_c==PASSWORD && lock_stata_flag && confirm && password==PASSWORD_INI && !password_correct_twice)begin
password_correct_twice <= 1;
end
else if(password2locked_switch0 || password2locked_switch1 || password2open_switch0 || password2open_switch1 || password2error_switch)begin
password_correct_twice <= 0;
end
end
//cnt_2s
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt_2s <= 0;
end
else if(end_cnt_2s )begin
cnt_2s <= 0;
end
else if(add_cnt_2s )begin
cnt_2s <= cnt_2s + 1;
end
end
assign add_cnt_2s = state_c==ERROR;
assign end_cnt_2s = add_cnt_2s && cnt_2s==C_2S_NUM-1;
//seg_dout
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
seg_dout <= 0;
end
else if(state_c==OPEN)begin
seg_dout <= {NONE_DIS,NONE_DIS,CHAR_O,CHAR_P,CHAR_E,CHAR_N};
end
else if(state_c==LOCKED)begin
seg_dout <= {CHAR_L,CHAR_O,CHAR_C,CHAR_K,CHAR_E,CHAR_D};
end
else if(state_c==ERROR)begin
seg_dout <= {NONE_DIS,CHAR_E,CHAR_R,CHAR_R,CHAR_O,CHAR_R};
end
else if(state_c==PASSWORD)begin
if(cnt_password==0)
seg_dout <= {NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS};
else if(cnt_password==1)
seg_dout <= {NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,{1'b0,password[3:0]}};
else if(cnt_password==2)
seg_dout <= {NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,{1'b0,password[7:4]},{1'b0,password[3:0]}};
else if(cnt_password==3)
seg_dout <= {NONE_DIS,NONE_DIS,NONE_DIS,{1'b0,password[11:8]},{1'b0,password[7:4]},{1'b0,password[3:0]}};
else if(cnt_password==4)
seg_dout <= {NONE_DIS,NONE_DIS,{1'b0,password[15:12]},{1'b0,password[11:8]},{1'b0,password[7:4]},{1'b0,password[3:0]}};
end
end
//seg_dout_vld
assign seg_dout_vld = 6'b11_1111;
//cnt_password
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt_password <= 0;
end
else if(end_cnt_password)begin
cnt_password <= 0;
end
else if(add_cnt_password)begin
cnt_password <= cnt_password + 1;
end
end
assign add_cnt_password = state_c!=ERROR && key_num<10 && key_vld && cnt_password<4;
assign end_cnt_password = confirm || end_cnt_10s_nvld;
//password
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
password <= 16'h0000;
end
else if(add_cnt_password)begin
password <= {password[11:0],key_num};
end
end
endmodule
1.4 數碼管(guǎn)顯示模块(kuài)設計(jì)
1.4.1接口(kǒu)信(xìn)号(hào)
1.4.2設計(jì)思(sī)路(lù)
在(zài)前(qián)面(miàn)的(de)案(àn)例中(zhōng)已經(jīng)有(yǒu)數碼管(guǎn)顯示的(de)介紹,所(suǒ)以(yǐ)这(zhè)里(lǐ)不(bù)在(zài)过(guò)多(duō)介紹,詳细(xì)介紹請看(kàn)下(xià)方(fāng)鍊(liàn)接:
http://fpgabbs.com/forum.php?mod=viewthread&tid=1085&fromuid=100105
其中(zhōng),數碼管(guǎn)顯示的(de)數值和(hé)英文(wén)字(zì)母对(duì)應(yìng)图(tú)像如(rú)下(xià)图(tú)所(suǒ)示:
1.4.3參考代(dài)碼
module seg_display(
clk ,
rst_n ,
din ,
din_vld ,
segment ,
seg_sel
);
parameter SEGMENT_NUM = 6 ;
parameter W_DATA = 5 ;
parameter SEGMENT_WID = 8 ;
parameter TIME_300US = 15_000 ;
parameter SEG_DATA_0 = 7'b100_0000 ;
parameter SEG_DATA_1 = 7'b111_1001 ;
parameter SEG_DATA_2 = 7'b010_0100 ;
parameter SEG_DATA_3 = 7'b011_0000 ;
parameter SEG_DATA_4 = 7'b001_1001 ;
parameter SEG_DATA_5 = 7'b001_0010 ;
parameter SEG_DATA_6 = 7'b000_0010 ;
parameter SEG_DATA_7 = 7'b111_1000 ;
parameter SEG_DATA_8 = 7'b000_0000 ;
parameter SEG_DATA_9 = 7'b001_0000 ;
parameter SEG_CHAR_O = 7'b010_0011 ;
parameter SEG_CHAR_P = 7'b000_1100 ;
parameter SEG_CHAR_E = 7'b000_0110 ;
parameter SEG_CHAR_N = 7'b010_1011 ;
parameter SEG_CHAR_L = 7'b100_0111 ;
parameter SEG_CHAR_C = 7'b100_0110 ;
parameter SEG_CHAR_K = 7'b000_0101 ;
parameter SEG_CHAR_D = 7'b010_0001 ;
parameter SEG_CHAR_R = 7'b010_1111 ;
parameter SEG_NONE_DIS = 7'b111_1111 ;
input clk ;
input rst_n ;
input [SEGMENT_NUM*W_DATA-1:0] din ;
input [SEGMENT_NUM-1:0] din_vld ;
output[SEGMENT_WID-1:0] segment ;
output[SEGMENT_NUM-1:0] seg_sel ;
reg [SEGMENT_WID-1:0] segment ;
reg [SEGMENT_NUM-1:0] seg_sel ;
reg [W_DATA-1:0] segment_pre ;
reg [SEGMENT_NUM*W_DATA-1:0] din_get ;
reg [14:0] cnt_300us ;
reg [2:0] cnt_sel ;
wire dot ;
wire add_cnt_300us ;
wire end_cnt_300us ;
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
cnt_300us <= 0;
end
else if(add_cnt_300us) begin
if(end_cnt_300us)
cnt_300us <= 0;
else
cnt_300us <= cnt_300us+1 ;
end
end
assign add_cnt_300us =1;
assign end_cnt_300us = add_cnt_300us && cnt_300us == TIME_300US-1 ;
wire add_cnt_sel ;
wire end_cnt_sel ;
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
cnt_sel <= 0;
end
else if(add_cnt_sel) begin
if(end_cnt_sel)
cnt_sel <= 0;
else
cnt_sel <= cnt_sel+1 ;
end
end
assign add_cnt_sel = end_cnt_300us;
assign end_cnt_sel = add_cnt_sel && cnt_sel == SEGMENT_NUM-1 ;
reg [SEGMENT_NUM-1:0] din_vvld;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
din_vvld <= 0 ;
end
else begin
din_vvld <= din_vld ;
end
end
reg [ 2:0] cnt ;
wire add_cnt ;
wire end_cnt ;
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
cnt <= 0;
end
else if(add_cnt) begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt+1 ;
end
end
assign add_cnt = 1;
assign end_cnt = add_cnt && cnt == SEGMENT_NUM-1 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
din_get <= 0;
end
else if(din_vvld[cnt])begin
din_get[W_DATA*(cnt+1)-1 -:W_DATA] <= din[W_DATA*(cnt+1)-1 -:W_DATA];
end
end
always @(*)begin
segment_pre = din_get[W_DATA*(cnt_sel+1)-1 -:W_DATA];
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
segment <= {dot,SEG_NONE_DIS};
end
else if(add_cnt_300us && cnt_300us ==10-1)begin
case(segment_pre)
5'h00: segment <= {dot,SEG_DATA_0};
5'h01: segment <= {dot,SEG_DATA_1};
5'h02: segment <= {dot,SEG_DATA_2};
5'h03: segment <= {dot,SEG_DATA_3};
5'h04: segment <= {dot,SEG_DATA_4};
5'h05: segment <= {dot,SEG_DATA_5};
5'h06: segment <= {dot,SEG_DATA_6};
5'h07: segment <= {dot,SEG_DATA_7};
5'h08: segment <= {dot,SEG_DATA_8};
5'h09: segment <= {dot,SEG_DATA_9};
5'h10: segment <= {dot,SEG_CHAR_O};
5'h11: segment <= {dot,SEG_CHAR_P};
5'h12: segment <= {dot,SEG_CHAR_E};
5'h13: segment <= {dot,SEG_CHAR_N};
5'h14: segment <= {dot,SEG_CHAR_L};
5'h15: segment <= {dot,SEG_CHAR_C};
5'h16: segment <= {dot,SEG_CHAR_K};
5'h17: segment <= {dot,SEG_CHAR_D};
5'h18: segment <= {dot,SEG_CHAR_R};
5'h1F: segment <= {dot,SEG_NONE_DIS};
default:segment <= {dot,SEG_NONE_DIS};
endcase
end
end
assign dot = 1'b1;
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
seg_sel <= {SEGMENT_NUM{1'b0}};
end
else begin
seg_sel <= ~(1'b1<<cnt_sel);
end
end
endmodule
1.5 效果(guǒ)和(hé)總(zǒng)結
下(xià)图(tú)是(shì)該工程在(zài)db603開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——密碼鎖初始狀态和(hé)閉合狀态
下(xià)图(tú)是(shì)該工程在(zài)db603開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——提(tí)示輸入(rù)錯誤狀态
下(xià)图(tú)是(shì)該工程在(zài)db603開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——密碼鎖開(kāi)啟狀态
下(xià)图(tú)是(shì)該工程在(zài)db603開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——輸入(rù)密碼狀态
下(xià)图(tú)是(shì)該工程在(zài)mp801開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——密碼鎖初始狀态和(hé)閉合狀态
下(xià)图(tú)是(shì)該工程在(zài)mp801開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——提(tí)示輸入(rù)錯誤狀态
下(xià)图(tú)是(shì)該工程在(zài)ms980開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——密碼鎖初始狀态和(hé)閉合狀态
下(xià)图(tú)是(shì)該工程在(zài)ms980開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——提(tí)示輸入(rù)錯誤狀态
下(xià)图(tú)是(shì)該工程在(zài)ms980開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——密碼鎖開(kāi)啟狀态
下(xià)图(tú)是(shì)該工程在(zài)ms980開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——輸入(rù)密碼狀态
由(yóu)于(yú)該項目的(de)上(shàng)板現(xiàn)象(xiàng)是(shì)在(zài)數碼管(guǎn)上(shàng)顯示輸入(rù)的(de)密碼,并且判斷密碼是(shì)否正(zhèng)确:正(zhèng)确則在(zài)數碼管(guǎn)上(shàng)顯示OPEN,錯誤則在(zài)數碼管(guǎn)上(shàng)顯示ERROR并提(tí)示輸入(rù)錯誤2秒(miǎo),然後(hòu)數碼管(guǎn)顯示LOCKED。想(xiǎng)观看(kàn)完整現(xiàn)象(xiàng)的(de)朋友可(kě)以(yǐ)看(kàn)一(yī)下(xià)上(shàng)板演示的(de)視頻。
感(gǎn)興趣的(de)朋友也(yě)可(kě)以(yǐ)訪問(wèn)明(míng)德揚論壇(http://www.fpgabbs.cn/)進(jìn)行FPGA相關(guān)工程設計(jì)学習。
源工程和(hé)設計(jì)教学視頻請到(dào)論壇下(xià)载。
明(míng)德揚至(zhì)簡設計(jì)案(àn)例200例:
http://fpgabbs.net/thread-1134-1-1.html
(出(chū)处: 明(míng)德揚論壇)
1.6 公司簡介
明(míng)德揚是(shì)一(yī)家(jiā)專注于(yú)FPGA領域的(de)專業性(xìng)公司,公司主(zhǔ)要(yào)業务包(bāo)括開(kāi)發(fà)板、教育培訓、項目承接、人(rén)才服(fú)务等多(duō)个(gè)方(fāng)向(xiàng)。點(diǎn)撥開(kāi)發(fà)板——学習FPGA的(de)入(rù)門(mén)之選。
MP801開(kāi)發(fà)板——千(qiān)兆(zhào)网(wǎng)、ADDA、大容量(liàng)SDRAM等,学習和(hé)項目需求一(yī)步到(dào)位。网(wǎng)絡培訓班——不(bù)管(guǎn)时(shí)間(jiān)和(hé)空間(jiān),明(míng)德揚随时(shí)在(zài)你身(shēn)邊(biān),助你快(kuài)速学習FPGA。周末(mò)培訓班——明(míng)天(tiān)的(de)你会(huì)感(gǎn)激現(xiàn)在(zài)的(de)努力進(jìn)取(qǔ),升(shēng)職加薪明(míng)德揚来(lái)助你。就(jiù)業培訓班——七(qī)大企業級項目实訓,獲得豐富的(de)項目經(jīng)验(yàn),高(gāo)薪就(jiù)業。專題(tí)課程——高(gāo)手(shǒu)修煉課:提(tí)升(shēng)設計(jì)能(néng)力;实用(yòng)調試技巧課:提(tí)升(shēng)定(dìng)位和(hé)解(jiě)決問(wèn)題(tí)能(néng)力;FIFO架構設計(jì)課:助你快(kuài)速成(chéng)为(wèi)架構設計(jì)师(shī);时(shí)序約束(shù)、數字(zì)信(xìn)号(hào)处理、PCIE、綜合項目实踐課等你来(lái)選。項目承接——承接企業FPGA研發(fà)項目。人(rén)才服(fú)务——提(tí)供人(rén)才推薦、人(rén)才代(dài)培、人(rén)才派遣等服(fú)务。








