【上(shàng)板現(xiàn)象(xiàng)】
電(diàn)子密碼鎖的(de)在(zài)MP801的(de)上(shàng)板現(xiàn)象(xiàng)
https://www.bilibili.com/video/BV1Af4y117H4?p=43
電(diàn)子密碼鎖的(de)在(zài)點(diǎn)撥開(kāi)發(fà)板的(de)上(shàng)板現(xiàn)象(xiàng)
https://www.bilibili.com/video/BV1Af4y117H4?p=42
電(diàn)子密碼鎖的(de)在(zài)实验(yàn)箱的(de)上(shàng)板現(xiàn)象(xiàng)
https://www.bilibili.com/video/BV1Af4y117H4?p=44
【設計(jì)教程
至(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ú)一(yī)所(suǒ)示:
图(tú)一(yī)
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)
| 信(xìn)号(hào)名 | | | |
| | | 系(xì)統工作时(shí)鐘(zhōng) 50M |
| | | 系(xì)統複位信(xìn)号(hào),低電(diàn)平有(yǒu)效 |
| | | |
| | | |
| | | 6位數碼管(guǎn)位選信(xìn)号(hào) |
| | | 8位數碼管(guǎn)段(duàn)選信(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
複制代(dài)碼
1.2按鍵檢测模块(kuài)設計(jì)1.2.1接口(kǒu)信(xìn)号(hào)
| 信(xìn)号(hào)名 | | | |
| | | 系(xì)統工作时(shí)鐘(zhōng) 50M |
| | | 系(xì)統複位信(xìn)号(hào),低電(diàn)平有(yǒu)效 |
| | | |
| | | |
| | | |
| | | |
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)接:
其中(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
複制代(dài)碼
1.3控制模块(kuài)設計(jì)1.3.1接口(kǒu)信(xìn)号(hào)
| 信(xìn)号(hào)名 | | | |
| | | 系(xì)統工作时(shí)鐘(zhōng) 50M |
| | | 系(xì)統複位信(xìn)号(hào),低電(diàn)平有(yǒu)效 |
| | | |
| | | |
| | | 30bit的(de)數碼管(guǎn)顯示數據(jù),每5bit为(wèi)一(yī)个(gè)字(zì)符(对(duì)應(yìng)一(yī)个(gè)數碼管(guǎn)),一(yī)共(gòng)表(biǎo)示6个(gè)數碼管(guǎn)的(de)顯示數據(jù)。 |
| | | 數碼管(guǎn)顯示數據(jù)有(yǒu)效指示信(xìn)号(hào),seg_dout_vld [0]为(wèi)1时(shí),seg_dout[4:0]有(yǒu)效;seg_dout_vld [1]为(wèi)1时(shí),seg_dout[9:5]有(yǒu)效,以(yǐ)此(cǐ)为(wèi)推。 |
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
複制代(dài)碼
1.4數碼管(guǎn)顯示模块(kuài)設計(jì)1.4.1接口(kǒu)信(xìn)号(hào)
| 信(xìn)号(hào)名 | | | |
| | | 系(xì)統工作时(shí)鐘(zhōng) 50M |
| | | 系(xì)統複位信(xìn)号(hào),低電(diàn)平有(yǒu)效 |
| | | 30位的(de)輸入(rù)數碼管(guǎn)顯示數據(jù)。每5bit一(yī)个(gè)字(zì)符(对(duì)應(yìng)一(yī)个(gè)數碼管(guǎn)),6个(gè)數碼管(guǎn)則一(yī)共(gòng)30bit。 |
| | | 輸入(rù)數據(jù)有(yǒu)效指示信(xìn)号(hào),din_vld[0]为(wèi)1时(shí),din[4:0]有(yǒu)效;din_vld[1]为(wèi)1时(shí),din[9:5]有(yǒu)效,以(yǐ)此(cǐ)類(lèi)推。 |
| | | 8位數碼管(guǎn)段(duàn)選信(xìn)号(hào) |
| | | 6位數碼管(guǎn)位選信(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ǒ)示:
file:///C:/Users/27657/AppData/Local/Temp/msohtmlclip1/01/clip_image010.gif
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
複制代(dài)碼
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)mp801開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——密碼鎖開(kāi)啟狀态

下(xià)图(tú)是(shì)該工程在(zài)mp801開(kāi)發(fà)板上(shàng)的(de)現(xiàn)象(xiàng)——輸入(rù)密碼狀态

下(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ì)学習,也(yě)可(kě)以(yǐ)看(kàn)一(yī)下(xià)我(wǒ)们(men)往期(qī)的(de)文(wén)章(zhā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ú)务。
設計(jì)教程下(xià)载】
至(zhì)簡設計(jì)系(xì)列_電(diàn)子密碼鎖.pdf (3.41 MB, 下(xià)载次(cì)數: 1111)
設計(jì)視頻教程】
https://www.bilibili.com/video/BV1Af4y117H4?p=41
【工程源碼】
mdyPwdlock.zip (66.36 KB, 下(xià)载次(cì)數: 1130)
【答(dá)疑】
【問(wèn)題(tí)1】

答(dá):在(zài)頂层里(lǐ),可(kě)以(yǐ)看(kàn)到(dào)紅(hóng)框里(lǐ)的(de)信(xìn)号(hào)的(de)是(shì)相連(lián)的(de),

那(nà)麼(me)去(qù)control模块(kuài)看(kàn),这(zhè)里(lǐ)的(de)CHAR_O的(de)參數的(de)數值是(shì)随便定(dìng)的(de),只(zhī)要(yào)可(kě)以(yǐ)與(yǔ)其它(tā)區(qū)分(fēn)

再到(dào)seg_display模块(kuài)看(kàn),當得到(dào)數值为(wèi)5'h10时(shí)則表(biǎo)示要(yào)顯示的(de)是(shì)“O”,那(nà)麼(me)对(duì)應(yìng)的(de)數碼管(guǎn)段(duàn)選信(xìn)号(hào)segment的(de)數值就(jiù)取(qǔ):信(xìn)号(hào)dot的(de)值和(hé)參數SIG_CHAR_O的(de)值拼接得到(dào)的(de)數據(jù)。

温(wēn)馨提(tí)示:明(míng)德揚2023推出(chū)了(le)全(quán)新課程——邏輯設計(jì)基本(běn)功修煉課,降低学習FPGA門(mén)檻的(de)同(tóng)时(shí),增加了(le)学習的(de)趣味性(xìng),并組織了(le)考試赢積分(fēn)活動(dòng)
http://www.minyingyiyuan.com/ffkc/415.html
(點(diǎn)擊→了(le)解(jiě)課程詳情(qíng)☝)感(gǎn)興趣請聯系(xì)易老(lǎo)师(shī):13112063618(微信(xìn)同(tóng)步)
有(yǒu)問(wèn)題(tí)請聯系(xì)陳老(lǎo)师(shī):MDYfpga003
本(běn)文(wén)TAG: