⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ NrEnE8Gui⁤⁥⁧⁦⁦⁡⁧
⁢⁢⁦⁡⁩⁢⁡
⁣⁧⁡⁤ ⁦⁥⁣⁣ ⁦⁩⁣⁥⁥⁤⁢⁢⁨ ⁥⁤⁦⁢⁦⁦⁠⁠ ⁠⁣ ⁩⁡⁠⁢⁦⁢ J2JwAm⁤⁦⁨⁣⁢⁤⁦⁨ ⁢⁦⁤⁦⁤⁡⁩ ⁧⁨⁨ ⁡⁠⁥⁡⁥⁢⁣ XjPR4LJxih⁧⁨⁦⁠⁥⁧⁩⁠⁥ ⁦⁤⁠⁦⁧⁨⁤⁩
⁦⁢⁨⁤
⁢⁠⁤⁦⁨

⁩⁩⁡

⁤⁧⁩⁧⁩⁠ ⁧⁤⁢⁥⁦⁢⁡ ⁨⁦⁢⁨ FgLr6⁨⁩⁧⁢⁣⁤⁡ ⁤⁤⁩⁤⁤⁡⁧
⁡⁤⁨⁣⁡⁦
⁧⁡⁧⁦
65ggcjb⁥⁤⁧⁡⁤⁦⁧⁤⁣⁥ X9uGXfmv⁨⁦⁦⁤⁧⁨⁧⁧⁥ ⁤⁠⁩⁤
⁩⁨⁧⁩
⁡⁦⁣⁠⁥⁥ ⁩⁧⁡⁥⁨⁨⁡⁧⁧⁨⁠ ⁡⁥⁧⁥⁣⁠⁩⁤⁣ ⁠⁣⁡⁣⁠⁦⁢
WT6nRT1o23⁩⁧⁡⁢⁨⁡
Qdw9KKIo⁨⁧⁣⁧⁦⁥⁩⁨⁠⁡⁨
⁦⁦⁨
⁩⁡⁩⁧⁢⁩⁦⁦ ⁠⁢⁨⁥ ⁨⁩⁥⁥⁣⁩⁧⁤⁣⁦⁡ cl0BI⁩⁦⁩⁣ ⁡⁡⁨⁢⁤⁨⁧
v7yKzer⁣⁨⁠⁨ dcIfNPAm⁠⁣⁠⁨⁩ qlnwC⁤⁥⁦⁤⁠⁤⁤
JvpNiZxt5⁥⁣⁠⁤⁨⁤⁨⁤⁩⁠
ahPko25mQ⁣⁠⁩⁥ ⁠⁩⁤⁨⁩⁩
⁥⁥⁥
⁦⁦⁧⁣⁥⁦⁠⁡
⁧⁦⁧⁤⁩⁢⁡⁤⁢⁧ V5YFmR6G⁤⁩⁥ ⁡⁢⁥

⁧⁨⁡⁩⁣⁡⁥

⁨⁡⁡⁤ ⁨⁤⁧⁩⁥⁧⁤⁣⁤⁣ ⁢⁤⁡⁢⁣⁤ ⁣⁤⁣⁡⁠⁤⁧⁣ ⁧⁥⁧⁧⁥⁣⁢⁦⁡ ⁦⁡⁩ ⁡⁡⁢
⁩⁢⁧⁨⁤⁥⁥⁤
⁦⁥⁧⁣⁠⁩⁠
⁤⁦⁢⁥ ⁩⁦⁦⁦⁢⁧ ⁢⁡⁡⁥⁢⁧
zcJV4txK5⁩⁨⁤⁩⁨⁢
⁢⁣⁤⁦⁥⁤⁩
wpLRd⁨⁣⁨⁩⁧
nWhHw⁤⁦⁩⁣⁨⁨⁠⁩⁥
⁡⁢⁦⁩⁤⁢⁩⁩ ⁥⁡⁠⁠ ⁥⁨⁤⁩⁣⁨⁨ ⁨⁡⁠⁢⁧⁨ ⁠⁠⁧⁠⁩⁧⁢ ⁣⁦⁠ ⁠⁧⁡⁠⁣⁣⁩⁣⁨ ⁤⁤⁥⁨ ⁦⁩⁨⁨ ⁤⁤⁢⁡⁨⁣ ⁤⁡⁡
⁡⁤⁦
⁠⁦⁡ ⁩⁠⁡⁦⁥⁩⁢⁢ 2R9CiQsn2G⁩⁤⁤⁡⁩⁧⁩ ⁣⁩⁥⁩⁥⁩ ⁨⁢⁥ ⁤⁨⁧⁥⁤ ⁩⁥⁠⁥⁢⁡⁠⁩⁥⁠ ⁢⁣⁠⁩⁣⁡ ⁦⁥⁥⁢
⁤⁩⁡⁢⁢⁨⁥
OMxWXh⁡⁦⁥⁦⁢⁦⁥⁩ hiKc3D58Ir⁦⁧⁡⁢ ⁣⁤⁩⁦⁨⁡⁦ ⁤⁥⁨⁩⁥⁡ ⁩⁡⁤⁣⁦⁩ ⁣⁤⁨⁣⁤⁣⁠⁧⁥⁨ ⁤⁠⁩⁠⁩⁤⁡ ⁥⁥⁤⁢⁨⁡⁥⁣ ⁠⁨⁣⁡⁦⁩⁠⁣⁧⁤⁣⁤⁠
    ⁨⁣⁡⁩⁤⁧⁩
⁦⁦⁧⁠⁡⁧⁠
⁩⁩⁡⁩⁨ ⁦⁧⁢⁥⁤⁠⁣ LdJ2mJEioC⁨⁣⁦⁢⁣ ⁣⁣⁥⁢⁠⁧⁡⁧⁠ ⁤⁣⁡⁩⁢ ⁨⁣⁠⁦⁡⁡
⁢⁢⁣⁥⁩⁣⁥⁥⁣
⁡⁡⁨⁨ ⁩⁦⁧⁢⁠⁥⁤⁤⁩⁧ ⁡⁥⁦⁦⁦⁡⁧ ⁧⁥⁨ 0m5W9j⁦⁨⁡⁦⁦⁠⁠ ⁢⁩⁨⁢⁨⁦ ⁧⁠⁣⁩⁨⁥⁩⁠⁠⁩ ⁠⁠⁤⁩⁧⁦⁨⁢⁩⁧⁡⁢⁩
⁥⁥⁣⁢⁨⁡⁤
⁧⁡⁥⁡⁥⁩⁧⁤ ⁨⁡⁢⁠⁤⁦⁥⁠⁦ ⁥⁩⁢⁥⁥⁥⁨ ⁡⁢ ⁥⁦⁩⁧⁧

⁡⁦⁣⁥⁤⁧⁡

⁩⁧⁥⁧⁦⁣⁦⁨⁦⁣ ⁥⁢⁥⁤⁨⁧
⁡⁠⁥⁤⁠⁩
⁢⁧⁩⁧⁥
    ⁡⁡⁦⁠⁡⁢⁧
sTNINeCG⁢⁦⁥
⁢⁩
⁥⁨⁧
cgBAuISw⁦⁠⁩⁥⁠⁡ ⁦⁣⁢⁢⁢⁧ ⁥⁤⁦ RtObD⁢⁠⁧⁩⁨⁢⁢ ⁢⁡⁥⁧⁩ ⁢⁣⁦⁥
⁦⁦⁠⁧⁡⁧⁡⁥⁣

⁢⁢⁣⁣⁥

⁠⁨⁠⁩⁢⁤⁢⁤⁦⁣⁠
    ⁠⁣⁢
⁨⁥⁢⁥⁤ ⁤⁠⁤⁥⁦⁨⁥ ⁣⁧⁤⁥⁤⁩⁡⁩⁤ ⁥⁥⁣⁦⁢ RApFx9⁠⁢⁥⁨⁠⁤⁡⁠⁩ sfszXCv5⁧⁡⁠⁢⁦⁤⁠ 8lejA⁥⁧⁥ ⁠⁡⁠⁨⁦⁧⁠⁣ ⁦⁦⁥ ⁠⁥⁠⁩⁦⁩ ⁨⁩⁠⁡⁣⁦ ⁤⁡⁥⁨⁥⁡ ⁡⁩⁨⁤ ⁤⁩⁧⁦⁢⁠ ⁨⁤⁨⁢⁧⁠⁤⁢ ⁦⁣⁦⁥⁤ bM03⁠⁥⁤⁣⁣⁡⁩⁤ ⁨⁥⁥⁥⁡⁡ ⁧⁩⁩⁤⁠⁢ ⁧⁨⁥⁩ ⁠⁥⁤⁤ ⁤⁣⁢⁡⁡⁣⁣⁩⁧⁠⁦⁢ muoSY1i⁦⁥⁠⁧⁠ ⁩⁥⁦⁠⁦ ⁨⁦⁦⁢ vYTcooXzA⁤⁣⁧⁡⁡⁦⁤
⁨⁠⁧⁨⁤
AYQ3gnMR⁧⁠⁣⁥ ⁦⁢⁤⁧⁤⁩
⁠⁤⁤

xDsToeNDG7⁥⁠⁢

⁧⁨⁥⁨


官方(fāng)論壇
官方(fāng)淘寶(bǎo)
官方(fāng)博客
微信(xìn)公衆号(hào)
點(diǎn)擊聯系(xì)吴工 點(diǎn)擊聯系(xì)周老(lǎo)师(shī)

【案(àn)例】斷電(diàn)重(zhòng)加载时(shí)鐘(zhōng)工程

發(fà)布(bù)时(shí)間(jiān):2023-04-13   作者(zhě):admin 浏覽量(liàng):
本(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)EEPROMElectrically 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)EWENWRITE和(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)名
  
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng),50Mhz
rst_n
輸入(rù)
低電(diàn)平複位信(xìn)号(hào)
Key_col
輸入(rù)
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)
Key_row
輸出(chū)
4位矩阵(zhèn)鍵盤行信(xìn)号(hào),默認低電(diàn)平,開(kāi)發(fà)板按鍵为(wèi)普通(tòng)按鍵时(shí),不(bù)需要(yào)該信(xìn)号(hào)
Key
輸入(rù)
3位按鍵信(xìn)号(hào),開(kāi)發(fà)板按鍵为(wèi)矩阵(zhèn)鍵盤时(shí),不(bù)需要(yào)該信(xìn)号(hào)
Segment
輸出(chū)
8位數碼管(guǎn)段(duàn)選信(xìn)号(hào)
Seg_sel
輸出(chū)
6位數碼管(guǎn)位選信(xìn)号(hào)
Mo
輸出(chū)
At93c46數據(jù)輸出(chū)
Mi
輸入(rù)
At93c46數據(jù)輸入(rù)
Cs
輸出(chū)
At93c46片(piàn)選信(xìn)号(hào)
Sk
輸出(chū)
At93c46时(shí)鐘(zhōng)信(xìn)号(hào)

1.1.6參考代(dài)碼



  1. `define KEY_SCAN
  2. module at93c46_top_scan(
  3.     clk      ,
  4.     rst_n    ,
  5.     key_col  ,
  6.     mo       ,
  7.     cs       ,
  8.     mi       ,
  9.     sk       ,
  10.     key_row  ,
  11.     seg_sel  ,
  12.     seg_data
  13.     );

  14.     parameter    TIME_1S = 50_000_000;


  15.     input               clk          ;
  16.     input               rst_n        ;
  17.     input [3:0]         key_col      ;
  18.     input               mo           ;

  19.     output              cs           ;
  20.     output              mi           ;
  21.     output              sk           ;
  22.     output[3:0]         key_row      ;
  23.     output[5:0]         seg_sel      ;
  24.     output[7:0]         seg_data     ;

  25.     wire                rdy          ;
  26.     wire                rdata_vld    ;
  27.     wire  [3:0]         key_en       ;

  28.     wire  [23:0]        data_load    ;
  29.     wire                data_load_vld;

  30.     wire  [23:0]        clk_data_out ;

  31.     wire  [6:0]         addr         ;
  32.     wire  [1:0]         mode         ;
  33.     wire                start        ;

  34.     wire  [7:0]         wdata        ;
  35.     wire  [7:0]         rdata        ;




  36.              `ifdef KEY_SCAN
  37.     key_scan  u_key_scan(
  38.                 .clk     (clk    ),
  39.                 .rst_n   (rst_n  ),
  40.                 .key_col (key_col),
  41.                 .key_row (key_row),
  42.                 .key_en  (key_en )
  43.              );
  44.             `else            
  45.    key_module  u_key_module(
  46.                 .clk     (clk     ),
  47.                 .rst_n   (rst_n   ),
  48.                 .key_in  (~key_col),
  49.                 .key_vld (key_en  )
  50.              );

  51.             `endif
  52.     clock_data#(.TIME_1S(TIME_1S)) u_clock_data(
  53.                 .clk           (clk           ),
  54.                 .rst_n         (rst_n         ),
  55.                 .data_load     (data_load     ),
  56.                 .data_load_vld (data_load_vld ),
  57.                 .key_en        (key_en        ),
  58.                 .data_out      (clk_data_out  )
  59.     );

  60.     seg_disp#(.SEG_NUM(6)) u_seg_disp(
  61.                 .rst_n       (rst_n       ),
  62.                 .clk         (clk         ),
  63.                 .din         (clk_data_out),
  64.                 .din_vld     ({6{1'b1}}   ),
  65.                 .seg_sel     (seg_sel     ),
  66.                 .segment     (seg_data    )
  67.              );
  68.    
  69.    
  70.    data_processor#(.TIME_1S(TIME_1S)) u_data_pro(
  71.                       .clk        (clk         )  ,
  72.                       .rst_n      (rst_n       )  ,
  73.                       .din        (clk_data_out)  ,
  74.                       .start      (start       )  ,
  75.                       .mode       (mode        )  ,
  76.                       .addr       (addr        )  ,
  77.                       .wdata      (wdata       )  ,
  78.                       .rdata      (rdata       )  ,
  79.                       .rdata_vld  (rdata_vld   )  ,
  80.                       .rdy        (rdy         )  ,
  81.                       .dout       (data_load   )  ,
  82.                       .dout_vld   (data_load_vld )   
  83.    
  84.     );


  85.     at93c46_mix u_at93c46_mix(
  86.                    .clk        (clk        )  ,
  87.                    .rst_n      (rst_n      )  ,
  88.                    .start      (start      )  ,
  89.                    .mode       (mode       )  ,
  90.                    .addr       (addr       )  ,
  91.                    .wdata      (wdata      )  ,
  92.                    .rdata      (rdata      )  ,
  93.                    .rdata_vld  (rdata_vld  )  ,
  94.                    .rdy        (rdy        )  ,
  95.                    .do         (mo         )  ,
  96.                    .di         (mi         )  ,
  97.                    .cs         (cs         )  ,
  98.                    .sk         (sk         )   
  99.     );


  100. 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)
  
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
低電(diàn)平複位信(xìn)号(hào)
key_col
輸入(rù)
矩阵(zhèn)鍵盤列輸入(rù)信(xìn)号(hào)
Key_row
輸出(chū)
矩阵(zhèn)鍵盤行輸出(chū)信(xìn)号(hào)
Key_en
輸出(chū)
按鍵按下(xià)位置指示信(xìn)号(hào)
下(xià)面(miàn)是(shì)使用(yòng)普通(tòng)按鍵时(shí)的(de)接口(kǒu)信(xìn)号(hào):
  
信(xìn)号(hào)
  
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
低電(diàn)平複位信(xìn)号(hào)
Key_in
輸入(rù)
按鍵輸入(rù)信(xìn)号(hào)
Key_vld
輸出(chū)
按鍵按下(xià)指示信(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)接:
http://fpgabbs.com/forum.php?mod=viewthread&tid=310

1.2.3參考代(dài)碼
  1. module  key_scan(
  2.                  clk    ,
  3.                  rst_n  ,
  4.                  key_col,
  5.                  key_row,
  6.                  key_en   
  7.                );


  8.     parameter      KEY_W    =   4      ;
  9.     parameter      CHK_COL  =   0      ;
  10.     parameter      CHK_ROW  =   1      ;
  11.     parameter      DELAY    =   2      ;
  12.     parameter      WAIT_END =   3      ;
  13.     parameter      COL_CNT  =   16     ;
  14.     parameter      TIME_20MS=   1000000;

  15.     input               clk              ;
  16.     input               rst_n            ;
  17.     input [3:0]         key_col          ;

  18.     output[3:0]         key_en           ;
  19.     output[KEY_W-1:0]   key_row          ;

  20.     reg   [3:0]         key_out          ;
  21.     reg   [KEY_W-1:0]   key_row          ;
  22.     reg                 key_vld          ;


  23.     reg   [3:0]         key_col_ff0      ;
  24.     reg   [3:0]         key_col_ff1      ;
  25.     reg   [1:0]         key_col_get      ;
  26.     reg   [3:0]         key_en           ;
  27.     wire                end_shake_cnt    ;
  28.     reg                 end_shake_cnt_ff0;
  29.     reg   [3:0]         state_c          ;
  30.     reg   [19:0]        shake_cnt        ;
  31.     reg   [3:0]         state_n          ;
  32.     reg   [1:0]         row_index        ;
  33.     reg   [15:0]        row_cnt          ;
  34.     wire                col2row_start    ;
  35.     wire                row2del_start    ;
  36.     wire                del2wait_start   ;
  37.     wire                wait2col_start   ;
  38.     wire                add_row_cnt      ;
  39.     wire                end_row_cnt      ;
  40.     wire                add_shake_cnt    ;
  41.     wire                add_row_index    ;
  42.     wire                end_row_index    ;


  43. always  @(posedge clk or negedge rst_n)begin
  44.     if(rst_n==1'b0)begin
  45.         key_col_ff0 <= 4'b1111;
  46.         key_col_ff1 <= 4'b1111;
  47.     end
  48.     else begin
  49.         key_col_ff0 <= key_col    ;
  50.         key_col_ff1 <= key_col_ff0;
  51.     end
  52. end


  53. always @(posedge clk or negedge rst_n) begin
  54.     if (rst_n==0) begin
  55.         shake_cnt <= 0;
  56.     end
  57.     else if(add_shake_cnt) begin
  58.         if(end_shake_cnt)
  59.             shake_cnt <= 0;
  60.         else
  61.             shake_cnt <= shake_cnt+1 ;
  62.    end
  63. end
  64. assign add_shake_cnt = key_col_ff1!=4'hf;
  65. assign end_shake_cnt = add_shake_cnt  && shake_cnt == TIME_20MS-1 ;


  66. always  @(posedge clk or negedge rst_n)begin
  67.     if(rst_n==1'b0)begin
  68.         state_c <= CHK_COL;
  69.     end
  70.     else begin
  71.         state_c <= state_n;
  72.     end
  73. end

  74. always  @(*)begin
  75.     case(state_c)
  76.         CHK_COL: begin
  77.                      if(col2row_start )begin
  78.                          state_n = CHK_ROW;
  79.                      end
  80.                      else begin
  81.                          state_n = CHK_COL;
  82.                      end
  83.                  end
  84.         CHK_ROW: begin
  85.                      if(row2del_start)begin
  86.                          state_n = DELAY;
  87.                      end
  88.                      else begin
  89.                          state_n = CHK_ROW;
  90.                      end
  91.                  end
  92.         DELAY :  begin
  93.                      if(del2wait_start)begin
  94.                          state_n = WAIT_END;
  95.                      end
  96.                      else begin
  97.                          state_n = DELAY;
  98.                      end
  99.                  end
  100.         WAIT_END: begin
  101.                      if(wait2col_start)begin
  102.                          state_n = CHK_COL;
  103.                      end
  104.                      else begin
  105.                          state_n = WAIT_END;
  106.                      end
  107.                   end
  108.        default: state_n = CHK_COL;
  109.     endcase
  110. end
  111. assign col2row_start = state_c==CHK_COL  && end_shake_cnt;
  112. assign row2del_start = state_c==CHK_ROW  && row_index==3 && end_row_cnt;
  113. assign del2wait_start= state_c==DELAY    && end_row_cnt;
  114. assign wait2col_start= state_c==WAIT_END && key_col_ff1==4'hf;

  115. always  @(posedge clk or negedge rst_n)begin
  116.     if(rst_n==1'b0)begin
  117.         key_row <= 4'b0;
  118.     end
  119.     else if(state_c==CHK_ROW)begin
  120.         key_row <= ~(1'b1 << row_index);
  121.     end
  122.     else begin
  123.         key_row <= 4'b0;
  124.     end
  125. end





  126. always @(posedge clk or negedge rst_n) begin
  127.     if (rst_n==0) begin
  128.         row_index <= 0;
  129.     end
  130.     else if(add_row_index) begin
  131.         if(end_row_index)
  132.             row_index <= 0;
  133.         else
  134.             row_index <= row_index+1 ;
  135.    end
  136.    else if(state_c!=CHK_ROW)begin
  137.        row_index <= 0;
  138.    end
  139. end
  140. assign add_row_index = state_c==CHK_ROW && end_row_cnt;
  141. assign end_row_index = add_row_index  && row_index == 4-1 ;


  142. always @(posedge clk or negedge rst_n) begin
  143.     if (rst_n==0) begin
  144.         row_cnt <= 0;
  145.     end
  146.     else if(add_row_cnt) begin
  147.         if(end_row_cnt)
  148.             row_cnt <= 0;
  149.         else
  150.             row_cnt <= row_cnt+1 ;
  151.    end
  152. end
  153. assign add_row_cnt = state_c==CHK_ROW || state_c==DELAY;
  154. assign end_row_cnt = add_row_cnt  && row_cnt == 16-1 ;



  155. always  @(posedge clk or negedge rst_n)begin
  156.     if(rst_n==1'b0)begin
  157.         key_col_get <= 0;
  158.     end
  159.     else if(state_c==CHK_COL && end_shake_cnt ) begin
  160.         if(key_col_ff1==4'b1110)
  161.             key_col_get <= 0;
  162.         else if(key_col_ff1==4'b1101)
  163.             key_col_get <= 1;
  164.         else if(key_col_ff1==4'b1011)
  165.             key_col_get <= 2;
  166.         else
  167.             key_col_get <= 3;
  168.     end
  169. end


  170. always  @(posedge clk or negedge rst_n)begin
  171.     if(rst_n==1'b0)begin
  172.         key_out <= 0;
  173.     end
  174.     else if(state_c==CHK_ROW && end_row_cnt)begin
  175.         key_out <= {row_index,key_col_get};
  176.     end
  177.     else begin
  178.         key_out <= 0;
  179.     end
  180. end

  181. always  @(posedge clk or negedge rst_n)begin
  182.     if(rst_n==1'b0)begin
  183.         key_vld <= 1'b0;
  184.     end
  185.     else if(state_c==CHK_ROW && end_row_cnt && key_col_ff1[key_col_get]==1'b0)begin
  186.         key_vld <= 1'b1;
  187.     end
  188.     else begin
  189.         key_vld <= 1'b0;
  190.     end
  191. end


  192. always  @(*)begin
  193.     if(rst_n==1'b0)begin
  194.         key_en = 0;
  195.     end
  196.     else if(key_vld && key_out==0)begin
  197.         key_en = 4'b0001;
  198.     end
  199.     else if(key_vld && key_out==1)begin
  200.         key_en = 4'b0010;
  201.     end
  202.     else if(key_vld && key_out==2)begin
  203.         key_en = 4'b0100;
  204.     end
  205.     else begin
  206.         key_en = 0;
  207.     end
  208. 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)
  
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
低電(diàn)平複位信(xìn)号(hào)
Data_load
輸入(rù)
重(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è)位
Data_load_vld
輸入(rù)
重(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ù)
Key_num
輸入(rù)
按鍵位置輸入(rù)信(xìn)号(hào),key_vld有(yǒu)效时(shí),該信(xìn)号(hào)有(yǒu)效
Key_vld
輸入(rù)
按鍵值有(yǒu)效信(xìn)号(hào),为(wèi)1时(shí)表(biǎo)示檢测到(dào)一(yī)个(gè)按鍵
data_out
輸出(chū)
當前(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)碼

  1. module clock_data(
  2.     clk          ,
  3.     rst_n        ,
  4.     data_load    ,
  5.     data_load_vld,
  6.     key_en       ,
  7.     data_out   
  8.     );

  9.     parameter      TIME_1S    =       50_000_000   ;

  10.     input               clk          ;
  11.     input               rst_n        ;
  12.     input               data_load_vld;
  13.     input [23:0]        data_load    ;
  14.     input [ 3:0]        key_en       ;
  15.     output[23:0]        data_out     ;
  16.     wire  [23:0]        data_out     ;


  17.     reg   [25:0]        cnt_1s       ;
  18.     reg   [3:0]         miao_ge      ;
  19.     reg   [3:0]         miao_shi     ;
  20.     reg   [3:0]         fen_ge       ;
  21.     reg   [3:0]         fen_shi      ;
  22.     reg   [3:0]         shi_ge       ;
  23.     reg   [3:0]         shi_shi      ;
  24.     reg   [2:0]         set_sel      ;
  25.     reg                 set_flag     ;
  26.     wire                add_set_sel  ;
  27.     wire                add_cnt_1s   ;
  28.     wire                add_miao_ge  ;
  29.     wire                add_miao_shi ;
  30.     wire                add_fen_ge   ;
  31.     wire                add_fen_shi  ;
  32.     wire                add_shi_ge   ;
  33.     wire                add_shi_shi  ;
  34.     wire                end_cnt_1s   ;
  35.     wire                end_set_sel  ;
  36.     wire                end_miao_ge  ;
  37.     wire                end_miao_shi ;
  38.     wire                end_fen_ge   ;
  39.     wire                end_fen_shi  ;
  40.     wire                end_shi_ge   ;
  41.     wire                end_shi_shi  ;
  42.     wire                set_miao_ge  ;
  43.     wire                set_miao_shi ;
  44.     wire                set_fen_ge   ;
  45.     wire                set_fen_shi  ;
  46.     wire                set_shi_ge   ;
  47.     wire                set_shi_shi  ;

  48.     reg  [ 3:0]         x            ;
  49.     reg  [ 2:0]         y            ;

  50.     always  @(posedge clk or negedge rst_n)begin
  51.         if(rst_n==1'b0)begin
  52.             set_flag <= 1'b0;
  53.         end
  54.         else if(key_en[0]) begin
  55.             set_flag <= ~ set_flag;
  56.         end
  57.     end



  58.     always @(posedge clk or negedge rst_n)begin
  59.         if(!rst_n)begin
  60.             set_sel <= 0;
  61.         end
  62.         else if(add_set_sel)begin
  63.             if(end_set_sel)
  64.                 set_sel <= 0;
  65.             else
  66.                 set_sel <= set_sel + 1;
  67.         end
  68.         else if(set_flag==0)begin
  69.             set_sel <= 0;
  70.         end
  71.     end

  72.     assign add_set_sel = set_flag && key_en[1];      
  73.     assign end_set_sel = add_set_sel && set_sel==6-1 ;   

  74.     always @(posedge clk or negedge rst_n)begin
  75.         if(!rst_n)begin
  76.             cnt_1s <= 0;
  77.         end
  78.         else if(add_cnt_1s)begin
  79.             if(end_cnt_1s)
  80.                 cnt_1s <= 0;
  81.             else
  82.                 cnt_1s <= cnt_1s + 1;
  83.         end
  84.     end

  85.     assign add_cnt_1s = set_flag==0 ;      
  86.     assign end_cnt_1s = add_cnt_1s && cnt_1s==TIME_1S-1 ;   





  87.     always @(posedge clk or negedge rst_n)begin
  88.         if(!rst_n)begin
  89.             miao_ge <= 0;
  90.         end
  91.         else if(add_miao_ge)begin
  92.             if(end_miao_ge)
  93.                 miao_ge <= 0;
  94.             else
  95.                 miao_ge <= miao_ge + 1;
  96.         end
  97.         else if(data_load_vld)begin
  98.             miao_ge <=  data_load[3:0];
  99.         end
  100.     end

  101.     assign add_miao_ge = (end_cnt_1s || set_miao_ge) ;      
  102.     assign end_miao_ge = add_miao_ge && miao_ge==10-1 ;
  103.     assign set_miao_ge = set_flag    && set_sel==0 && key_en[2];   



  104.     always @(posedge clk or negedge rst_n)begin
  105.         if(!rst_n)begin
  106.             miao_shi <= 0;
  107.         end
  108.         else if(add_miao_shi)begin
  109.             if(end_miao_shi)
  110.                 miao_shi <= 0;
  111.             else
  112.                 miao_shi <= miao_shi + 1;
  113.         end
  114.         else if(data_load_vld)begin
  115.             miao_shi <= data_load[7:4];
  116.         end
  117.     end

  118.     assign add_miao_shi = (end_miao_ge || set_miao_shi);      
  119.     assign end_miao_shi = add_miao_shi && miao_shi==6-1;
  120.     assign set_miao_shi = set_flag     && set_sel==1 && key_en[2];   


  121.     always @(posedge clk or negedge rst_n)begin
  122.         if(!rst_n)begin
  123.             fen_ge <= 0;
  124.         end
  125.         else if(add_fen_ge)begin
  126.             if(end_fen_ge)
  127.                 fen_ge <= 0;
  128.             else
  129.                 fen_ge <= fen_ge + 1;
  130.         end
  131.         else if(data_load_vld)begin
  132.             fen_ge <= data_load[11:8];
  133.         end
  134.     end

  135.     assign add_fen_ge = (end_miao_shi || set_fen_ge);      
  136.     assign end_fen_ge = add_fen_ge && fen_ge==10-1;
  137.     assign set_fen_ge = set_flag     && set_sel==2 && key_en[2];   


  138.     always @(posedge clk or negedge rst_n)begin
  139.         if(!rst_n)begin
  140.             fen_shi <= 0;
  141.         end
  142.         else if(add_fen_shi)begin
  143.             if(end_fen_shi)
  144.                 fen_shi <= 0;
  145.             else
  146.                 fen_shi <= fen_shi + 1;
  147.         end
  148.         else if(data_load_vld)begin
  149.             fen_shi <= data_load[15:12];
  150.         end
  151.     end

  152.     assign add_fen_shi = (end_fen_ge || set_fen_shi);      
  153.     assign end_fen_shi = add_fen_shi && fen_shi==6-1;
  154.     assign set_fen_shi = set_flag     && set_sel==3 && key_en[2];   

  155.    always @(posedge clk or negedge rst_n)begin
  156.         if(!rst_n)begin
  157.             shi_ge <= 0;
  158.         end
  159.         else if(add_shi_ge)begin
  160.             if(end_shi_ge)
  161.                 shi_ge <= 0;
  162.             else
  163.                 shi_ge <= shi_ge + 1;
  164.         end
  165.         else if(data_load_vld)begin
  166.             shi_ge <= data_load[19:16];
  167.         end
  168.     end

  169.     assign add_shi_ge = (end_fen_shi || set_shi_ge);      
  170.     assign end_shi_ge = add_shi_ge && shi_ge==x-1;
  171.     assign set_shi_ge = set_flag     && set_sel==4 && key_en[2];   


  172.     always @(posedge clk or negedge rst_n)begin
  173.         if(!rst_n)begin
  174.             shi_shi <= 0;
  175.         end
  176.         else if(add_shi_shi)begin
  177.             if(end_shi_shi)
  178.                 shi_shi <= 0;
  179.             else
  180.                 shi_shi <= shi_shi + 1;
  181.         end
  182.         else if(data_load_vld)begin
  183.             shi_shi <= data_load[23:20];
  184.         end
  185.     end

  186.     assign add_shi_shi = (end_shi_ge || set_shi_shi);      
  187.     assign end_shi_shi = add_shi_shi && shi_shi==y-1;
  188.     assign set_shi_shi = set_flag     && set_sel==5 && key_en[2];   

  189.     always  @(*)begin
  190.         if(shi_shi<2)
  191.             x =  10;
  192.         else
  193.             x =   4;
  194.     end

  195.     always  @(*)begin
  196.         if(set_flag && set_sel==5 && shi_ge>=4)
  197.             y = 2;
  198.         else
  199.             y = 3;
  200.     end
  201.     assign data_out = {shi_shi,shi_ge,fen_shi,fen_ge,miao_shi,miao_ge};


  202. endmodule
複制代(dài)碼



1.4 數碼管(guǎn)顯示模块(kuài)設計(jì)

1.4.1接口(kǒu)信(xìn)号(hào)
  
信(xìn)号(hào)
  
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng),50MHz
rst_n
輸入(rù)
低電(diàn)平複位信(xìn)号(hào)
din
輸入(rù)
當前(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)
  
值。
Seg_sel
輸出(chū)
數碼管(guǎn)位選信(xìn)号(hào)
Segment
輸出(chū)
數碼管(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)碼
  1. always @(posedge clk or negedge rst_n)begin
  2.     if(!rst_n)begin
  3.         cnt_2ms <= 0;
  4.     end
  5.     else if(add_cnt_2ms)begin
  6.         if(end_cnt_2ms)
  7.             cnt_2ms <= 0;
  8.         else
  9.             cnt_2ms <= cnt_2ms + 1;
  10.     end
  11. end

  12. assign add_cnt_2ms = 1;      
  13. assign end_cnt_2ms = add_cnt_2ms && cnt_2ms==TIME_2MS-1 ;   

  14. always @(posedge clk or negedge rst_n)begin
  15.     if(!rst_n)begin
  16.         cnt_sel <= 0;
  17.     end
  18.     else if(add_cnt_sel)begin
  19.         if(end_cnt_sel)
  20.             cnt_sel <= 0;
  21.         else
  22.             cnt_sel <= cnt_sel + 1;
  23.     end
  24. end

  25. assign add_cnt_sel = end_cnt_2ms;      
  26. assign end_cnt_sel = add_cnt_sel && cnt_sel== SEG_NUM-1;   



  27. always  @(posedge clk or negedge rst_n)begin
  28.     if(rst_n==1'b0)begin
  29.         seg_sel <= {SEG_NUM{1'b1}};
  30.     end
  31.     else begin
  32.         seg_sel <= ~(1'b1 << cnt_sel);
  33.     end
  34. end

  35. always  @(posedge clk or negedge rst_n)begin
  36.     if(rst_n==1'b0)begin
  37.         din_ff0 <= 0;
  38.     end
  39.     else begin
  40.         for(ii=0;ii<SEG_NUM;ii=ii+1)begin
  41.             if(din_vld[ii]==1'b1)begin
  42.                 din_ff0[(ii+1)*4-1 -:4] <= din[(ii+1)*4-1 -:4];
  43.             end
  44.             else begin
  45.                 din_ff0[(ii+1)*4-1 -:4] <= din_ff0[(ii+1)*4-1 -:4];
  46.             end
  47.         end
  48.     end
  49. end

  50. always  @(*)begin
  51.     seg_tmp = din_ff0[(cnt_sel+1)*4-1 -:4];
  52. end


  53. always@(posedge clk or negedge rst_n)begin
  54.     if(rst_n==1'b0)begin
  55.         segment<=NUM_0;
  56.     end
  57.     else begin
  58.         case(seg_tmp)
  59.             4'd0:segment <= NUM_0;
  60.             4'd1:segment <= NUM_1;
  61.             4'd2:segment <= NUM_2;
  62.             4'd3:segment <= NUM_3;
  63.             4'd4:segment <= NUM_4;
  64.             4'd5:segment <= NUM_5;
  65.             4'd6:segment <= NUM_6;
  66.             4'd7:segment <= NUM_7;
  67.             4'd8:segment <= NUM_8;
  68.             4'd9:segment <= NUM_9;
  69.             default:begin
  70.                 segment <= NUM_ERR;
  71.             end
  72.         endcase
  73.     end
  74. end

  75. endmodul
複制代(dài)碼


1.5 數據(jù)处理模块(kuài)設計(jì)


1.5.1接口(kǒu)信(xìn)号(hào)
  
信(xìn)号(hào)
  
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
低電(diàn)平複位信(xìn)号(hào)
din
輸入(rù)
时(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)值
dout
輸出(chū)
用(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)值
dout_vld
輸出(chū)
时(shí)鐘(zhōng)加载有(yǒu)效指示信(xìn)号(hào),高(gāo)電(diàn)平有(yǒu)效
Start
輸出(chū)
对(duì)AT93C46進(jìn)行打(dǎ)開(kāi)写保護、写數據(jù)或(huò)者(zhě)读(dú)數據(jù)命令。注意(yì),在(zài)rdy=0时(shí),不(bù)應(yìng)該使start有(yǒu)效
mode
輸出(chū)
对(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)
addr
輸出(chū)
读(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)效
Wdata
輸出(chū)
写到(dào)AT93C46的(de)數據(jù),start=1,且mode=1时(shí),此(cǐ)值有(yǒu)效
rdy
輸入(rù)
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à)送命令
rdata
輸入(rù)
從AT93C46读(dú)取(qǔ)的(de)數據(jù)
rdata_vld
輸入(rù)
從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)碼
  1.     always  @(posedge clk or negedge rst_n)begin
  2.         if(rst_n==1'b0)begin
  3.             state_c <= S_EWEN;
  4.         end
  5.         else begin
  6.             state_c <= state_n;
  7.         end
  8.     end

  9.     always  @(*)begin
  10.         case(state_c)
  11.             S_EWEN : begin
  12.                 if(ewen2read_start)begin
  13.                     state_n = S_READ ;
  14.                 end
  15.                 else begin
  16.                     state_n = state_c;
  17.                 end
  18.             end
  19.             S_READ : begin
  20.                 if(read2idle_start)begin
  21.                     state_n = S_IDLE;
  22.                 end
  23.                 else begin
  24.                     state_n = state_c;
  25.                 end
  26.             end
  27.             S_IDLE : begin
  28.                 if(idle2write_start)begin
  29.                     state_n = S_WRITE;
  30.                 end
  31.                 else begin
  32.                     state_n = state_c;
  33.                 end
  34.             end
  35.             S_WRITE : begin
  36.                 if(write2idle_start)begin
  37.                     state_n = S_IDLE;
  38.                 end
  39.                 else begin
  40.                     state_n = state_c;
  41.                 end
  42.             end
  43.             default : begin
  44.                 state_n = S_EWEN;
  45.             end
  46.         endcase
  47.     end


  48.     assign   ewen2read_start  = state_c==S_EWEN  && add_time_cnt && time_cnt==1000-1 && rdy;
  49.     assign   read2idle_start  = state_c==S_READ  && end_rd_cnt      ;
  50.     assign   idle2write_start = state_c==S_IDLE  && end_time_cnt    ;
  51.     assign   write2idle_start = state_c==S_WRITE && end_wr_cnt      ;


  52.     always @(posedge clk or negedge rst_n)begin
  53.         if(!rst_n)begin
  54.             time_cnt <= 0;
  55.         end
  56.         else if(add_time_cnt)begin
  57.             if(end_time_cnt)
  58.                 time_cnt <= 0;
  59.             else
  60.                 time_cnt <= time_cnt + 1;
  61.         end
  62.     end

  63.     assign add_time_cnt = 1;      
  64.     assign end_time_cnt = add_time_cnt && time_cnt==TIME_1S-1 ;   


  65.     always @(posedge clk or negedge rst_n)begin
  66.         if(!rst_n)begin
  67.             wr_cnt <= 0;
  68.         end
  69.         else if(add_wr_cnt)begin
  70.             if(end_wr_cnt)
  71.                 wr_cnt <= 0;
  72.             else
  73.                 wr_cnt <= wr_cnt + 1;
  74.         end
  75.     end

  76.     assign add_wr_cnt = state_c==S_WRITE && rdy;
  77.     assign end_wr_cnt = add_wr_cnt && wr_cnt == WR_NUM-1 ;


  78.     always @(posedge clk or negedge rst_n)begin
  79.         if(!rst_n)begin
  80.             rd_cnt <= 0;
  81.         end
  82.         else if(add_rd_cnt)begin
  83.             if(end_rd_cnt)
  84.                 rd_cnt <= 0;
  85.             else
  86.                 rd_cnt <= rd_cnt + 1;
  87.         end
  88.     end

  89.     assign add_rd_cnt = state_c==S_READ && crc_dout_vld;
  90.     assign end_rd_cnt = add_rd_cnt && rd_cnt == RD_NUM-1 ;


  91.     assign start_read = state_c==S_READ && flag_wait_crc==0 && rdy;

  92.     always  @(posedge clk or negedge rst_n)begin
  93.         if(rst_n==1'b0)begin
  94.             flag_wait_crc <= 0;
  95.         end
  96.         else if(start_read)begin
  97.             flag_wait_crc <= 1;
  98.         end
  99.         else if(crc_dout_vld)begin
  100.             flag_wait_crc <= 0;
  101.         end
  102.     end

  103.     always  @(posedge clk or negedge rst_n)begin
  104.         if(rst_n==1'b0)begin
  105.             mode <= EWEN;
  106.         end
  107.         else if(state_c==S_EWEN) begin
  108.             mode <= EWEN;
  109.         end
  110.         else if(state_c==S_WRITE)begin
  111.             mode <= WRITE;
  112.         end
  113.         else if(state_c==S_READ)begin
  114.             mode <= READ;
  115.         end
  116.     end



  117.     always  @(posedge clk or negedge rst_n)begin
  118.         if(rst_n==1'b0)begin
  119.             crc_din <= 0;
  120.         end
  121.         else if(add_wr_cnt && end_wr_cnt==0) begin
  122.             crc_din <= din[8*(D_LEN-wr_cnt)-1 -:8];
  123.         end
  124.         else begin
  125.             crc_din <= rdata;
  126.         end
  127.     end

  128.     always  @(posedge clk or negedge rst_n)begin
  129.         if(rst_n==1'b0)begin
  130.             crc_din_vld <= 1'b0;
  131.         end
  132.         else if(add_wr_cnt && end_wr_cnt==0) begin
  133.             crc_din_vld <= 1'b1;
  134.         end
  135.         else begin
  136.             crc_din_vld <= rdata_vld;
  137.         end
  138.     end

  139.     always  @(posedge clk or negedge rst_n)begin
  140.         if(rst_n==1'b0)begin
  141.             crc_clr <= 1'b0;
  142.         end
  143.         else if((add_rd_cnt && rd_cnt==4-1)|| read2idle_start || write2idle_start) begin
  144.             crc_clr <= 1'b1;
  145.         end
  146.         else begin
  147.             crc_clr <= 1'b0;
  148.         end
  149.     end

  150.     always  @(posedge clk or negedge rst_n)begin
  151.         if(rst_n==1'b0)begin
  152.             addr <= 0;
  153.         end
  154.         else if(state_c==S_WRITE) begin
  155.             addr <= {4'b0,write_sel,wr_cnt[1:0]};
  156.         end
  157.         else if(state_c==S_EWEN) begin
  158.             addr <= 7'b1100000;
  159.         end
  160.         else begin
  161.             addr <= {4'b0,rd_cnt};
  162.         end
  163.     end

  164.     always  @(posedge clk or negedge rst_n)begin
  165.         if(rst_n==1'b0)begin
  166.             write_sel <= 1'b0;
  167.         end
  168.         else if(write2idle_start) begin
  169.             write_sel <= ~write_sel;
  170.         end
  171.     end

  172.   


  173.     always  @(posedge clk or negedge rst_n)begin
  174.         if(rst_n==1'b0)begin
  175.             wdata <= 0;
  176.         end
  177.         else if(wr_cnt==WR_NUM-1) begin
  178.             wdata <= crc_dout;
  179.         end
  180.         else begin
  181.             wdata <= din[8*(D_LEN-wr_cnt)-1 -:8];
  182.         end
  183.     end

  184.     always  @(posedge clk or negedge rst_n)begin
  185.         if(rst_n==1'b0)begin
  186.             start <= 1'b0;
  187.         end
  188.         else if(add_wr_cnt || start_read || ewen2read_start)begin
  189.             start <= 1'b1;
  190.         end
  191.         else begin
  192.             start <= 1'b0;
  193.         end
  194.     end

  195.     always  @(posedge clk or negedge rst_n)begin
  196.         if(rst_n==1'b0)begin
  197.             dout_temp<= 0;
  198.         end
  199.         else if(rdata_vld) begin
  200.             dout_temp[(8-rd_cnt)*8-1 -:8] <= rdata;
  201.         end
  202.     end

  203.     always  @(posedge clk or negedge rst_n)begin
  204.         if(rst_n==1'b0)begin
  205.             dout0_err <= 1'b0;
  206.         end
  207.         else if(add_rd_cnt && rd_cnt==4-1) begin
  208.             if(crc_dout!=0)
  209.                 dout0_err <= 1'b1;
  210.             else
  211.                 dout0_err <= 1'b0;
  212.         end
  213.     end

  214.     always  @(*)begin
  215.         if(crc_dout!=0)
  216.             dout1_err = 1'b1;
  217.         else
  218.             dout1_err = 1'b0;
  219.     end


  220.     assign dout0_temp = dout_temp[8*8-1 -:24];
  221.     assign dout1_temp = dout_temp[4*8-1 -:24];



  222.    
  223.     always  @(posedge clk or negedge rst_n)begin
  224.         if(rst_n==1'b0)begin
  225.             dout <= 0;
  226.         end
  227.         else if(end_rd_cnt) begin
  228.             if(dout0_err==1'b0 && dout1_err==1'b0)begin
  229.                 if(dout0_temp > dout1_temp)
  230.                     dout <= dout0_temp;
  231.                 else
  232.                     dout <= dout1_temp;
  233.             end
  234.             else if(dout0_err==1'b0)begin
  235.                 dout <= dout0_temp;
  236.             end
  237.             else begin
  238.                 dout <= dout1_temp;
  239.             end
  240.         end
  241.     end


  242.     always  @(posedge clk or negedge rst_n)begin
  243.         if(rst_n==1'b0)begin
  244.             dout_vld <= 1'b0;
  245.         end
  246.         else if(end_rd_cnt) begin
  247.             if(dout0_err && dout1_err)begin
  248.                 dout_vld <= 1'b0;
  249.             end
  250.             else begin
  251.                 dout_vld <= 1'b1;
  252.             end
  253.         end
  254.         else begin
  255.             dout_vld <= 1'b0;
  256.         end
  257.     end


  258.    crc8_d8 u_crc8_d8(
  259.               .clk      (clk          ),
  260.               .rst_n    (rst_n        ),
  261.               .clr      (crc_clr      ),
  262.               .din_vld  (crc_din_vld  ),
  263.               .din      (crc_din      ),
  264.               .dout_vld (crc_dout_vld ),
  265.               .dout     (crc_dout     )      
  266.     );
複制代(dài)碼


1.6 CRC处理模块(kuài)設計(jì)


1.6.1接口(kǒu)信(xìn)号(hào)
  
信(xìn)号(hào)
  
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
低電(diàn)平複位信(xìn)号(hào)
Clr
輸入(rù)
清(qīng)零(líng)信(xìn)号(hào),将當前(qián)的(de)CRC運算複位,重(zhòng)新開(kāi)始新的(de)運算。
din_vld
輸入(rù)
CRC輸入(rù)數據(jù)有(yǒu)效信(xìn)号(hào)
din
輸入(rù)
CRC運算輸入(rù)的(de)數據(jù)
dout
輸出(chū)
CRC運算結果(guǒ)
dout_vld
輸出(chū)
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)碼
  1.     assign d   =    din    ;
  2.     assign c   =    dout   ;


  3.     always  @(posedge clk or negedge rst_n)begin
  4.         if(rst_n==1'b0)begin
  5.             dout <= 0;
  6.         end
  7.         else if(clr)begin
  8.             dout <= 0;
  9.         end
  10.         else if(din_vld) begin
  11.             dout[0] <= d[7] ^ d[6] ^ d[0] ^ c[0] ^ c[6] ^ c[7];
  12.             dout[1] <= d[6] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[6];
  13.             dout[2] <= d[6] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[6];
  14.             dout[3] <= d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[3] ^ c[7];
  15.             dout[4] <= d[4] ^ d[3] ^ d[2] ^ c[2] ^ c[3] ^ c[4];
  16.             dout[5] <= d[5] ^ d[4] ^ d[3] ^ c[3] ^ c[4] ^ c[5];
  17.             dout[6] <= d[6] ^ d[5] ^ d[4] ^ c[4] ^ c[5] ^ c[6];
  18.             dout[7] <= d[7] ^ d[6] ^ d[5] ^ c[5] ^ c[6] ^ c[7];
  19.         end
  20.     end

  21.     always  @(posedge clk or negedge rst_n)begin
  22.         if(rst_n==1'b0)begin
  23.             dout_vld <= 0;
  24.         end
  25.         else begin
  26.             dout_vld <= din_vld;
  27.         end
  28.     end

  29. endmodul
複制代(dài)碼


1.7 AT93C46接口(kǒu)模块(kuài)設計(jì)


1.7.1接口(kǒu)信(xìn)号(hào)
  
信(xìn)号(hào)
  
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
低電(diàn)平複位信(xìn)号(hào)
addr
輸入(rù)
地(dì)址信(xìn)号(hào),在(zài)start有(yǒu)效时(shí),此(cǐ)值有(yǒu)效
Wdata
輸入(rù)
写數據(jù)信(xìn)号(hào),在(zài)start有(yǒu)效时(shí),此(cǐ)值有(yǒu)效
start
輸入(rù)
開(kāi)始命令,僅在(zài)rdy=1时(shí)才有(yǒu)效
mode
輸出(chū)
操作模式指示信(xìn)号(hào),start有(yǒu)效时(shí),此(cǐ)值有(yǒu)效
rdy
輸入(rù)
準備好(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)效
rdata
輸入(rù)
從AT93C46读(dú)取(qǔ)的(de)數據(jù)
rdata_vld
輸出(chū)
從AT93C46读(dú)到(dào)的(de)數據(jù)有(yǒu)效指示信(xìn)号(hào)
do
輸出(chū)
AT93C46數據(jù)輸出(chū)
di
輸出(chū)
AT93C46數據(jù)輸入(rù)
cs
輸出(chū)
AT93C46片(piàn)選信(xìn)号(hào)
sk
輸出(chū)
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),等待TWP5ms)时(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ì)數器cnt2flag_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)10EWEN)、18READ和(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)2EWEN和(hé)READ)、3WRITE)。

除了(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)指令集,将SBOpcodeAddress和(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)碼
  1.     assign start_vld = flag_work==0 && start;

  2.     always  @(*)begin
  3.         if(mode==EWEN)
  4.             opcode = 3'b100;
  5.         else if(mode==WRITE)
  6.             opcode = 3'b101;
  7.         else
  8.             opcode = 3'b110;
  9.     end

  10.     always  @(posedge clk or negedge rst_n)begin
  11.         if(rst_n==1'b0)begin
  12.             dout <= 0;
  13.         end
  14.         else if(start_vld) begin
  15.             dout <={opcode,addr,wdata};
  16.         end
  17.     end


  18.     always  @(posedge clk or negedge rst_n)begin
  19.         if(rst_n==1'b0)begin
  20.             mode_reg <= 0;
  21.         end
  22.         else if(start_vld) begin
  23.             mode_reg <= mode;
  24.         end
  25.     end

  26.     always  @(posedge clk or negedge rst_n)begin
  27.         if(rst_n==1'b0)begin
  28.             flag_work <= 0;
  29.         end
  30.         else if(start_vld) begin
  31.             flag_work <= 1;
  32.         end
  33.         else if(end_cnt2)begin
  34.             flag_work <= 0;
  35.         end
  36.     end


  37.    
  38.     always @(posedge clk or negedge rst_n)begin
  39.         if(!rst_n)begin
  40.             cnt0 <= 0;
  41.         end
  42.         else if(add_cnt0)begin
  43.             if(end_cnt0)
  44.                 cnt0 <= 0;
  45.             else
  46.                 cnt0 <= cnt0 + 1;
  47.         end
  48.     end

  49.     assign add_cnt0 = flag_work;      
  50.     assign end_cnt0 = add_cnt0 && cnt0== x-1;   

  51.     always @(posedge clk or negedge rst_n)begin
  52.         if(!rst_n)begin
  53.             cnt1 <= 0;
  54.         end
  55.         else if(add_cnt1)begin
  56.             if(end_cnt1)
  57.                 cnt1 <= 0;
  58.             else
  59.                 cnt1 <= cnt1 + 1;
  60.         end
  61.     end

  62.     assign add_cnt1 = end_cnt0;      
  63.     assign end_cnt1 = add_cnt1 && cnt1==y-1 ;


  64.     always @(posedge clk or negedge rst_n)begin
  65.         if(!rst_n)begin
  66.              cnt2 <= 0;
  67.          end
  68.          else if(add_cnt2)begin
  69.              if(end_cnt2)
  70.                   cnt2 <= 0;
  71.              else
  72.                   cnt2 <= cnt2 + 1;
  73.           end
  74.     end
  75.    
  76.     assign add_cnt2 = end_cnt1;      
  77.     assign end_cnt2 = add_cnt2 && cnt2==u-1;   


  78.     assign en_sk1 = add_cnt0 && cnt0==x/2-1 && cnt2==1-1;
  79.     assign en_sk0 = end_cnt0                            ;
  80.     always  @(posedge clk or negedge rst_n)begin
  81.         if(rst_n==1'b0)begin
  82.             sk <= 0;
  83.         end
  84.         else if(add_cnt0 && cnt0==x/2-1 && cnt2==1-1)begin
  85.             sk <= 1;
  86.         end
  87.         else if(end_cnt0)begin
  88.             sk <= 0;
  89.         end
  90.     end

  91.     assign en_di = add_cnt0 && cnt0==1-1 && cnt2==1-1;

  92.     always  @(posedge clk or negedge rst_n)begin
  93.         if(rst_n==1'b0)begin
  94.             di <= 0;
  95.         end
  96.         else if(en_di) begin
  97.             di <= dout[17-cnt1];
  98.         end
  99.     end


  100.     always  @(posedge clk or negedge rst_n)begin
  101.         if(rst_n==1'b0)begin
  102.             cs <= 0;
  103.         end
  104.         else if(start_vld==1 || (add_cnt2 && cnt2==2-1 && end_cnt2==0)) begin
  105.             cs <= 1;
  106.         end
  107.         else if((add_cnt2 && cnt2==1-1) || end_cnt2)begin
  108.             cs <= 0;
  109.         end
  110.     end


  111.     always  @(posedge clk or negedge rst_n)begin
  112.         if(rst_n==1'b0)begin
  113.             rdata <= 0;
  114.         end
  115.         else if(end_cnt0 && cnt1 >=10 && cnt2==1-1 && mode_reg==READ ) begin
  116.             rdata[17-cnt1] <= do;
  117.         end
  118.     end

  119.     always  @(posedge clk or negedge rst_n)begin
  120.         if(rst_n==1'b0)begin
  121.             rdata_vld <= 0;
  122.         end
  123.         else begin
  124.             rdata_vld <= end_cnt2 && mode_reg==READ;
  125.         end
  126.     end

  127.     always  @(*)begin
  128.         if(start || flag_work)
  129.             rdy = 1'b0;
  130.         else
  131.             rdy = 1'b1;
  132.     end


  133.     always  @(*)begin
  134.         if(mode_reg==WRITE && cnt2==1-1)begin
  135.             x = 250;
  136.             y =  18;
  137.             u =   3;  
  138.         end
  139.         else if(mode_reg==WRITE && (cnt2==2-1 ))begin
  140.             x = 250 ;
  141.             y =   1 ;
  142.             u =   3 ;  
  143.         end
  144.         else if(mode_reg==WRITE && cnt2==3-1)begin
  145.             x = 500000;  
  146.             y =   1 ;
  147.             u =   3 ;  
  148.         end
  149.         else if(mode_reg==READ && cnt2==1-1)begin
  150.             x = 250;
  151.             y =  18;
  152.             u =   2;  
  153.         end
  154.         else if(mode_reg==READ && cnt2==2-1)begin
  155.             x = 250 ;
  156.             y =   1 ;
  157.             u =   2 ;  
  158.         end
  159.         else if(mode_reg==EWEN && cnt2==1-1)begin
  160.             x = 250;
  161.             y =  10;
  162.             u =   2;  
  163.         end
  164.         else begin
  165.             x = 250 ;  
  166.             y =   1 ;
  167.             u =   2 ;  
  168.         end
  169.     end


  170. 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à)载学習。

   拓展(zhǎn)閱读(dú)
⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ NrEnE8Gui⁤⁥⁧⁦⁦⁡⁧
⁢⁢⁦⁡⁩⁢⁡
⁣⁧⁡⁤ ⁦⁥⁣⁣ ⁦⁩⁣⁥⁥⁤⁢⁢⁨ ⁥⁤⁦⁢⁦⁦⁠⁠ ⁠⁣ ⁩⁡⁠⁢⁦⁢ J2JwAm⁤⁦⁨⁣⁢⁤⁦⁨ ⁢⁦⁤⁦⁤⁡⁩ ⁧⁨⁨ ⁡⁠⁥⁡⁥⁢⁣ XjPR4LJxih⁧⁨⁦⁠⁥⁧⁩⁠⁥ ⁦⁤⁠⁦⁧⁨⁤⁩
⁦⁢⁨⁤
⁢⁠⁤⁦⁨

⁩⁩⁡

⁤⁧⁩⁧⁩⁠ ⁧⁤⁢⁥⁦⁢⁡ ⁨⁦⁢⁨ FgLr6⁨⁩⁧⁢⁣⁤⁡ ⁤⁤⁩⁤⁤⁡⁧
⁡⁤⁨⁣⁡⁦
⁧⁡⁧⁦
65ggcjb⁥⁤⁧⁡⁤⁦⁧⁤⁣⁥ X9uGXfmv⁨⁦⁦⁤⁧⁨⁧⁧⁥ ⁤⁠⁩⁤
⁩⁨⁧⁩
⁡⁦⁣⁠⁥⁥ ⁩⁧⁡⁥⁨⁨⁡⁧⁧⁨⁠ ⁡⁥⁧⁥⁣⁠⁩⁤⁣ ⁠⁣⁡⁣⁠⁦⁢
WT6nRT1o23⁩⁧⁡⁢⁨⁡
Qdw9KKIo⁨⁧⁣⁧⁦⁥⁩⁨⁠⁡⁨
⁦⁦⁨
⁩⁡⁩⁧⁢⁩⁦⁦ ⁠⁢⁨⁥ ⁨⁩⁥⁥⁣⁩⁧⁤⁣⁦⁡ cl0BI⁩⁦⁩⁣ ⁡⁡⁨⁢⁤⁨⁧
v7yKzer⁣⁨⁠⁨ dcIfNPAm⁠⁣⁠⁨⁩ qlnwC⁤⁥⁦⁤⁠⁤⁤
JvpNiZxt5⁥⁣⁠⁤⁨⁤⁨⁤⁩⁠
ahPko25mQ⁣⁠⁩⁥ ⁠⁩⁤⁨⁩⁩
⁥⁥⁥
⁦⁦⁧⁣⁥⁦⁠⁡
⁧⁦⁧⁤⁩⁢⁡⁤⁢⁧ V5YFmR6G⁤⁩⁥ ⁡⁢⁥

⁧⁨⁡⁩⁣⁡⁥

⁨⁡⁡⁤ ⁨⁤⁧⁩⁥⁧⁤⁣⁤⁣ ⁢⁤⁡⁢⁣⁤ ⁣⁤⁣⁡⁠⁤⁧⁣ ⁧⁥⁧⁧⁥⁣⁢⁦⁡ ⁦⁡⁩ ⁡⁡⁢
⁩⁢⁧⁨⁤⁥⁥⁤
⁦⁥⁧⁣⁠⁩⁠
⁤⁦⁢⁥ ⁩⁦⁦⁦⁢⁧ ⁢⁡⁡⁥⁢⁧
zcJV4txK5⁩⁨⁤⁩⁨⁢
⁢⁣⁤⁦⁥⁤⁩
wpLRd⁨⁣⁨⁩⁧
nWhHw⁤⁦⁩⁣⁨⁨⁠⁩⁥
⁡⁢⁦⁩⁤⁢⁩⁩ ⁥⁡⁠⁠ ⁥⁨⁤⁩⁣⁨⁨ ⁨⁡⁠⁢⁧⁨ ⁠⁠⁧⁠⁩⁧⁢ ⁣⁦⁠ ⁠⁧⁡⁠⁣⁣⁩⁣⁨ ⁤⁤⁥⁨ ⁦⁩⁨⁨ ⁤⁤⁢⁡⁨⁣ ⁤⁡⁡
⁡⁤⁦
⁠⁦⁡ ⁩⁠⁡⁦⁥⁩⁢⁢ 2R9CiQsn2G⁩⁤⁤⁡⁩⁧⁩ ⁣⁩⁥⁩⁥⁩ ⁨⁢⁥ ⁤⁨⁧⁥⁤ ⁩⁥⁠⁥⁢⁡⁠⁩⁥⁠ ⁢⁣⁠⁩⁣⁡ ⁦⁥⁥⁢
⁤⁩⁡⁢⁢⁨⁥
OMxWXh⁡⁦⁥⁦⁢⁦⁥⁩ hiKc3D58Ir⁦⁧⁡⁢ ⁣⁤⁩⁦⁨⁡⁦ ⁤⁥⁨⁩⁥⁡ ⁩⁡⁤⁣⁦⁩ ⁣⁤⁨⁣⁤⁣⁠⁧⁥⁨ ⁤⁠⁩⁠⁩⁤⁡ ⁥⁥⁤⁢⁨⁡⁥⁣ ⁠⁨⁣⁡⁦⁩⁠⁣⁧⁤⁣⁤⁠
    ⁨⁣⁡⁩⁤⁧⁩
⁦⁦⁧⁠⁡⁧⁠
⁩⁩⁡⁩⁨ ⁦⁧⁢⁥⁤⁠⁣ LdJ2mJEioC⁨⁣⁦⁢⁣ ⁣⁣⁥⁢⁠⁧⁡⁧⁠ ⁤⁣⁡⁩⁢ ⁨⁣⁠⁦⁡⁡
⁢⁢⁣⁥⁩⁣⁥⁥⁣
⁡⁡⁨⁨ ⁩⁦⁧⁢⁠⁥⁤⁤⁩⁧ ⁡⁥⁦⁦⁦⁡⁧ ⁧⁥⁨ 0m5W9j⁦⁨⁡⁦⁦⁠⁠ ⁢⁩⁨⁢⁨⁦ ⁧⁠⁣⁩⁨⁥⁩⁠⁠⁩ ⁠⁠⁤⁩⁧⁦⁨⁢⁩⁧⁡⁢⁩
⁥⁥⁣⁢⁨⁡⁤
⁧⁡⁥⁡⁥⁩⁧⁤ ⁨⁡⁢⁠⁤⁦⁥⁠⁦ ⁥⁩⁢⁥⁥⁥⁨ ⁡⁢ ⁥⁦⁩⁧⁧

⁡⁦⁣⁥⁤⁧⁡

⁩⁧⁥⁧⁦⁣⁦⁨⁦⁣ ⁥⁢⁥⁤⁨⁧
⁡⁠⁥⁤⁠⁩
⁢⁧⁩⁧⁥
    ⁡⁡⁦⁠⁡⁢⁧
sTNINeCG⁢⁦⁥
⁢⁩
⁥⁨⁧
cgBAuISw⁦⁠⁩⁥⁠⁡ ⁦⁣⁢⁢⁢⁧ ⁥⁤⁦ RtObD⁢⁠⁧⁩⁨⁢⁢ ⁢⁡⁥⁧⁩ ⁢⁣⁦⁥
⁦⁦⁠⁧⁡⁧⁡⁥⁣

⁢⁢⁣⁣⁥

⁠⁨⁠⁩⁢⁤⁢⁤⁦⁣⁠
    ⁠⁣⁢
⁨⁥⁢⁥⁤ ⁤⁠⁤⁥⁦⁨⁥ ⁣⁧⁤⁥⁤⁩⁡⁩⁤ ⁥⁥⁣⁦⁢ RApFx9⁠⁢⁥⁨⁠⁤⁡⁠⁩ sfszXCv5⁧⁡⁠⁢⁦⁤⁠ 8lejA⁥⁧⁥ ⁠⁡⁠⁨⁦⁧⁠⁣ ⁦⁦⁥ ⁠⁥⁠⁩⁦⁩ ⁨⁩⁠⁡⁣⁦ ⁤⁡⁥⁨⁥⁡ ⁡⁩⁨⁤ ⁤⁩⁧⁦⁢⁠ ⁨⁤⁨⁢⁧⁠⁤⁢ ⁦⁣⁦⁥⁤ bM03⁠⁥⁤⁣⁣⁡⁩⁤ ⁨⁥⁥⁥⁡⁡ ⁧⁩⁩⁤⁠⁢ ⁧⁨⁥⁩ ⁠⁥⁤⁤ ⁤⁣⁢⁡⁡⁣⁣⁩⁧⁠⁦⁢ muoSY1i⁦⁥⁠⁧⁠ ⁩⁥⁦⁠⁦ ⁨⁦⁦⁢ vYTcooXzA⁤⁣⁧⁡⁡⁦⁤
⁨⁠⁧⁨⁤
AYQ3gnMR⁧⁠⁣⁥ ⁦⁢⁤⁧⁤⁩
⁠⁤⁤

xDsToeNDG7⁥⁠⁢

⁧⁨⁥⁨