本(běn)文(wén)为(wèi)明(míng)德揚原創及(jí)录(lù)用(yòng)文(wén)章(zhāng),轉(zhuǎn)载請注明(míng)出(chū)处!
案(àn)例編号(hào):00000066
1.1 總(zǒng)體(tǐ)設計(jì)
1.1.1 概述
在(zài)微機(jī)的(de)發(fà)展(zhǎn)初期(qī),BIOS都存放(fàng)在(zài)ROM(只(zhī)读(dú)存儲器)中(zhōng)。ROM內(nèi)部(bù)的(de)資料是(shì)在(zài)ROM的(de)制造工序中(zhōng),在(zài)工廠(chǎng)里(lǐ)用(yòng)特(tè)殊的(de)方(fāng)法燒录(lù)進(jìn)去(qù)的(de),其中(zhōng)的(de)內(nèi)容只(zhī)能(néng)读(dú)不(bù)能(néng)改,一(yī)旦燒录(lù)進(jìn)去(qù),用(yòng)戶只(zhī)能(néng)验(yàn)證写入(rù)的(de)資料是(shì)否正(zhèng)确,不(bù)能(néng)再做任何修改。如(rú)果(guǒ)發(fà)現(xiàn)資料有(yǒu)任何錯誤,則只(zhī)有(yǒu)舍棄不(bù)用(yòng),重(zhòng)新訂做一(yī)份。ROM是(shì)在(zài)生(shēng)産線(xiàn)上(shàng)生(shēng)産的(de),由(yóu)于(yú)成(chéng)本(běn)高(gāo),一(yī)般只(zhī)用(yòng)在(zài)大批量(liàng)應(yìng)用(yòng)的(de)场合。
由(yóu)于(yú)ROM制造和(hé)升(shēng)級的(de)不(bù)便,後(hòu)来(lái)人(rén)们(men)發(fà)明(míng)了(le)PROM(Programmable ROM,可(kě)編程ROM)。最(zuì)初從工廠(chǎng)中(zhōng)制作完成(chéng)的(de)PROM內(nèi)部(bù)并沒(méi)有(yǒu)資料,用(yòng)戶可(kě)以(yǐ)用(yòng)專用(yòng)的(de)編程器将自(zì)己的(de)資料写入(rù),但是(shì)这(zhè)種(zhǒng)機(jī)会(huì)只(zhī)有(yǒu)一(yī)次(cì),一(yī)旦写入(rù)後(hòu)也(yě)无法修改,若是(shì)出(chū)了(le)錯誤,已写入(rù)的(de)芯片(piàn)只(zhī)能(néng)報廢。PROM的(de)特(tè)性(xìng)和(hé)ROM相同(tóng),但是(shì)其成(chéng)本(běn)比ROM高(gāo),而(ér)且写入(rù)資料的(de)速度(dù)比ROM的(de)量(liàng)産速度(dù)要(yào)慢(màn),一(yī)般只(zhī)适用(yòng)于(yú)少(shǎo)量(liàng)需求的(de)场合或(huò)是(shì)ROM量(liàng)産前(qián)的(de)验(yàn)證。
EPROM(Erasable Programmable ROM,可(kě)擦除可(kě)編程ROM)芯片(piàn)可(kě)重(zhòng)複擦除和(hé)写入(rù),解(jiě)決了(le)PROM芯片(piàn)只(zhī)能(néng)写入(rù)一(yī)次(cì)的(de)弊端。EPROM芯片(piàn)有(yǒu)一(yī)个(gè)很明(míng)顯的(de)特(tè)征,在(zài)其正(zhèng)面(miàn)的(de)陶瓷封(fēng)裝(zhuāng)上(shàng),開(kāi)有(yǒu)一(yī)个(gè)玻璃窗(chuāng)口(kǒu),透过(guò)該窗(chuāng)口(kǒu),可(kě)以(yǐ)看(kàn)到(dào)其內(nèi)部(bù)的(de)集成(chéng)電(diàn)路(lù),紫外(wài)線(xiàn)透过(guò)該孔照射內(nèi)部(bù)芯片(piàn)就(jiù)可(kě)以(yǐ)擦除其內(nèi)的(de)數據(jù),完成(chéng)芯片(piàn)擦除的(de)操作要(yào)用(yòng)到(dào)EPROM擦除器。EPROM內(nèi)資料的(de)写入(rù)要(yào)用(yòng)專用(yòng)的(de)編程器,并且往芯片(piàn)中(zhōng)写內(nèi)容时(shí)必須要(yào)加一(yī)定(dìng)的(de)編程電(diàn)壓(VPP=12~24V,随不(bù)同(tóng)的(de)芯片(piàn)型号(hào)而(ér)定(dìng))。EPROM的(de)型号(hào)是(shì)以(yǐ)27開(kāi)头(tóu)的(de),如(rú)27C020(8*256K)是(shì)一(yī)片(piàn)2M Bits容量(liàng)的(de)EPROM芯片(piàn)。EPROM芯片(piàn)在(zài)写入(rù)資料後(hòu),還(huán)要(yào)以(yǐ)不(bù)透光(guāng)的(de)贴紙(zhǐ)或(huò)胶(jiāo)布(bù)把窗(chuāng)口(kǒu)封(fēng)住,以(yǐ)免受到(dào)周圍的(de)紫外(wài)線(xiàn)照射而(ér)使資料受損。
由(yóu)于(yú)EPROM操作的(de)不(bù)便,後(hòu)来(lái)出(chū)的(de)主(zhǔ)板上(shàng)BIOS ROM芯片(piàn)大部(bù)分(fēn)都采用(yòng)EEPROM(Electrically Erasable Programmable ROM,電(diàn)可(kě)擦除可(kě)編程ROM)。EEPROM的(de)擦除不(bù)需要(yào)借(jiè)助于(yú)其它(tā)設備,它(tā)是(shì)以(yǐ)電(diàn)子信(xìn)号(hào)来(lái)修改其內(nèi)容的(de),而(ér)且是(shì)以(yǐ)Byte为(wèi)最(zuì)小修改單位,不(bù)必将資料全(quán)部(bù)洗掉才能(néng)写入(rù),徹底擺脫了(le)EPROM Eraser和(hé)編程器的(de)束(shù)缚。EEPROM在(zài)写入(rù)數據(jù)时(shí),仍要(yào)利用(yòng)一(yī)定(dìng)的(de)編程電(diàn)壓,此(cǐ)时(shí),只(zhī)需用(yòng)廠(chǎng)商提(tí)供的(de)專用(yòng)刷新程序就(jiù)可(kě)以(yǐ)輕(qīng)而(ér)易舉地(dì)改写內(nèi)容,所(suǒ)以(yǐ),它(tā)屬于(yú)双(shuāng)電(diàn)壓芯片(piàn)。借(jiè)助于(yú)EEPROM芯片(piàn)的(de)双(shuāng)電(diàn)壓特(tè)性(xìng),可(kě)以(yǐ)使BIOS具有(yǒu)良好(hǎo)的(de)防毒功能(néng),在(zài)升(shēng)級时(shí),把跳線(xiàn)開(kāi)關(guān)打(dǎ)至(zhì)“on”的(de)位置,即給(gěi)芯片(piàn)加上(shàng)相應(yìng)的(de)編程電(diàn)壓,就(jiù)可(kě)以(yǐ)方(fāng)便地(dì)升(shēng)級;平时(shí)使用(yòng)时(shí),則把跳線(xiàn)開(kāi)關(guān)打(dǎ)至(zhì)“off”的(de)位置,防止CIH類(lèi)的(de)病毒对(duì)BIOS芯片(piàn)的(de)非(fēi)法修改。所(suǒ)以(yǐ),仍有(yǒu)不(bù)少(shǎo)主(zhǔ)板采用(yòng)EEPROM作为(wèi)BIOS芯片(piàn)并作为(wèi)自(zì)己主(zhǔ)板的(de)一(yī)大特(tè)色(sè)。 1.1.2 設計(jì)目标(biāo)
整个(gè)工程由(yóu)FPGA、矩阵(zhèn)鍵盤/按鍵、數碼管(guǎn)和(hé)AT93C46組成(chéng),实現(xiàn)一(yī)个(gè)上(shàng)電(diàn)後(hòu)能(néng)重(zhòng)新加载,接着上(shàng)次(cì)計(jì)數的(de)數字(zì)时(shí)鐘(zhōng),詳细(xì)功能(néng)如(rú)下(xià)。
1、數碼管(guǎn)顯示时(shí)鐘(zhōng)值,共(gòng)使用(yòng)了(le)6个(gè)數碼管(guǎn),分(fēn)别表(biǎo)示时(shí)十(shí)位、时(shí)个(gè)位、分(fēn)十(shí)位、分(fēn)个(gè)位、秒(miǎo)十(shí)位和(hé)秒(miǎo)个(gè)位。
2、 矩阵(zhèn)鍵盤或(huò)者(zhě)按鍵可(kě)以(yǐ)对(duì)數字(zì)时(shí)鐘(zhōng)進(jìn)行时(shí)分(fēn)秒(miǎo)的(de)設置。
A、上(shàng)電(diàn)後(hòu),时(shí)鐘(zhōng)默認处于(yú)計(jì)时(shí)狀态,當按鍵1按下(xià),跳到(dào)时(shí)間(jiān)設置狀态,當按鍵1再次(cì)按下(xià),回(huí)到(dào)計(jì)时(shí)狀态。
B、 當处于(yú)时(shí)間(jiān)設置狀态时(shí),默認此(cǐ)刻設置的(de)是(shì)秒(miǎo)个(gè)位,當按鍵2按下(xià),此(cǐ)刻設置秒(miǎo)十(shí)位,以(yǐ)此(cǐ)類(lèi)推,一(yī)次(cì)設置为(wèi)分(fēn)个(gè)位、分(fēn)十(shí)位、时(shí)个(gè)位和(hé)时(shí)十(shí)位。再按下(xià)按鍵2,則重(zhòng)新設置秒(miǎo)个(gè)位。
C、當处于(yú)时(shí)間(jiān)設置狀态时(shí),按下(xià)按鍵3,則設置位的(de)值加1,如(rú)果(guǒ)溢出(chū),則變(biàn)成(chéng)0。例如(rú)當目前(qián)小时(shí)顯示05时(shí),設置时(shí)十(shí)位,按下(xià)按鍵3,變(biàn)成(chéng)15,再按下(xià)按鍵3,則變(biàn)成(chéng)05.當目前(qián)小时(shí)顯示为(wèi)03时(shí),設置时(shí)十(shí)位,按一(yī)下(xià)按鍵3,變(biàn)成(chéng)13,再按一(yī)下(xià)按鍵3,則變(biàn)成(chéng)23,再按則为(wèi)03。
3、AT93C46則用(yòng)于(yú)保存时(shí)鐘(zhōng)值,其具有(yǒu)斷電(diàn)保護功能(néng),斷電(diàn)數據(jù)不(bù)丢失。
A、AT93C46一(yī)共(gòng)可(kě)以(yǐ)保存128字(zì)节(jié)的(de)數據(jù)。工程将AT93C46分(fēn)成(chéng)空間(jiān)1和(hé)空間(jiān)2。空間(jiān)1占用(yòng)的(de)地(dì)址为(wèi)0~3,空間(jiān)2占用(yòng)的(de)地(dì)址为(wèi)4~7。
B、每隔1秒(miǎo),保存當前(qián)时(shí)鐘(zhōng)值。第(dì)一(yī)次(cì)保存到(dào)空間(jiān)1,第(dì)二(èr)次(cì)保存到(dào)空間(jiān)2,第(dì)三(sān)次(cì)保存带(dài)空間(jiān)1,依此(cǐ)類(lèi)推。(如(rú)果(guǒ)只(zhī)有(yǒu)一(yī)个(gè)空間(jiān),則可(kě)能(néng)出(chū)現(xiàn)写數據(jù)过(guò)程中(zhōng)斷電(diàn),從而(ér)得不(bù)到(dào)完整數據(jù)情(qíng)況)
C、支持(chí)8位的(de)CRC,生(shēng)成(chéng)多(duō)項式
,初始值为(wèi)全(quán)1。
D、每次(cì)保存的(de)值,时(shí)十(shí)位、时(shí)个(gè)位、分(fēn)十(shí)位、分(fēn)个(gè)位、秒(miǎo)十(shí)位和(hé)秒(miǎo)个(gè)位各(gè)占4bit,共(gòng)3个(gè)字(zì)节(jié),加上(shàng)1个(gè)字(zì)节(jié)的(de)CRC,一(yī)共(gòng)4个(gè)字(zì)节(jié)。
E、上(shàng)電(diàn)後(hòu),FPGA将读(dú)取(qǔ)两(liǎng)个(gè)空間(jiān)的(de)數值,并作CRC檢验(yàn)。如(rú)果(guǒ)两(liǎng)組數據(jù)的(de)CRC檢验(yàn)均失敗,則不(bù)重(zhòng)新加载;如(rú)果(guǒ)有(yǒu)一(yī)組數據(jù)CRC檢验(yàn)失敗,則加载正(zhèng)确的(de)一(yī)組數據(jù);如(rú)果(guǒ)两(liǎng)組數據(jù)CRC檢验(yàn)均正(zhèng)确,則加载數值較大的(de)一(yī)組數據(jù)。
1.1.3 系(xì)統結構框图(tú)
系(xì)統結構框图(tú)如(rú)下(xià)所(suǒ)示:
图(tú)一(yī)
1.1.4模块(kuài)功能(néng)
鍵盤(按鍵)掃描模块(kuài)实現(xiàn)功能(néng)
1、将外(wài)来(lái)异(yì)步信(xìn)号(hào)打(dǎ)两(liǎng)拍处理,将异(yì)步信(xìn)号(hào)同(tóng)步化(huà)。
2、实現(xiàn)20ms按鍵消抖功能(néng)。
3、实現(xiàn)矩阵(zhèn)鍵盤或(huò)者(zhě)普通(tòng)案(àn)件(jiàn)的(de)檢测功能(néng),并輸出(chū)有(yǒu)效按鍵信(xìn)号(hào)。
时(shí)鐘(zhōng)數據(jù)産生(shēng)模块(kuài)实現(xiàn)功能(néng)
負責産生(shēng)數字(zì)时(shí)鐘(zhōng)需要(yào)的(de)时(shí)鐘(zhōng)信(xìn)息。包(bāo)括:
1、按數字(zì)时(shí)鐘(zhōng)方(fāng)式進(jìn)行計(jì)數
2、設置數字(zì)时(shí)鐘(zhōng)的(de)值
3、将时(shí)鐘(zhōng)數據(jù)輸出(chū)給(gěi)外(wài)部(bù)模块(kuài)使用(yòng)
4、從數據(jù)处理模块(kuài)得到(dào)时(shí)鐘(zhōng)數據(jù),并重(zhòng)新加载
數碼管(guǎn)顯示模块(kuài)实現(xiàn)功能(néng)
1、对(duì)时(shí)鐘(zhōng)數據(jù)進(jìn)行譯碼,然後(hòu)發(fà)到(dào)數碼管(guǎn)顯示
2、逐一(yī)顯示时(shí)分(fēn)秒(miǎo)的(de)值
數據(jù)处理模块(kuài)实現(xiàn)功能(néng)
負責写到(dào)AT93C46的(de)數據(jù),或(huò)者(zhě)從AT93C46读(dú)到(dào)數據(jù)後(hòu)的(de)处理,包(bāo)括:
1、上(shàng)電(diàn)後(hòu),發(fà)送EWEN命令,打(dǎ)開(kāi)AT93C46的(de)写保護。
2、發(fà)送EWEN命令後(hòu),開(kāi)始读(dú)存儲在(zài)AT93C46的(de)两(liǎng)組时(shí)鐘(zhōng)數據(jù);对(duì)數據(jù)進(jìn)行檢验(yàn),然後(hòu)選擇适合的(de)數據(jù)給(gěi)时(shí)鐘(zhōng)數據(jù)産生(shēng)模块(kuài)加载
3、每隔1秒(miǎo)從时(shí)鐘(zhōng)數據(jù)産生(shēng)模块(kuài)獲取(qǔ)时(shí)分(fēn)秒(miǎo)的(de)值,并産生(shēng)CRC值,最(zuì)後(hòu)写道(dào)AT93C46上(shàng)
CRC处理模块(kuài)实現(xiàn)功能(néng)
負責CRC算法的(de)模块(kuài),在(zài)數據(jù)处理模块(kuài)內(nèi)部(bù)使用(yòng)
AT93C46模块(kuài)实現(xiàn)功能(néng)
根(gēn)據(jù)上(shàng)遊模块(kuài)的(de)EWEN、WRITE和(hé)READ命令,産生(shēng)AT93C46的(de)相應(yìng)时(shí)序,從而(ér)写數據(jù)或(huò)者(zhě)读(dú)到(dào)數據(jù)。至(zhì)于(yú)數據(jù)是(shì)什麼(me)、有(yǒu)什麼(me)用(yòng),不(bù)關(guān)心(xīn),只(zhī)關(guān)心(xīn)AT93C46的(de)时(shí)序。
1.1.5頂层信(xìn)号(hào)
| 信(xìn)号(hào)名 | | |
| | 系(xì)統时(shí)鐘(zhōng),50Mhz |
| | |
| | 4位矩阵(zhèn)鍵盤列信(xìn)号(hào),默認高(gāo)電(diàn)平,開(kāi)發(fà)板按鍵为(wèi)普通(tòng)按鍵时(shí),不(bù)需要(yào)該信(xìn)号(hào) |
| | 4位矩阵(zhèn)鍵盤行信(xìn)号(hào),默認低電(diàn)平,開(kāi)發(fà)板按鍵为(wèi)普通(tòng)按鍵时(shí),不(bù)需要(yào)該信(xìn)号(hào) |
| | 3位按鍵信(xìn)号(hào),開(kāi)發(fà)板按鍵为(wèi)矩阵(zhèn)鍵盤时(shí),不(bù)需要(yào)該信(xìn)号(hào) |
| | 8位數碼管(guǎn)段(duàn)選信(xìn)号(hào) |
| | 6位數碼管(guǎn)位選信(xìn)号(hào) |
| | |
| | |
| | At93c46片(piàn)選信(xìn)号(hào) |
| | At93c46时(shí)鐘(zhōng)信(xìn)号(hào) |
1.1.6參考代(dài)碼
`define KEY_SCAN
module at93c46_top_scan(
clk ,
rst_n ,
key_col ,
mo ,
cs ,
mi ,
sk ,
key_row ,
seg_sel ,
seg_data
);
parameter TIME_1S = 50_000_000;
input clk ;
input rst_n ;
input [3:0] key_col ;
input mo ;
output cs ;
output mi ;
output sk ;
output[3:0] key_row ;
output[5:0] seg_sel ;
output[7:0] seg_data ;
wire rdy ;
wire rdata_vld ;
wire [3:0] key_en ;
wire [23:0] data_load ;
wire data_load_vld;
wire [23:0] clk_data_out ;
wire [6:0] addr ;
wire [1:0] mode ;
wire start ;
wire [7:0] wdata ;
wire [7:0] rdata ;
`ifdef KEY_SCAN
key_scan u_key_scan(
.clk (clk ),
.rst_n (rst_n ),
.key_col (key_col),
.key_row (key_row),
.key_en (key_en )
);
`else
key_module u_key_module(
.clk (clk ),
.rst_n (rst_n ),
.key_in (~key_col),
.key_vld (key_en )
);
`endif
clock_data#(.TIME_1S(TIME_1S)) u_clock_data(
.clk (clk ),
.rst_n (rst_n ),
.data_load (data_load ),
.data_load_vld (data_load_vld ),
.key_en (key_en ),
.data_out (clk_data_out )
);
seg_disp#(.SEG_NUM(6)) u_seg_disp(
.rst_n (rst_n ),
.clk (clk ),
.din (clk_data_out),
.din_vld ({6{1'b1}} ),
.seg_sel (seg_sel ),
.segment (seg_data )
);
data_processor#(.TIME_1S(TIME_1S)) u_data_pro(
.clk (clk ) ,
.rst_n (rst_n ) ,
.din (clk_data_out) ,
.start (start ) ,
.mode (mode ) ,
.addr (addr ) ,
.wdata (wdata ) ,
.rdata (rdata ) ,
.rdata_vld (rdata_vld ) ,
.rdy (rdy ) ,
.dout (data_load ) ,
.dout_vld (data_load_vld )
);
at93c46_mix u_at93c46_mix(
.clk (clk ) ,
.rst_n (rst_n ) ,
.start (start ) ,
.mode (mode ) ,
.addr (addr ) ,
.wdata (wdata ) ,
.rdata (rdata ) ,
.rdata_vld (rdata_vld ) ,
.rdy (rdy ) ,
.do (mo ) ,
.di (mi ) ,
.cs (cs ) ,
.sk (sk )
);
endmodule
複制代(dài)碼
本(běn)工程会(huì)應(yìng)用(yòng)于(yú)不(bù)同(tóng)的(de)開(kāi)發(fà)板,主(zhǔ)要(yào)區(qū)别在(zài)于(yú)使用(yòng)普通(tòng)按鍵還(huán)是(shì)矩阵(zhèn)鍵盤,頂层代(dài)碼中(zhōng)針(zhēn)对(duì)这(zhè)一(yī)點(diǎn)進(jìn)行了(le)設計(jì),如(rú)何開(kāi)發(fà)板使用(yòng)的(de)是(shì)矩阵(zhèn)鍵盤,則頂层代(dài)碼不(bù)需要(yào)改,如(rú)果(guǒ)使用(yòng)的(de)是(shì)普通(tòng)按鍵,只(zhī)需要(yào)将頂层代(dài)碼最(zuì)上(shàng)面(miàn)的(de)一(yī)行删除或(huò)者(zhě)注釋掉就(jiù)可(kě)以(yǐ)了(le)。
1.2 鍵盤(按鍵)掃描模块(kuài)設計(jì)1.2.1接口(kǒu)信(xìn)号(hào)
下(xià)面(miàn)为(wèi)使用(yòng)矩阵(zhèn)鍵盤时(shí)的(de)接口(kǒu)信(xìn)号(hào):
| 信(xìn)号(hào) | | |
| | |
| | |
| | 矩阵(zhèn)鍵盤列輸入(rù)信(xìn)号(hào) |
| | 矩阵(zhèn)鍵盤行輸出(chū)信(xìn)号(hào) |
| | 按鍵按下(xià)位置指示信(xìn)号(hào) |
下(xià)面(miàn)是(shì)使用(yòng)普通(tòng)按鍵时(shí)的(de)接口(kǒu)信(xìn)号(hào):
1.2.2 設計(jì)思(sī)路(lù)
在(zài)前(qián)面(miàn)的(de)按鍵控制數字(zì)时(shí)鐘(zhōng)的(de)案(àn)例中(zhōng)已經(jīng)有(yǒu)介紹,所(suǒ)以(yǐ)这(zhè)里(lǐ)不(bù)在(zài)过(guò)多(duō)介紹,詳细(xì)介紹請看(kàn)下(xià)方(fāng)鍊(liàn)接:
1.2.3參考代(dài)碼
module key_scan(
clk ,
rst_n ,
key_col,
key_row,
key_en
);
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[3:0] key_en ;
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 ;
reg [3:0] key_en ;
wire end_shake_cnt ;
reg end_shake_cnt_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 col2row_start ;
wire row2del_start ;
wire del2wait_start ;
wire wait2col_start ;
wire add_row_cnt ;
wire end_row_cnt ;
wire add_shake_cnt ;
wire add_row_index ;
wire end_row_index ;
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
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
shake_cnt <= 0;
end
else if(add_shake_cnt) begin
if(end_shake_cnt)
shake_cnt <= 0;
else
shake_cnt <= shake_cnt+1 ;
end
end
assign add_shake_cnt = key_col_ff1!=4'hf;
assign end_shake_cnt = 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(col2row_start )begin
state_n = CHK_ROW;
end
else begin
state_n = CHK_COL;
end
end
CHK_ROW: begin
if(row2del_start)begin
state_n = DELAY;
end
else begin
state_n = CHK_ROW;
end
end
DELAY : begin
if(del2wait_start)begin
state_n = WAIT_END;
end
else begin
state_n = DELAY;
end
end
WAIT_END: begin
if(wait2col_start)begin
state_n = CHK_COL;
end
else begin
state_n = WAIT_END;
end
end
default: state_n = CHK_COL;
endcase
end
assign col2row_start = state_c==CHK_COL && end_shake_cnt;
assign row2del_start = state_c==CHK_ROW && row_index==3 && end_row_cnt;
assign del2wait_start= state_c==DELAY && end_row_cnt;
assign wait2col_start= state_c==WAIT_END && 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==0) begin
row_index <= 0;
end
else if(add_row_index) begin
if(end_row_index)
row_index <= 0;
else
row_index <= row_index+1 ;
end
else if(state_c!=CHK_ROW)begin
row_index <= 0;
end
end
assign add_row_index = state_c==CHK_ROW && end_row_cnt;
assign end_row_index = add_row_index && row_index == 4-1 ;
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
row_cnt <= 0;
end
else if(add_row_cnt) begin
if(end_row_cnt)
row_cnt <= 0;
else
row_cnt <= row_cnt+1 ;
end
end
assign add_row_cnt = state_c==CHK_ROW || state_c==DELAY;
assign end_row_cnt = add_row_cnt && row_cnt == 16-1 ;
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 && end_shake_cnt ) 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 && end_row_cnt)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 && end_row_cnt && key_col_ff1[key_col_get]==1'b0)begin
key_vld <= 1'b1;
end
else begin
key_vld <= 1'b0;
end
end
always @(*)begin
if(rst_n==1'b0)begin
key_en = 0;
end
else if(key_vld && key_out==0)begin
key_en = 4'b0001;
end
else if(key_vld && key_out==1)begin
key_en = 4'b0010;
end
else if(key_vld && key_out==2)begin
key_en = 4'b0100;
end
else begin
key_en = 0;
end
end
複制代(dài)碼
1.3 时(shí)間(jiān)數據(jù)産生(shēng)模块(kuài)設計(jì)
1.3.1接口(kǒu)信(xìn)号(hào)
| 信(xìn)号(hào) | | |
| | |
| | |
| | 重(zhòng)载的(de)时(shí)鐘(zhōng)數據(jù),每四(sì)个(gè)一(yī)組,共(gòng)6組。由(yóu)高(gāo)位至(zhì)低位,分(fēn)别是(shì)时(shí)十(shí)位、时(shí)个(gè)位、分(fēn)十(shí)位、分(fēn)个(gè)位、秒(miǎo)十(shí)位和(hé)秒(miǎo)个(gè)位 |
| | 重(zhòng)载的(de)时(shí)鐘(zhōng)數據(jù)有(yǒu)效指示信(xìn)号(hào),當有(yǒu)效时(shí),采用(yòng)data_load的(de)數據(jù)为(wèi)最(zuì)新的(de)时(shí)鐘(zhōng)數據(jù) |
| | 按鍵位置輸入(rù)信(xìn)号(hào),key_vld有(yǒu)效时(shí),該信(xìn)号(hào)有(yǒu)效 |
| | 按鍵值有(yǒu)效信(xìn)号(hào),为(wèi)1时(shí)表(biǎo)示檢测到(dào)一(yī)个(gè)按鍵 |
| | 當前(qián)的(de)时(shí)鐘(zhōng)數據(jù),每四(sì)个(gè)1組,共(gòng)六(liù)組,由(yóu)高(gāo)位至(zhì)低位,分(fēn)别是(shì)时(shí)十(shí)位、时(shí)个(gè)位、分(fēn)十(shí)位、分(fēn)个(gè)位、秒(miǎo)十(shí)位和(hé)秒(miǎo)个(gè)位 |
1.3.2設計(jì)思(sī)路(lù)
本(běn)模块(kuài)相对(duì)于(yú)前(qián)面(miàn)的(de)按鍵控制數字(zì)时(shí)鐘(zhōng)案(àn)例中(zhōng)的(de)时(shí)間(jiān)數據(jù)産生(shēng)模块(kuài)来(lái)说(shuō),總(zǒng)體(tǐ)的(de)設計(jì)思(sī)路(lù)是(shì)相同(tóng)的(de),只(zhī)是(shì)增加了(le)一(yī)个(gè)重(zhòng)载的(de)时(shí)鐘(zhōng)信(xìn)号(hào),对(duì)于(yú)此(cǐ)信(xìn)号(hào)的(de)設計(jì)也(yě)比較簡單,只(zhī)需要(yào)在(zài)时(shí)分(fēn)秒(miǎo)的(de)个(gè)位和(hé)十(shí)位計(jì)數器中(zhōng)增加一(yī)句(jù):在(zài)重(zhòng)载的(de)时(shí)鐘(zhōng)數據(jù)有(yǒu)效的(de)时(shí)候,使計(jì)數器輸出(chū)重(zhòng)载的(de)时(shí)鐘(zhōng)对(duì)應(yìng)的(de)數據(jù)即可(kě),比如(rú)秒(miǎo)个(gè)位計(jì)數器應(yìng)該輸出(chū)重(zhòng)载时(shí)鐘(zhōng)數據(jù)的(de)第(dì)0到(dào)第(dì)3位數據(jù),秒(miǎo)十(shí)位計(jì)數器應(yìng)該輸出(chū)重(zhòng)载时(shí)鐘(zhōng)數據(jù)的(de)第(dì)4到(dào)第(dì)7位數據(jù),以(yǐ)此(cǐ)類(lèi)推。
其他(tā)詳细(xì)的(de)設計(jì)思(sī)路(lù)可(kě)以(yǐ)看(kàn)一(yī)下(xià)往期(qī)按鍵控制數字(zì)时(shí)鐘(zhōng)的(de)文(wén)章(zhāng):
1.3.3參考代(dài)碼
module clock_data(
clk ,
rst_n ,
data_load ,
data_load_vld,
key_en ,
data_out
);
parameter TIME_1S = 50_000_000 ;
input clk ;
input rst_n ;
input data_load_vld;
input [23:0] data_load ;
input [ 3:0] key_en ;
output[23:0] data_out ;
wire [23:0] data_out ;
reg [25:0] cnt_1s ;
reg [3:0] miao_ge ;
reg [3:0] miao_shi ;
reg [3:0] fen_ge ;
reg [3:0] fen_shi ;
reg [3:0] shi_ge ;
reg [3:0] shi_shi ;
reg [2:0] set_sel ;
reg set_flag ;
wire add_set_sel ;
wire add_cnt_1s ;
wire add_miao_ge ;
wire add_miao_shi ;
wire add_fen_ge ;
wire add_fen_shi ;
wire add_shi_ge ;
wire add_shi_shi ;
wire end_cnt_1s ;
wire end_set_sel ;
wire end_miao_ge ;
wire end_miao_shi ;
wire end_fen_ge ;
wire end_fen_shi ;
wire end_shi_ge ;
wire end_shi_shi ;
wire set_miao_ge ;
wire set_miao_shi ;
wire set_fen_ge ;
wire set_fen_shi ;
wire set_shi_ge ;
wire set_shi_shi ;
reg [ 3:0] x ;
reg [ 2:0] y ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
set_flag <= 1'b0;
end
else if(key_en[0]) begin
set_flag <= ~ set_flag;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
set_sel <= 0;
end
else if(add_set_sel)begin
if(end_set_sel)
set_sel <= 0;
else
set_sel <= set_sel + 1;
end
else if(set_flag==0)begin
set_sel <= 0;
end
end
assign add_set_sel = set_flag && key_en[1];
assign end_set_sel = add_set_sel && set_sel==6-1 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_1s <= 0;
end
else if(add_cnt_1s)begin
if(end_cnt_1s)
cnt_1s <= 0;
else
cnt_1s <= cnt_1s + 1;
end
end
assign add_cnt_1s = set_flag==0 ;
assign end_cnt_1s = add_cnt_1s && cnt_1s==TIME_1S-1 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
miao_ge <= 0;
end
else if(add_miao_ge)begin
if(end_miao_ge)
miao_ge <= 0;
else
miao_ge <= miao_ge + 1;
end
else if(data_load_vld)begin
miao_ge <= data_load[3:0];
end
end
assign add_miao_ge = (end_cnt_1s || set_miao_ge) ;
assign end_miao_ge = add_miao_ge && miao_ge==10-1 ;
assign set_miao_ge = set_flag && set_sel==0 && key_en[2];
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
miao_shi <= 0;
end
else if(add_miao_shi)begin
if(end_miao_shi)
miao_shi <= 0;
else
miao_shi <= miao_shi + 1;
end
else if(data_load_vld)begin
miao_shi <= data_load[7:4];
end
end
assign add_miao_shi = (end_miao_ge || set_miao_shi);
assign end_miao_shi = add_miao_shi && miao_shi==6-1;
assign set_miao_shi = set_flag && set_sel==1 && key_en[2];
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
fen_ge <= 0;
end
else if(add_fen_ge)begin
if(end_fen_ge)
fen_ge <= 0;
else
fen_ge <= fen_ge + 1;
end
else if(data_load_vld)begin
fen_ge <= data_load[11:8];
end
end
assign add_fen_ge = (end_miao_shi || set_fen_ge);
assign end_fen_ge = add_fen_ge && fen_ge==10-1;
assign set_fen_ge = set_flag && set_sel==2 && key_en[2];
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
fen_shi <= 0;
end
else if(add_fen_shi)begin
if(end_fen_shi)
fen_shi <= 0;
else
fen_shi <= fen_shi + 1;
end
else if(data_load_vld)begin
fen_shi <= data_load[15:12];
end
end
assign add_fen_shi = (end_fen_ge || set_fen_shi);
assign end_fen_shi = add_fen_shi && fen_shi==6-1;
assign set_fen_shi = set_flag && set_sel==3 && key_en[2];
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
shi_ge <= 0;
end
else if(add_shi_ge)begin
if(end_shi_ge)
shi_ge <= 0;
else
shi_ge <= shi_ge + 1;
end
else if(data_load_vld)begin
shi_ge <= data_load[19:16];
end
end
assign add_shi_ge = (end_fen_shi || set_shi_ge);
assign end_shi_ge = add_shi_ge && shi_ge==x-1;
assign set_shi_ge = set_flag && set_sel==4 && key_en[2];
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
shi_shi <= 0;
end
else if(add_shi_shi)begin
if(end_shi_shi)
shi_shi <= 0;
else
shi_shi <= shi_shi + 1;
end
else if(data_load_vld)begin
shi_shi <= data_load[23:20];
end
end
assign add_shi_shi = (end_shi_ge || set_shi_shi);
assign end_shi_shi = add_shi_shi && shi_shi==y-1;
assign set_shi_shi = set_flag && set_sel==5 && key_en[2];
always @(*)begin
if(shi_shi<2)
x = 10;
else
x = 4;
end
always @(*)begin
if(set_flag && set_sel==5 && shi_ge>=4)
y = 2;
else
y = 3;
end
assign data_out = {shi_shi,shi_ge,fen_shi,fen_ge,miao_shi,miao_ge};
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),50MHz |
| | |
| | 當前(qián)的(de)时(shí)鐘(zhōng)數據(jù),每四(sì)位一(yī)組,共(gòng) 6 組。由(yóu)高(gāo)位至(zhì)低位,分(fēn) 别是(shì)时(shí)十(shí)位、时(shí)个(gè)位、分(fēn)十(shí)位、分(fēn)个(gè)位、秒(miǎo)十(shí)位和(hé)秒(miǎo)个(gè)位的(de) 值。 |
| | |
| | 數碼管(guǎn)段(duàn)選信(xìn)号(hào) |
1.4.2設計(jì)思(sī)路(lù)
數碼管(guǎn)顯示在(zài)前(qián)面(miàn)的(de)案(àn)例文(wén)章(zhāng)已經(jīng)有(yǒu)講述,这(zhè)里(lǐ)不(bù)再進(jìn)行介紹,想(xiǎng)了(le)解(jiě)的(de)可(kě)以(yǐ)看(kàn)一(yī)下(xià)往期(qī)文(wén)章(zhāng):
1.4.3參考代(dài)碼
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_2ms <= 0;
end
else if(add_cnt_2ms)begin
if(end_cnt_2ms)
cnt_2ms <= 0;
else
cnt_2ms <= cnt_2ms + 1;
end
end
assign add_cnt_2ms = 1;
assign end_cnt_2ms = add_cnt_2ms && cnt_2ms==TIME_2MS-1 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)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_2ms;
assign end_cnt_sel = add_cnt_sel && cnt_sel== SEG_NUM-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
seg_sel <= {SEG_NUM{1'b1}};
end
else begin
seg_sel <= ~(1'b1 << cnt_sel);
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
din_ff0 <= 0;
end
else begin
for(ii=0;ii<SEG_NUM;ii=ii+1)begin
if(din_vld[ii]==1'b1)begin
din_ff0[(ii+1)*4-1 -:4] <= din[(ii+1)*4-1 -:4];
end
else begin
din_ff0[(ii+1)*4-1 -:4] <= din_ff0[(ii+1)*4-1 -:4];
end
end
end
end
always @(*)begin
seg_tmp = din_ff0[(cnt_sel+1)*4-1 -:4];
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
segment<=NUM_0;
end
else begin
case(seg_tmp)
4'd0:segment <= NUM_0;
4'd1:segment <= NUM_1;
4'd2:segment <= NUM_2;
4'd3:segment <= NUM_3;
4'd4:segment <= NUM_4;
4'd5:segment <= NUM_5;
4'd6:segment <= NUM_6;
4'd7:segment <= NUM_7;
4'd8:segment <= NUM_8;
4'd9:segment <= NUM_9;
default:begin
segment <= NUM_ERR;
end
endcase
end
end
endmodul
複制代(dài)碼
1.5 數據(jù)处理模块(kuài)設計(jì)
1.5.1接口(kǒu)信(xìn)号(hào)
| 信(xìn)号(hào) | | |
| | |
| | |
| | 时(shí)鐘(zhōng)數據(jù),每四(sì)位1組,共(gòng) 6 組。由(yóu)高(gāo)位至(zhì)低位,分(fēn)别是(shì)时(shí)十(shí)位、时(shí)个(gè)位、分(fēn)十(shí)位、分(fēn)个(gè)位、秒(miǎo)十(shí)位和(hé)秒(miǎo)个(gè)位的(de)值 |
| | 用(yòng)于(yú)加载的(de)时(shí)鐘(zhōng)數據(jù),每四(sì)位1組,共(gòng) 6 組。由(yóu)高(gāo)位至(zhì)低位,分(fēn)别是(shì)时(shí)十(shí)位、时(shí)个(gè)位、分(fēn)十(shí)位、分(fēn)个(gè)位、秒(miǎo)十(shí)位和(hé)秒(miǎo)个(gè)位的(de)值 |
| | 时(shí)鐘(zhōng)加载有(yǒu)效指示信(xìn)号(hào),高(gāo)電(diàn)平有(yǒu)效 |
| | 对(duì)AT93C46進(jìn)行打(dǎ)開(kāi)写保護、写數據(jù)或(huò)者(zhě)读(dú)數據(jù)命令。注意(yì),在(zài)rdy=0时(shí),不(bù)應(yìng)該使start有(yǒu)效 |
| | 对(duì)AT93C46的(de)操作模式,start有(yǒu)效时(shí),此(cǐ)值有(yǒu)效, 0:打(dǎ)開(kāi)写保護操作(EWEN) 1:写數據(jù)操作(WRITE) 2:读(dú)數據(jù)操作(READ) 其他(tā):不(bù)應(yìng)該出(chū)現(xiàn) |
| | 读(dú)写AT93C46的(de)地(dì)址信(xìn)号(hào),同(tóng)时(shí)亦是(shì)EWEN的(de)指示信(xìn)号(hào),使用(yòng)EWEN命令时(shí),此(cǐ)值必須为(wèi)7’b1100000,在(zài)start有(yǒu)效时(shí),此(cǐ)信(xìn)号(hào)有(yǒu)效 |
| | 写到(dào)AT93C46的(de)數據(jù),start=1,且mode=1时(shí),此(cǐ)值有(yǒu)效 |
| | AT93C46接口(kǒu)模块(kuài)準備好(hǎo)信(xìn)号(hào),只(zhī)有(yǒu)當其为(wèi)1时(shí),才能(néng)向(xiàng)接口(kǒu)模块(kuài)發(fà)送命令 |
| | 從AT93C46读(dú)取(qǔ)的(de)數據(jù) |
| | 從AT93C46读(dú)到(dào)的(de)數據(jù)有(yǒu)效指示信(xìn)号(hào) |
1.5.2設計(jì)思(sī)路(lù)
本(běn)模块(kuài)主(zhǔ)要(yào)負責写到(dào)AT93C46的(de)數據(jù)或(huò)者(zhě)读(dú)出(chū)的(de)數據(jù)的(de)处理,上(shàng)電(diàn)後(hòu),發(fà)送EWEN指令給(gěi)AT93C46接口(kǒu)模块(kuài),打(dǎ)開(kāi)AT93C46的(de)写保護;發(fà)送EWEN命令後(hòu),開(kāi)始读(dú)取(qǔ)存儲在(zài)AT93C46保存的(de)两(liǎng)組时(shí)鐘(zhōng)數據(jù);每隔1秒(miǎo)读(dú)取(qǔ)輸入(rù)时(shí)鐘(zhōng)數據(jù)的(de)值,并産生(shēng)CRC值,写到(dào)AT93C46上(shàng)。
根(gēn)據(jù)上(shàng)面(miàn)的(de)功能(néng)描述,該模块(kuài)采用(yòng)狀态機(jī)進(jìn)行架構,可(kě)劃(huà)分(fēn)四(sì)个(gè)狀态:打(dǎ)開(kāi)写保護狀态(S_EWEN)、读(dú)數據(jù)狀态(S_READ)、空閑狀态(S_IDLE)和(hé)写數據(jù)狀态(S_WRIT),狀态的(de)跳轉(zhuǎn)图(tú)如(rú)下(xià):
由(yóu)于(yú)功能(néng)要(yào)求只(zhī)在(zài)刚上(shàng)電(diàn)或(huò)者(zhě)複位的(de)时(shí)候才读(dú)取(qǔ)AT93C46中(zhōng)的(de)數據(jù),因(yīn)此(cǐ)刚上(shàng)電(diàn)就(jiù)是(shì)写保護打(dǎ)開(kāi)狀态,或(huò)者(zhě)複位有(yǒu)效时(shí),進(jìn)入(rù)写保護打(dǎ)開(kāi)狀态。由(yóu)于(yú)複位是(shì)由(yóu)按鍵控制的(de),因(yīn)此(cǐ)在(zài)按下(xià)的(de)时(shí)候会(huì)産生(shēng)抖動(dòng),可(kě)能(néng)会(huì)導致(zhì)産生(shēng)很多(duō)个(gè)start,因(yīn)此(cǐ)延时(shí)一(yī)段(duàn)时(shí)間(jiān)之後(hòu),如(rú)果(guǒ)AT93C46接口(kǒu)模块(kuài)準備好(hǎo),便進(jìn)入(rù)读(dú)數據(jù)狀态。數據(jù)读(dú)完之後(hòu),就(jiù)進(jìn)入(rù)空閑狀态,等待計(jì)时(shí)1秒(miǎo)之後(hòu),開(kāi)始将輸入(rù)的(de)时(shí)鐘(zhōng)數據(jù)写入(rù)AT93C46中(zhōng),写完四(sì)个(gè)字(zì)节(jié)數據(jù)之後(hòu)重(zhòng)新回(huí)到(dào)空閑狀态,等待計(jì)时(shí)1秒(miǎo),如(rú)此(cǐ)循环(huán)。
下(xià)面(miàn)介紹一(yī)下(xià)該模块(kuài)中(zhōng)其他(tā)信(xìn)号(hào)的(de)設計(jì)思(sī)路(lù):
时(shí)鐘(zhōng)計(jì)數器time_cnt:該計(jì)數器是(shì)計(jì)數1秒(miǎo)的(de)时(shí)間(jiān),從写保護打(dǎ)開(kāi)狀态跳轉(zhuǎn)到(dào)读(dú)數據(jù)狀态需要(yào)的(de)延时(shí)和(hé)空閑狀态跳轉(zhuǎn)写數據(jù)狀态需要(yào)的(de)1秒(miǎo)的(de)时(shí)間(jiān)可(kě)使用(yòng)此(cǐ)計(jì)數器表(biǎo)示;加一(yī)条(tiáo)件(jiàn)为(wèi)1,表(biǎo)示一(yī)直(zhí)計(jì)數;結束(shù)条(tiáo)件(jiàn)为(wèi)數50000000个(gè),表(biǎo)示1秒(miǎo)的(de)时(shí)間(jiān),數完就(jiù)清(qīng)零(líng)。
写數據(jù)計(jì)數器wr_cnt:該計(jì)數器用(yòng)于(yú)对(duì)要(yào)写入(rù)AT93C46的(de)數據(jù)進(jìn)行計(jì)數;加一(yī)条(tiáo)件(jiàn)为(wèi)state_c==S_WRIT&& rdy,表(biǎo)示在(zài)写數據(jù)狀态的(de)时(shí)候,如(rú)果(guǒ)AT93C46接口(kǒu)模块(kuài)準備好(hǎo),就(jiù)開(kāi)始計(jì)數;結束(shù)条(tiáo)件(jiàn)为(wèi)數4个(gè),3个(gè)字(zì)节(jié)的(de)时(shí)鐘(zhōng)數據(jù)加上(shàng)1个(gè)字(zì)节(jié)的(de)CRC校(xiào)验(yàn),共(gòng)四(sì)个(gè)字(zì)节(jié),數完就(jiù)清(qīng)零(líng)。
读(dú)數據(jù)計(jì)數器:該計(jì)數器數的(de)是(shì)從AT93C46读(dú)出(chū),并經(jīng)过(guò)CRC处理的(de)數據(jù)字(zì)节(jié)數;加一(yī)条(tiáo)件(jiàn)为(wèi)state_c==S_READ&& crc_dout_vld,表(biǎo)示在(zài)读(dú)數據(jù)狀态的(de)时(shí)候,CRC处理完就(jiù)計(jì)數一(yī)个(gè);結束(shù)条(tiáo)件(jiàn)为(wèi)數8个(gè),AT93C46两(liǎng)个(gè)區(qū)域內(nèi)共(gòng)存有(yǒu)8个(gè)字(zì)节(jié)的(de)數據(jù),數完就(jiù)清(qīng)零(líng)。
写區(qū)間(jiān)選擇信(xìn)号(hào)write_sel:初始狀态为(wèi)0,表(biǎo)示選擇區(qū)間(jiān)0~3,當写操作完成(chéng)之後(hòu),該信(xìn)号(hào)取(qǔ)反(fǎn),變(biàn)为(wèi)1,表(biǎo)示選擇區(qū)間(jiān)4~7。
读(dú)写地(dì)址信(xìn)号(hào)addr:初始狀态为(wèi)0,根(gēn)據(jù)下(xià)方(fāng)的(de)表(biǎo)格(AT93C46的(de)指令集),當处于(yú)写數據(jù)狀态的(de)时(shí)候,地(dì)址为(wèi)7bit,由(yóu)于(yú)本(běn)工程只(zhī)会(huì)使用(yòng)區(qū)間(jiān)0~7来(lái)存儲數據(jù),因(yīn)此(cǐ)地(dì)址为(wèi)4bit0加上(shàng)写區(qū)間(jiān)選擇信(xìn)号(hào)write_sel加上(shàng)写數據(jù)計(jì)數器;當处于(yú)写保護打(dǎ)開(kāi)狀态的(de)时(shí)候,地(dì)址應(yìng)为(wèi)7’b11xxxxx,其中(zhōng)“x”表(biǎo)示不(bù)關(guān)注,工程中(zhōng)設为(wèi)0即可(kě);當处于(yú)读(dú)數據(jù)狀态的(de)时(shí)候,根(gēn)據(jù)读(dú)數據(jù)計(jì)數器的(de)變(biàn)化(huà)選擇地(dì)址即可(kě),即地(dì)址为(wèi)4’b0加上(shàng)rd_cnt
AT93C46指令集
AT93C46開(kāi)始命令start:初始狀态为(wèi)0,表(biǎo)示AT93C46不(bù)工作,當(add_wr_cnt || start_read),也(yě)就(jiù)是(shì)在(zài)写數據(jù)、读(dú)數據(jù)或(huò)者(zhě)写保護打(dǎ)開(kāi)狀态的(de)时(shí)候,該信(xìn)号(hào)拉高(gāo),指示AT93C46工作。
写數據(jù)wdata:該信(xìn)号(hào)表(biǎo)示要(yào)往AT93C46中(zhōng)写入(rù)的(de)數據(jù),初始狀态为(wèi)0。前(qián)三(sān)个(gè)字(zì)节(jié)写入(rù)輸入(rù)的(de)时(shí)鐘(zhōng)數據(jù),第(dì)四(sì)个(gè)字(zì)节(jié)写入(rù)CRC。
AT93C46返回(huí)數據(jù)dout_temp:從AT93C46读(dú)出(chū)的(de)8个(gè)字(zì)节(jié)數據(jù),經(jīng)过(guò)串并轉(zhuǎn)換之後(hòu)保存在(zài)該信(xìn)号(hào)中(zhōng)。
第(dì)一(yī)區(qū)間(jiān)CRC錯誤指示信(xìn)号(hào)dout0_err:初始狀态为(wèi)0,表(biǎo)示沒(méi)有(yǒu)錯誤;當读(dú)數據(jù)計(jì)數器數到(dào)第(dì)4个(gè)的(de)时(shí)候,表(biǎo)示CRC模块(kuài)已經(jīng)完成(chéng)了(le)第(dì)一(yī)區(qū)間(jiān)數據(jù)的(de)校(xiào)验(yàn),如(rú)果(guǒ)校(xiào)验(yàn)結果(guǒ)为(wèi)0,表(biǎo)示正(zhèng)确,如(rú)果(guǒ)校(xiào)验(yàn)結果(guǒ)不(bù)等于(yú)0,表(biǎo)示輸出(chū)錯誤。
第(dì)二(èr)區(qū)間(jiān)CRC錯誤指示信(xìn)号(hào)dout1_err:为(wèi)了(le)使錯誤指示信(xìn)号(hào)跟數據(jù)能(néng)对(duì)齊,采用(yòng)組合邏輯設計(jì),當CRC模块(kuài)輸出(chū)數據(jù)为(wèi)0,表(biǎo)示沒(méi)有(yǒu)錯誤,該信(xìn)号(hào)为(wèi)0,如(rú)果(guǒ)CRC模块(kuài)輸出(chū)數據(jù)不(bù)为(wèi)0,表(biǎo)示有(yǒu)錯誤,該信(xìn)号(hào)为(wèi)1。
用(yòng)于(yú)加载的(de)时(shí)鐘(zhōng)數據(jù)dout:初始狀态为(wèi)0;當读(dú)數據(jù)計(jì)數器數完的(de)时(shí)候,如(rú)果(guǒ)區(qū)間(jiān)1和(hé)區(qū)間(jiān)2的(de)檢验(yàn)都沒(méi)有(yǒu)錯誤,則比較AT93C46返回(huí)數據(jù)的(de)高(gāo)4字(zì)节(jié)和(hé)低4字(zì)节(jié)的(de)大小,輸出(chū)大的(de);如(rú)果(guǒ)區(qū)間(jiān)1檢验(yàn)正(zhèng)确,區(qū)間(jiān)2檢验(yàn)錯誤,則輸出(chū)高(gāo)4字(zì)节(jié)數據(jù),反(fǎn)之則輸出(chū)低4字(zì)节(jié)數據(jù)。
时(shí)鐘(zhōng)加载有(yǒu)效指示信(xìn)号(hào)dout_vld:初始狀态为(wèi)0,表(biǎo)示时(shí)鐘(zhōng)數據(jù)无效;當读(dú)數據(jù)計(jì)數器數完的(de)时(shí)候,如(rú)果(guǒ)第(dì)一(yī)區(qū)間(jiān)和(hé)第(dì)二(èr)區(qū)間(jiān)有(yǒu)最(zuì)少(shǎo)一(yī)个(gè)正(zhèng)确,該信(xìn)号(hào)就(jiù)拉高(gāo),表(biǎo)示待加载的(de)时(shí)鐘(zhōng)數據(jù)有(yǒu)效,其他(tā)情(qíng)況不(bù)拉高(gāo)。
1.5.3參考代(dài)碼
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
state_c <= S_EWEN;
end
else begin
state_c <= state_n;
end
end
always @(*)begin
case(state_c)
S_EWEN : begin
if(ewen2read_start)begin
state_n = S_READ ;
end
else begin
state_n = state_c;
end
end
S_READ : begin
if(read2idle_start)begin
state_n = S_IDLE;
end
else begin
state_n = state_c;
end
end
S_IDLE : begin
if(idle2write_start)begin
state_n = S_WRITE;
end
else begin
state_n = state_c;
end
end
S_WRITE : begin
if(write2idle_start)begin
state_n = S_IDLE;
end
else begin
state_n = state_c;
end
end
default : begin
state_n = S_EWEN;
end
endcase
end
assign ewen2read_start = state_c==S_EWEN && add_time_cnt && time_cnt==1000-1 && rdy;
assign read2idle_start = state_c==S_READ && end_rd_cnt ;
assign idle2write_start = state_c==S_IDLE && end_time_cnt ;
assign write2idle_start = state_c==S_WRITE && end_wr_cnt ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
time_cnt <= 0;
end
else if(add_time_cnt)begin
if(end_time_cnt)
time_cnt <= 0;
else
time_cnt <= time_cnt + 1;
end
end
assign add_time_cnt = 1;
assign end_time_cnt = add_time_cnt && time_cnt==TIME_1S-1 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
wr_cnt <= 0;
end
else if(add_wr_cnt)begin
if(end_wr_cnt)
wr_cnt <= 0;
else
wr_cnt <= wr_cnt + 1;
end
end
assign add_wr_cnt = state_c==S_WRITE && rdy;
assign end_wr_cnt = add_wr_cnt && wr_cnt == WR_NUM-1 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rd_cnt <= 0;
end
else if(add_rd_cnt)begin
if(end_rd_cnt)
rd_cnt <= 0;
else
rd_cnt <= rd_cnt + 1;
end
end
assign add_rd_cnt = state_c==S_READ && crc_dout_vld;
assign end_rd_cnt = add_rd_cnt && rd_cnt == RD_NUM-1 ;
assign start_read = state_c==S_READ && flag_wait_crc==0 && rdy;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_wait_crc <= 0;
end
else if(start_read)begin
flag_wait_crc <= 1;
end
else if(crc_dout_vld)begin
flag_wait_crc <= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
mode <= EWEN;
end
else if(state_c==S_EWEN) begin
mode <= EWEN;
end
else if(state_c==S_WRITE)begin
mode <= WRITE;
end
else if(state_c==S_READ)begin
mode <= READ;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
crc_din <= 0;
end
else if(add_wr_cnt && end_wr_cnt==0) begin
crc_din <= din[8*(D_LEN-wr_cnt)-1 -:8];
end
else begin
crc_din <= rdata;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
crc_din_vld <= 1'b0;
end
else if(add_wr_cnt && end_wr_cnt==0) begin
crc_din_vld <= 1'b1;
end
else begin
crc_din_vld <= rdata_vld;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
crc_clr <= 1'b0;
end
else if((add_rd_cnt && rd_cnt==4-1)|| read2idle_start || write2idle_start) begin
crc_clr <= 1'b1;
end
else begin
crc_clr <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
addr <= 0;
end
else if(state_c==S_WRITE) begin
addr <= {4'b0,write_sel,wr_cnt[1:0]};
end
else if(state_c==S_EWEN) begin
addr <= 7'b1100000;
end
else begin
addr <= {4'b0,rd_cnt};
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
write_sel <= 1'b0;
end
else if(write2idle_start) begin
write_sel <= ~write_sel;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
wdata <= 0;
end
else if(wr_cnt==WR_NUM-1) begin
wdata <= crc_dout;
end
else begin
wdata <= din[8*(D_LEN-wr_cnt)-1 -:8];
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
start <= 1'b0;
end
else if(add_wr_cnt || start_read || ewen2read_start)begin
start <= 1'b1;
end
else begin
start <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout_temp<= 0;
end
else if(rdata_vld) begin
dout_temp[(8-rd_cnt)*8-1 -:8] <= rdata;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout0_err <= 1'b0;
end
else if(add_rd_cnt && rd_cnt==4-1) begin
if(crc_dout!=0)
dout0_err <= 1'b1;
else
dout0_err <= 1'b0;
end
end
always @(*)begin
if(crc_dout!=0)
dout1_err = 1'b1;
else
dout1_err = 1'b0;
end
assign dout0_temp = dout_temp[8*8-1 -:24];
assign dout1_temp = dout_temp[4*8-1 -:24];
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout <= 0;
end
else if(end_rd_cnt) begin
if(dout0_err==1'b0 && dout1_err==1'b0)begin
if(dout0_temp > dout1_temp)
dout <= dout0_temp;
else
dout <= dout1_temp;
end
else if(dout0_err==1'b0)begin
dout <= dout0_temp;
end
else begin
dout <= dout1_temp;
end
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout_vld <= 1'b0;
end
else if(end_rd_cnt) begin
if(dout0_err && dout1_err)begin
dout_vld <= 1'b0;
end
else begin
dout_vld <= 1'b1;
end
end
else begin
dout_vld <= 1'b0;
end
end
crc8_d8 u_crc8_d8(
.clk (clk ),
.rst_n (rst_n ),
.clr (crc_clr ),
.din_vld (crc_din_vld ),
.din (crc_din ),
.dout_vld (crc_dout_vld ),
.dout (crc_dout )
);
複制代(dài)碼
1.6 CRC处理模块(kuài)設計(jì)
1.6.1接口(kǒu)信(xìn)号(hào)
| 信(xìn)号(hào) | | |
| | |
| | |
| | 清(qīng)零(líng)信(xìn)号(hào),将當前(qián)的(de)CRC運算複位,重(zhòng)新開(kāi)始新的(de)運算。 |
| | CRC輸入(rù)數據(jù)有(yǒu)效信(xìn)号(hào) |
| | |
| | |
| | CRC輸出(chū)有(yǒu)效指示信(xìn)号(hào) |
1.6.2設計(jì)思(sī)路(lù)
該模块(kuài)主(zhǔ)要(yào)的(de)作用(yòng)是(shì)負責CRC運算,在(zài)數據(jù)处理模块(kuài)內(nèi)部(bù)使用(yòng),多(duō)項式为(wèi) ,本(běn)模块(kuài)代(dài)碼不(bù)需要(yào)設計(jì),使用(yòng)网(wǎng)上(shàng)的(de)生(shēng)成(chéng)工具(https://www.easics.com/crctool/
),輸入(rù)多(duō)項式即可(kě)生(shēng)成(chéng),具體(tǐ)設置請看(kàn)下(xià)图(tú)。
關(guān)于(yú)CRC的(de)原理和(hé)并行、串行实現(xiàn)的(de)方(fāng)法,有(yǒu)另(lìng)外(wài)的(de)視頻進(jìn)行講解(jiě),这(zhè)里(lǐ)不(bù)在(zài)進(jìn)行介紹。
1.6.3參考代(dài)碼
assign d = din ;
assign c = dout ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout <= 0;
end
else if(clr)begin
dout <= 0;
end
else if(din_vld) begin
dout[0] <= d[7] ^ d[6] ^ d[0] ^ c[0] ^ c[6] ^ c[7];
dout[1] <= d[6] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[6];
dout[2] <= d[6] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[6];
dout[3] <= d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[3] ^ c[7];
dout[4] <= d[4] ^ d[3] ^ d[2] ^ c[2] ^ c[3] ^ c[4];
dout[5] <= d[5] ^ d[4] ^ d[3] ^ c[3] ^ c[4] ^ c[5];
dout[6] <= d[6] ^ d[5] ^ d[4] ^ c[4] ^ c[5] ^ c[6];
dout[7] <= d[7] ^ d[6] ^ d[5] ^ c[5] ^ c[6] ^ c[7];
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout_vld <= 0;
end
else begin
dout_vld <= din_vld;
end
end
endmodul
複制代(dài)碼
1.7 AT93C46接口(kǒu)模块(kuài)設計(jì)
1.7.1接口(kǒu)信(xìn)号(hào)
| 信(xìn)号(hào) | | |
| | |
| | |
| | 地(dì)址信(xìn)号(hào),在(zài)start有(yǒu)效时(shí),此(cǐ)值有(yǒu)效 |
| | 写數據(jù)信(xìn)号(hào),在(zài)start有(yǒu)效时(shí),此(cǐ)值有(yǒu)效 |
| | 開(kāi)始命令,僅在(zài)rdy=1时(shí)才有(yǒu)效 |
| | 操作模式指示信(xìn)号(hào),start有(yǒu)效时(shí),此(cǐ)值有(yǒu)效 |
| | 準備好(hǎo)信(xìn)号(hào)。當rdy为(wèi)1时(shí),start才有(yǒu)效。在(zài)rdy为(wèi)0时(shí),不(bù)能(néng)使start有(yǒu)效 |
| | 從AT93C46读(dú)取(qǔ)的(de)數據(jù) |
| | 從AT93C46读(dú)到(dào)的(de)數據(jù)有(yǒu)效指示信(xìn)号(hào) |
| | |
| | |
| | AT93C46片(piàn)選信(xìn)号(hào) |
| | AT93C46时(shí)鐘(zhōng),200KHz |
1.7.2設計(jì)思(sī)路(lù)
參考數據(jù)手(shǒu)册,本(běn)模块(kuài)主(zhǔ)要(yào)实現(xiàn)三(sān)个(gè)命令:打(dǎ)開(kāi)写保護(EWEN)、读(dú)數據(jù)(READ)和(hé)写數據(jù)(WRITE)。
下(xià)面(miàn)时(shí)EWEN命令的(de)时(shí)序图(tú),結合上(shàng)文(wén)提(tí)到(dào)的(de)AT93C46的(de)指令集,打(dǎ)開(kāi)写保護指令的(de)时(shí)序應(yìng)該是(shì)写10bit數據(jù)之後(hòu),等待TCS时(shí)間(jiān),然後(hòu)結束(shù)。
下(xià)面(miàn)是(shì)READ命令的(de)时(shí)序图(tú)。結合上(shàng)文(wén)提(tí)到(dào)的(de)AT93C46的(de)指令集,读(dú)數據(jù)命令对(duì)應(yìng)的(de)时(shí)序應(yìng)該是(shì)写10bit數據(jù)鐘(zhōng)後(hòu),读(dú)8bit數據(jù),等待TCS时(shí)間(jiān),然後(hòu)結束(shù)。
下(xià)面(miàn)是(shì)WRITE命令的(de)时(shí)序图(tú)。結合上(shàng)文(wén)提(tí)到(dào)的(de)AT93C46的(de)指令集,写數據(jù)命令对(duì)應(yìng)的(de)时(shí)序應(yìng)該是(shì)写18bit數據(jù),cs拉低TCS时(shí)間(jiān),等待TWP(5ms)时(shí)間(jiān),然後(hòu)結束(shù)。
根(gēn)據(jù)上(shàng)述的(de)时(shí)序介紹,本(běn)模块(kuài)采用(yòng)3个(gè)計(jì)數器的(de)架構,下(xià)面(miàn)是(shì)計(jì)數器的(de)架構图(tú)。
架構中(zhōng)的(de)三(sān)个(gè)計(jì)數器分(fēn)别为(wèi)时(shí)鐘(zhōng)計(jì)數器cnt0、比特(tè)計(jì)數器cnt1和(hé)階(jiē)段(duàn)計(jì)數器cnt2,flag_work为(wèi)工作狀态指示信(xìn)号(hào)。
时(shí)鐘(zhōng)計(jì)數器cnt0:該計(jì)數器用(yòng)来(lái)計(jì)數时(shí)鐘(zhōng)的(de)个(gè)數。加一(yī)条(tiáo)件(jiàn)为(wèi)flag_work,表(biǎo)示進(jìn)入(rù)工作狀态就(jiù)開(kāi)始計(jì)數。結束(shù)条(tiáo)件(jiàn)为(wèi)數x个(gè),根(gēn)據(jù)不(bù)同(tóng)的(de)工作模式和(hé)所(suǒ)处的(de)階(jiē)段(duàn)不(bù)同(tóng)而(ér)變(biàn)化(huà)。包(bāo)括SK的(de)时(shí)鐘(zhōng)周期(qī)數、等待时(shí)間(jiān)TCS、等待5ms时(shí)間(jiān)。
比特(tè)計(jì)數器cnt1:該計(jì)數器用(yòng)来(lái)數有(yǒu)多(duō)少(shǎo)bit數據(jù),加一(yī)条(tiáo)件(jiàn)为(wèi)end_cnt0,表(biǎo)示每數完1bit,就(jiù)加1;結束(shù)条(tiáo)件(jiàn)为(wèi)數y个(gè),y分(fēn)别为(wèi)10(EWEN)、18(READ和(hé)WRITE)、1(等待TCS和(hé)5ms)。
階(jiē)段(duàn)計(jì)數器cnt2:該計(jì)數器用(yòng)来(lái)对(duì)每个(gè)指令需要(yào)的(de)階(jiē)段(duàn)進(jìn)行計(jì)數。加一(yī)条(tiáo)件(jiàn)为(wèi)end_cnt1,表(biǎo)示發(fà)送完一(yī)組數據(jù)就(jiù)加一(yī);結束(shù)条(tiáo)件(jiàn)为(wèi)數u个(gè),u分(fēn)别为(wèi)2(EWEN和(hé)READ)、3(WRITE)。
除了(le)上(shàng)述的(de)計(jì)數器之外(wài),還(huán)有(yǒu)一(yī)些比較重(zhòng)要(yào)的(de)信(xìn)号(hào),我(wǒ)们(men)来(lái)分(fēn)析一(yī)下(xià)如(rú)何進(jìn)行設計(jì)。
工作狀态指示信(xìn)号(hào)flag_work:初始狀态为(wèi)0,表(biǎo)示处于(yú)空閑狀态;當收(shōu)到(dào)開(kāi)始命令start的(de)时(shí)候,變(biàn)化(huà)變(biàn)为(wèi)1,由(yóu)空閑狀态轉(zhuǎn)为(wèi)工作狀态;當前(qián)指令的(de)时(shí)序結束(shù)之後(hòu),也(yě)就(jiù)是(shì)階(jiē)段(duàn)計(jì)數器cnt2數完,就(jiù)變(biàn)为(wèi)0,進(jìn)入(rù)空閑狀态。
待發(fà)送數據(jù)dout:當接收(shōu)到(dào)開(kāi)始命令的(de)时(shí)候,根(gēn)據(jù)AT93C46的(de)指令集,将SB、Opcode、Address和(hé)data按照順序拼接到(dào)一(yī)起。
模式暫存器mode_reg:为(wèi)保證在(zài)發(fà)送时(shí)序期(qī)間(jiān)保持(chí)不(bù)變(biàn),在(zài)接收(shōu)到(dào)開(kāi)始命令的(de)时(shí)候,将操作模式指示信(xìn)号(hào)進(jìn)行暫存。
AT93C46时(shí)鐘(zhōng)sk:时(shí)鐘(zhōng)頻率为(wèi)200KHz,工程的(de)系(xì)統时(shí)鐘(zhōng)为(wèi)50MHz,因(yīn)此(cǐ)sk一(yī)个(gè)完整的(de)周期(qī)需要(yào)250个(gè)系(xì)統时(shí)鐘(zhōng)周期(qī),初始狀态設为(wèi)低電(diàn)平,當时(shí)鐘(zhōng)計(jì)數器數到(dào)125个(gè)的(de)时(shí)候置为(wèi)高(gāo)電(diàn)平,时(shí)鐘(zhōng)計(jì)數器數完,在(zài)置为(wèi)低電(diàn)平。
AT93C46數據(jù)輸入(rù)di:在(zài)每个(gè)指令时(shí)序的(de)第(dì)一(yī)階(jiē)段(duàn),也(yě)就(jiù)是(shì)cnt2=1-1的(de)时(shí)候,根(gēn)據(jù)比特(tè)計(jì)數器要(yào)數的(de)个(gè)數,将待發(fà)送的(de)數據(jù)dout送給(gěi)di。
AT93C46片(piàn)選信(xìn)号(hào)cs:在(zài)写比特(tè)數據(jù)、等待5ms期(qī)間(jiān)为(wèi)高(gāo),其他(tā)时(shí)候都为(wèi)低,所(suǒ)以(yǐ)該信(xìn)号(hào)拉高(gāo)的(de)条(tiáo)件(jiàn)为(wèi)(start_vld==1 || (add_cnt2 && cnt2==2-1 &&end_cnt2==0))。其他(tā)时(shí)候片(piàn)選信(xìn)号(hào)都为(wèi)低,所(suǒ)以(yǐ)拉低的(de)条(tiáo)件(jiàn)为(wèi)((add_cnt2&& cnt2==1-1) || end_cnt2)。
读(dú)取(qǔ)數據(jù)rdata:在(zài)读(dú)模式下(xià),处于(yú)第(dì)一(yī)階(jiē)段(duàn),并且在(zài)第(dì)11~18bit的(de)时(shí)候,将AT93C46輸出(chū)數據(jù)do保存到(dào)rdata里(lǐ)面(miàn)。
準備好(hǎo)信(xìn)号(hào)rdy:由(yóu)組合邏輯産生(shēng),當接收(shōu)到(dào)開(kāi)始命令,或(huò)者(zhě)处于(yú)工作狀态的(de)时(shí)候,为(wèi)低電(diàn)平,表(biǎo)示沒(méi)有(yǒu)準備好(hǎo);其他(tā)时(shí)刻为(wèi)高(gāo)電(diàn)平,表(biǎo)示準備好(hǎo)。
1.7.3參考代(dài)碼
assign start_vld = flag_work==0 && start;
always @(*)begin
if(mode==EWEN)
opcode = 3'b100;
else if(mode==WRITE)
opcode = 3'b101;
else
opcode = 3'b110;
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout <= 0;
end
else if(start_vld) begin
dout <={opcode,addr,wdata};
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
mode_reg <= 0;
end
else if(start_vld) begin
mode_reg <= mode;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_work <= 0;
end
else if(start_vld) begin
flag_work <= 1;
end
else if(end_cnt2)begin
flag_work <= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt0 <= 0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end
assign add_cnt0 = flag_work;
assign end_cnt0 = add_cnt0 && cnt0== x-1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1==y-1 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt2 <= 0;
end
else if(add_cnt2)begin
if(end_cnt2)
cnt2 <= 0;
else
cnt2 <= cnt2 + 1;
end
end
assign add_cnt2 = end_cnt1;
assign end_cnt2 = add_cnt2 && cnt2==u-1;
assign en_sk1 = add_cnt0 && cnt0==x/2-1 && cnt2==1-1;
assign en_sk0 = end_cnt0 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
sk <= 0;
end
else if(add_cnt0 && cnt0==x/2-1 && cnt2==1-1)begin
sk <= 1;
end
else if(end_cnt0)begin
sk <= 0;
end
end
assign en_di = add_cnt0 && cnt0==1-1 && cnt2==1-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
di <= 0;
end
else if(en_di) begin
di <= dout[17-cnt1];
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cs <= 0;
end
else if(start_vld==1 || (add_cnt2 && cnt2==2-1 && end_cnt2==0)) begin
cs <= 1;
end
else if((add_cnt2 && cnt2==1-1) || end_cnt2)begin
cs <= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rdata <= 0;
end
else if(end_cnt0 && cnt1 >=10 && cnt2==1-1 && mode_reg==READ ) begin
rdata[17-cnt1] <= do;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rdata_vld <= 0;
end
else begin
rdata_vld <= end_cnt2 && mode_reg==READ;
end
end
always @(*)begin
if(start || flag_work)
rdy = 1'b0;
else
rdy = 1'b1;
end
always @(*)begin
if(mode_reg==WRITE && cnt2==1-1)begin
x = 250;
y = 18;
u = 3;
end
else if(mode_reg==WRITE && (cnt2==2-1 ))begin
x = 250 ;
y = 1 ;
u = 3 ;
end
else if(mode_reg==WRITE && cnt2==3-1)begin
x = 500000;
y = 1 ;
u = 3 ;
end
else if(mode_reg==READ && cnt2==1-1)begin
x = 250;
y = 18;
u = 2;
end
else if(mode_reg==READ && cnt2==2-1)begin
x = 250 ;
y = 1 ;
u = 2 ;
end
else if(mode_reg==EWEN && cnt2==1-1)begin
x = 250;
y = 10;
u = 2;
end
else begin
x = 250 ;
y = 1 ;
u = 2 ;
end
end
endmodul
複制代(dài)碼
1.8 效果(guǒ)和(hé)總(zǒng)結
本(běn)工程上(shàng)板之後(hòu),可(kě)通(tòng)过(guò)複位来(lái)验(yàn)證現(xiàn)象(xiàng),若要(yào)通(tòng)过(guò)斷電(diàn)来(lái)進(jìn)行验(yàn)證,需要(yào)将工程燒录(lù)進(jìn)開(kāi)發(fà)板才行。
1.8.1db603開(kāi)發(fà)板
由(yóu)于(yú)本(běn)工程現(xiàn)象(xiàng)是(shì)一(yī)个(gè)動(dòng)态的(de)过(guò)程,所(suǒ)以(yǐ)從下(xià)面(miàn)图(tú)片(piàn)中(zhōng)看(kàn)不(bù)出(chū)具體(tǐ)实現(xiàn)的(de)效果(guǒ),想(xiǎng)要(yào)看(kàn)上(shàng)板效果(guǒ)的(de)話(huà)可(kě)以(yǐ)看(kàn)一(yī)下(xià)工程上(shàng)板的(de)視頻。
1.8.2mp801開(kāi)發(fà)板
由(yóu)于(yú)本(běn)工程現(xiàn)象(xiàng)是(shì)一(yī)个(gè)動(dòng)态的(de)过(guò)程,所(suǒ)以(yǐ)從下(xià)面(miàn)图(tú)片(piàn)中(zhōng)看(kàn)不(bù)出(chū)具體(tǐ)实現(xiàn)的(de)效果(guǒ),想(xiǎng)要(yào)看(kàn)上(shàng)板效果(guǒ)的(de)話(huà)可(kě)以(yǐ)看(kàn)一(yī)下(xià)工程上(shàng)板的(de)視頻。
1.8.3ms980試验(yàn)箱
由(yóu)于(yú)本(běn)工程現(xiàn)象(xiàng)是(shì)一(yī)个(gè)動(dòng)态的(de)过(guò)程,所(suǒ)以(yǐ)從下(xià)面(miàn)图(tú)片(piàn)中(zhōng)看(kàn)不(bù)出(chū)具體(tǐ)实現(xiàn)的(de)效果(guǒ),想(xiǎng)要(yào)看(kàn)上(shàng)板效果(guǒ)的(de)話(huà)可(kě)以(yǐ)看(kàn)一(yī)下(xià)工程上(shàng)板的(de)視頻。
詳细(xì)的(de)設計(jì)視頻教程和(hé)工程源碼請到(dào)明(míng)德揚論壇学習!
MDY最(zuì)新推出(chū)《FPGA至(zhì)簡設計(jì)案(àn)例200例》項目,每周固定(dìng)更(gèng)新至(zhì)少(shǎo)1个(gè)案(àn)例,可(kě)到(dào)明(míng)德揚論壇www.fpgabbs.cn下(xià)载学習
温(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)步)
本(běn)文(wén)TAG: