日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > ZYNQ


狀態(tài)機(jī)是邏輯設(shè)計(jì)的重要內(nèi)容,狀態(tài)機(jī)的設(shè)計(jì)水平直接反應(yīng)工程師的邏輯功底,所以很多公司在硬件工程師及邏輯工程師面試中,狀態(tài)機(jī)設(shè)計(jì)幾乎是必選題目。本篇在引入狀態(tài)機(jī)設(shè)計(jì)思想的基礎(chǔ)上,重點(diǎn)討論如何寫好狀態(tài)機(jī)。由于篇幅比較長,如何寫好狀態(tài)機(jī)分成三篇呈現(xiàn)。話不多說,上貨。

主要內(nèi)容預(yù)覽:

  • 狀態(tài)機(jī)的基本概念;
  • 如何寫好狀態(tài)機(jī);
  • 使用 Synplify Pro 分析 FSM。
  • 狀態(tài)機(jī)的基本概念;
  • 如何寫好狀態(tài)機(jī);
  • 使用 Synplify Pro 分析 FSM。
  • 狀態(tài)機(jī)的基本概念;
  • 如何寫好狀態(tài)機(jī);
  • 使用 Synplify Pro 分析 FSM。



狀態(tài)機(jī)的基本概念


狀態(tài)機(jī)是一種思想方法

相信大多數(shù)工科學(xué)生在學(xué)習(xí)數(shù)字電路時(shí)都學(xué)習(xí)過狀態(tài)機(jī)的基本概念,了解一些使用狀態(tài)機(jī)描述時(shí)序電路的基本方法。但是,筆者希望大家能擴(kuò)展思維,認(rèn)識(shí)到狀態(tài)機(jī)不僅僅是一種時(shí)序電路設(shè)計(jì)工具,它更是一種思想方法。

我們先看下面一個(gè)簡單的例子。在大學(xué)生活中,某學(xué)生的在校的學(xué)習(xí)生活可以簡單地概括為宿舍、教室、食堂之間的周而復(fù)始,用下圖就可以形象地表現(xiàn)出來。這里畫這張圖,并不是要討論這個(gè)學(xué)生是否是一個(gè)“乖乖”類型學(xué)生,請(qǐng)大家注意,如果將圖中的“地點(diǎn)”認(rèn)為是“狀態(tài)”,將“功能”認(rèn)為是狀態(tài)的“輸出”,這張圖就是一張標(biāo)準(zhǔn)的狀態(tài)轉(zhuǎn)移圖,也就是說,我們用狀態(tài)機(jī)的方式清晰地描述了這個(gè)學(xué)生的在校生活方式。

圖1-1 一位學(xué)生在校生活狀態(tài)轉(zhuǎn)移圖


圖1-2 另一位學(xué)生在校生活狀態(tài)轉(zhuǎn)移圖


同樣如果將圖中的“地點(diǎn)”認(rèn)為是“狀態(tài)”,將“功能”認(rèn)為是狀態(tài)的“輸出”,將“條件”認(rèn)為是狀態(tài)轉(zhuǎn)移的“輸入條件”,圖 6-2 也是一張標(biāo)準(zhǔn)的狀態(tài)轉(zhuǎn)移圖,通過狀態(tài)機(jī)的方式我們?cè)俅吻逦孛枋隽硪粋€(gè)學(xué)生的在校生活方式。

事實(shí)上使用狀態(tài)機(jī)方式,我們可以細(xì)致入微地描述任何一個(gè)學(xué)生的在校生活方式。大家通過前面兩個(gè)簡單舉例已經(jīng)發(fā)現(xiàn)狀態(tài)機(jī)特別適合描述那些有發(fā)生有先后順序,或者有邏輯規(guī)律的事情——其實(shí)這就是狀態(tài)機(jī)的本質(zhì)。狀態(tài)機(jī)的本質(zhì)就是對(duì)具有邏輯順序或時(shí)序規(guī)律事件的一種描述方法。這個(gè)論斷的最重要的兩個(gè)詞就是“邏輯順序”和“時(shí)序規(guī)律”,這兩點(diǎn)就是狀態(tài)機(jī)所要描述的核心和強(qiáng)項(xiàng),換言之,所有具有邏輯順序和時(shí)序規(guī)律的事情都適合用狀態(tài)機(jī)描述。

很多初學(xué)者不知道何時(shí)應(yīng)用狀態(tài)機(jī)。這里介紹兩種應(yīng)用思路:第一種思路,從狀態(tài)變量入手。如果一個(gè)電路具有時(shí)序規(guī)律或者邏輯順序,我們就可以自然而然地規(guī)劃出狀態(tài),從這些狀態(tài)入手,分析每個(gè)狀態(tài)的輸入,狀態(tài)轉(zhuǎn)移和輸出,從而完成電路功能;第二種思路是首先明確電路的輸出的關(guān)系,這些輸出相當(dāng)于狀態(tài)的輸出,回溯規(guī)劃每個(gè)狀態(tài),和狀態(tài)轉(zhuǎn)移條件與狀態(tài)輸入。無論那種思路,使用狀態(tài)機(jī)的目的都是要控制某部分電路,完成某種具有邏輯順序或時(shí)序規(guī)律的電路設(shè)計(jì)。

其實(shí)對(duì)于邏輯電路而言,小到一個(gè)簡單的時(shí)序邏輯,大到復(fù)雜的微處理器,都適合用狀態(tài)機(jī)方法進(jìn)行描述。請(qǐng)讀者打開思路,不要僅僅局限于時(shí)序邏輯,發(fā)現(xiàn)電路的內(nèi)在規(guī)律,確認(rèn)電路的“狀態(tài)變量”,大膽使用狀態(tài)機(jī)描述電路模型。由于狀態(tài)機(jī)不僅僅是一種電路描述工具,它更是一種思想方法,而且狀態(tài)機(jī)的 HDL 語言表達(dá)方式比較規(guī)范,有章可循,所以很多有經(jīng)驗(yàn)的設(shè)計(jì)者習(xí)慣用狀態(tài)機(jī)思想進(jìn)行邏輯設(shè)計(jì),對(duì)各種復(fù)雜設(shè)計(jì)都套用狀態(tài)機(jī)的設(shè)計(jì)理念,從而提高設(shè)計(jì)的效率和穩(wěn)定性。



狀態(tài)機(jī)基本要素與分類

狀態(tài)機(jī)的基本要素有 3 個(gè),分別是:狀態(tài)、輸出和輸入。

  • 狀態(tài):也叫狀態(tài)變量。在邏輯設(shè)計(jì)中,使用狀態(tài)劃分邏輯順序和時(shí)序規(guī)律。比如:設(shè)計(jì)偽隨機(jī)碼發(fā)生器時(shí),可以用移位寄存器序列作為狀態(tài);在設(shè)計(jì)電機(jī)控制電路時(shí),可以以電機(jī)的不同轉(zhuǎn)速作為狀態(tài);在設(shè)計(jì)通信系統(tǒng)時(shí),可以用信令的狀態(tài)作為狀態(tài)變量等。
  • 輸出:輸出指在某一個(gè)狀態(tài)時(shí)特定發(fā)生的事件。如設(shè)計(jì)電機(jī)控制電路中,如果電機(jī)轉(zhuǎn)速過高,則輸出為轉(zhuǎn)速過高報(bào)警,也可以伴隨減速指令或降溫措施等。
  • 輸入指狀態(tài)機(jī)中進(jìn)入每個(gè)狀態(tài)的條件,有的狀態(tài)機(jī)沒有輸入條件,其中的狀態(tài)轉(zhuǎn)移較為簡單,有的狀態(tài)機(jī)有輸入條件,當(dāng)某個(gè)輸入條件存在時(shí)才能轉(zhuǎn)移到相應(yīng)的狀態(tài)。


根據(jù)狀態(tài)機(jī)的輸出是否與輸入條件相關(guān),可將狀態(tài)機(jī)分為兩大類:摩爾(Moore)型狀態(tài)機(jī)米勒(Mealy)型狀態(tài)機(jī)。

  • 摩爾狀態(tài)機(jī):摩爾狀態(tài)機(jī)的輸出僅僅依賴于當(dāng)前狀態(tài),而與輸入條件無關(guān)。例如圖 1-1 所示的例子,將圖中的“地點(diǎn)”認(rèn)為是“狀態(tài)”,將“功能”認(rèn)為是狀態(tài)的“輸出”,則每個(gè)輸出僅僅與狀態(tài)相關(guān),所以它是一個(gè)摩爾型狀態(tài)機(jī)。
  • 米勒型狀態(tài)機(jī):米勒型狀態(tài)機(jī)的輸出不僅依賴于當(dāng)前狀態(tài),而且取決于該狀態(tài)的輸入條件。例如圖1-2 所示的例子,將圖中的“地點(diǎn)”認(rèn)為是“狀態(tài)”,將“功能”認(rèn)為是狀態(tài)的“輸出”,將“條件”認(rèn)為是狀態(tài)轉(zhuǎn)移的“輸入條件”,大家可以發(fā)現(xiàn),該學(xué)生到達(dá)什么地方,做什么事情都是由當(dāng)前狀態(tài)和輸入條件共同決定,所以它是一個(gè)米勒型狀態(tài)機(jī)。


根據(jù)狀態(tài)機(jī)的數(shù)量是否為有限個(gè),可將狀態(tài)機(jī)分為有限狀態(tài)機(jī)(Finite State Machine,F(xiàn)SM)和無限狀態(tài)機(jī)(Infinite State Machine,ISM)。邏輯設(shè)計(jì)中一般所涉及的狀態(tài)都是有限的,所以以后我們所說的狀態(tài)機(jī)都指有限狀態(tài)機(jī),用 FSM 表示。



狀態(tài)機(jī)的基本描述方式

邏輯設(shè)計(jì)中,狀態(tài)機(jī)的基本描述方式有 3 種,分別是:狀態(tài)轉(zhuǎn)移圖,狀態(tài)轉(zhuǎn)移列表,HDL 語言描述。

  • 狀態(tài)轉(zhuǎn)移圖

狀態(tài)轉(zhuǎn)移圖是狀態(tài)機(jī)描述的最自然的方式。如圖 1-1,1-2 都使用了狀態(tài)轉(zhuǎn)移圖這一描述方式。狀態(tài)轉(zhuǎn)移圖經(jīng)常在設(shè)計(jì)規(guī)劃階段定義邏輯功能時(shí)使用,也可以在分析代碼中狀態(tài)機(jī)時(shí)使用,通過圖形化的方式非常有助于理解設(shè)計(jì)意圖。

另外值得一提的是目前有一些 EDA 工具支持狀態(tài)轉(zhuǎn)移圖作為邏輯設(shè)計(jì)的輸入,例如在 StateCAD。在該工具中設(shè)計(jì)者只要畫出狀態(tài)轉(zhuǎn)移圖就可以了,StateCAD 能自動(dòng)將狀態(tài)轉(zhuǎn)移圖翻譯成 HDL 語言代碼,而且翻譯出來的代碼規(guī)范、可讀性較好、可綜合、易維護(hù)。StateCAD 還能能自動(dòng)檢測(cè)狀態(tài)機(jī)的完備性和正確性,對(duì)狀態(tài)轉(zhuǎn)移圖中的冗余狀態(tài)、自鎖狀態(tài)、歧義轉(zhuǎn)移條件和不完備狀態(tài)機(jī)等隱含錯(cuò)誤都會(huì)報(bào)警,并協(xié)助設(shè)計(jì)者更正錯(cuò)誤。

最后 StateCAD 會(huì)自動(dòng)生成設(shè)計(jì)的測(cè)試激勵(lì),并調(diào)用仿真程序,驗(yàn)證狀態(tài)機(jī)的正確性,這個(gè)測(cè)試激勵(lì)甚至可在后仿真中使用??傊?,StateCAD 提供了狀態(tài)機(jī)的輸入、翻譯、檢測(cè)、優(yōu)化和測(cè)試等一條龍的服務(wù),使?fàn)顟B(tài)機(jī)的設(shè)計(jì)變得安全、可靠、快速、便捷。這類自動(dòng)轉(zhuǎn)換狀態(tài)轉(zhuǎn)移圖為 HDL 源代碼的工具對(duì)設(shè)計(jì)、分析一些規(guī)模較小的狀態(tài)機(jī)非常有效,但是由于自動(dòng)反應(yīng)的代碼過于程式化,效率不是最高,所以對(duì)于較大規(guī)模的邏輯設(shè)計(jì),一般還是推薦使用 HDL 語言之間描述。



使用 Synplify Pro 的 RTL 視圖配合 FSM Viewer 可以將源代碼中描述的 FSM 用狀態(tài)轉(zhuǎn)移圖顯示出來,使用圖形化的界面幫助用戶分析理解狀態(tài)機(jī)。關(guān)于使用 FSM Viewer 分析狀態(tài)機(jī)的方法在本篇后續(xù)詳細(xì)介紹。





  • 狀態(tài)轉(zhuǎn)移列表

狀態(tài)轉(zhuǎn)移列表是用列表的方式描述狀態(tài)機(jī),是數(shù)字邏輯電路常用的設(shè)計(jì)方法之一,經(jīng)常被用于對(duì)狀態(tài)化簡,對(duì)于可編程邏輯設(shè)計(jì),由于可用邏輯資源比較豐富,而且狀態(tài)編碼要考慮設(shè)計(jì)的穩(wěn)定性,安全性等因素,所以并不經(jīng)常使用狀態(tài)轉(zhuǎn)移列表優(yōu)化狀態(tài)。


  • HDL 語言描述狀態(tài)機(jī)

使用 HDL 語言描述狀態(tài)機(jī)是本章討論的重點(diǎn),使用 HDL 語言描述狀態(tài)機(jī)有一定的靈活性,但是決不是天馬行空,而是有章可循的。通過一些規(guī)范的描述方法,可以使 HDL 語言描述的狀態(tài)機(jī)更安全、穩(wěn)定、高效、易于維護(hù)。

如何寫好狀態(tài)機(jī)


什么是RTL級(jí)較好的 FSM 描述

可綜合的狀態(tài)機(jī)描述的一些基本規(guī)范,即如何在 RTL 級(jí)描述安全、高效的 FSM。

首先介紹好的 RTL 級(jí) FSM 的評(píng)判標(biāo)準(zhǔn)。其實(shí)評(píng)判 FSM 的標(biāo)準(zhǔn)很多,這里我們揀選最重要的幾個(gè)方面討論一下。好的 RTL 級(jí) FSM 的評(píng)判標(biāo)準(zhǔn)如下:

  • FSM 要安全,穩(wěn)定性高。所謂 FSM 安全是指 FSM 不會(huì)進(jìn)入死循環(huán),特別是不會(huì)進(jìn)入非預(yù)知的狀態(tài),而且由于某些擾動(dòng)進(jìn)入非設(shè)計(jì)狀態(tài),也能很快的恢復(fù)到正常的狀態(tài)循環(huán)中來。里面有兩層含義,第一:要求該 FSM 的綜合實(shí)現(xiàn)結(jié)果無毛刺等異常擾動(dòng);二:要求狀態(tài)機(jī)要完備,即使收到異常擾動(dòng)進(jìn)入非設(shè)計(jì)狀態(tài),也能很快恢復(fù)到正常狀態(tài)。
  • FSM 速度快,滿足設(shè)計(jì)的頻率要求。

任何 RTL 設(shè)計(jì)都應(yīng)該滿足設(shè)計(jì)的頻率要求。

  • FSM 面積小,滿足設(shè)計(jì)的面積要求。

同理任何 RTL 設(shè)計(jì)都應(yīng)該滿足設(shè)計(jì)的面積要求。

  • FSM 設(shè)計(jì)要清晰易懂、易維護(hù)。

不規(guī)范的 FSM 寫法很難讓其他人解讀,甚至過一段時(shí)間后設(shè)計(jì)者也發(fā)現(xiàn)很難維護(hù)。


需要說明的是以上所列的各項(xiàng)標(biāo)準(zhǔn),特別是前 3 項(xiàng)標(biāo)準(zhǔn)絕不是割裂的,它們直接有緊密的內(nèi)在聯(lián)系。在FPGA/CPLD 設(shè)計(jì)評(píng)判的兩個(gè)基本標(biāo)準(zhǔn):面積速度。這里“面積”是指一個(gè)設(shè)計(jì)所消耗FPGA/CPLD 的邏輯資源數(shù)量;“速度”指設(shè)計(jì)在芯片上穩(wěn)定運(yùn)行所能夠達(dá)到的最高頻率。兩者是對(duì)立統(tǒng)一的矛盾體,要求一個(gè)設(shè)計(jì)同時(shí)具備設(shè)計(jì)面積最小,運(yùn)行頻率最高,這是不現(xiàn)實(shí)的??茖W(xué)的設(shè)計(jì)目標(biāo)應(yīng)該是:在滿足設(shè)計(jì)時(shí)序要求(包含對(duì)設(shè)計(jì)最高頻率的要求)的前提下,占用最小的芯片面積,或者在所規(guī)定的面積下,使設(shè)計(jì)的時(shí)序余量更大,頻率更高。

另外,如果要求 FSM 安全,則很多時(shí)候需要使用“full case”的編碼方式,即將狀態(tài)轉(zhuǎn)移變量的所有向量組合情況都在 FSM 中有相應(yīng)的處理,這經(jīng)常勢(shì)必意味著要多花更多的設(shè)計(jì)資源,有時(shí)也會(huì)影響 FSM 的頻率。

所以,各條標(biāo)準(zhǔn)要綜合考慮,根據(jù)設(shè)計(jì)的要求進(jìn)行權(quán)衡。但是如果各條評(píng)判標(biāo)準(zhǔn)發(fā)生沖突時(shí),請(qǐng)按照標(biāo)準(zhǔn)的羅列順序考慮,前文標(biāo)準(zhǔn)的羅列順序是根據(jù)這些標(biāo)準(zhǔn)在設(shè)計(jì)中的重要性排列的,也就是說第一條“FSM 要安全,穩(wěn)定性高”的優(yōu)先級(jí)最高,最重要;第四條“FSM 設(shè)計(jì)要清晰易懂、易維護(hù)”的優(yōu)先級(jí)最低,是相對(duì)次要的標(biāo)準(zhǔn)。



RTL 級(jí)狀態(tài)機(jī)描述常用語法

本小節(jié)論述了 Verilog 的基本語法和常用關(guān)鍵字,其中在 RTL 級(jí)設(shè)計(jì)可綜合的FSM 相關(guān)的常用關(guān)鍵字如下:

  • wire 、reg等對(duì) wire 、reg 等變量、向量定義不加累述,需要補(bǔ)充的是狀態(tài)編碼時(shí)(也就是用某種編碼描述各個(gè)狀態(tài))一般都要使用 reg 寄存器型向量。
  • parameter用于描述狀態(tài)名稱,增強(qiáng)源代碼可讀性,簡化描述。


例:某狀態(tài)機(jī)使用初始值為“0”的獨(dú)熱碼(one-hot)編碼方式定義的 4bit 寬度的狀態(tài)變量 NS(代表 Next State,下一狀態(tài))和 CS(代表 Current State,當(dāng)前狀態(tài)),且狀態(tài)機(jī)包含 5 個(gè)具體狀態(tài) IDLE(空閑狀態(tài))、S1(工作狀態(tài) 1)、S2(工作狀態(tài) 2)、S3(工作狀態(tài) 3)、ERROR(告警狀態(tài)),則代碼如下:

reg [3:0] NS,CS;parameter [3:0] //one hot with zero initialIDLE = 3’b0000,S1 = 3’b0001,S2 = 3’b0010,S3 = 3’b0100,ERROR = 3’b1000;

  • always

在 FSM 設(shè)計(jì)中有 3 種 always 的使用方法,第 1 種用法是根據(jù)主時(shí)鐘沿,完成同步時(shí)序的狀態(tài)遷移。例:某狀態(tài)機(jī)從當(dāng)前狀態(tài) CS 遷移到下一個(gè)狀態(tài) NS 可以如下表述:

//sequential state transitionalways @ (posedge clk or negedge nrst) if (!nrst)  CS <= IDLE;  else  CS <=NS;

always 的第 2 種用法是根據(jù)信號(hào)敏感表,完成組合邏輯的輸出。

always 的第 3 種用法是根據(jù)時(shí)鐘沿,完成同步時(shí)序邏輯的輸出。


  • case/endcase

case/endcase 是 FSM 描述中最重要的語法關(guān)鍵字,這里我們要詳細(xì)討論一下。case/endcase 的基本語法結(jié)構(gòu)如下:

case (case_expression) case_item1 : case_item_statement1; case_item2 : case_item_statement2; case_item3 : case_item_statement3; case_item4 : case_item_statement4; default : case_item_statement5;endcase

其中,case_expression 就是 case 的判斷條件表達(dá)式,在 FSM 描述中,它一般為當(dāng)前狀態(tài)寄存器;每個(gè) case_item 是 case 語句的分支列表,在 FSM 描述中,它一般為 FSM 中的所有狀態(tài)的羅列,從中還可以分析出狀態(tài)的編碼方式;case_item_statement 為進(jìn)入每個(gè) case_item 的對(duì)應(yīng)操作,在 FSM 中,即為每個(gè)狀態(tài)對(duì)應(yīng)的狀態(tài)轉(zhuǎn)移或者輸出,如果 case_item_statement 包含的操作不只一條,可以用 begin/end 嵌套多條操作;default 是個(gè)可選的關(guān)鍵字,用以指明當(dāng)所列的所有 case_item 與 case_expression 都不匹配時(shí)的操作。

在 FSM 設(shè)計(jì)中,為了提高設(shè)計(jì)的安全性,排除所設(shè)計(jì)的 FSM 進(jìn)入死循環(huán),一般要求加上default 關(guān)鍵字來描述 FSM 所需狀態(tài)的補(bǔ)集狀態(tài)下的操作。另外 Verilog 還支持 casex 和 casez 等不同關(guān)鍵字,但是由于綜合器對(duì)這兩個(gè)關(guān)鍵字的支持情況略有差異,所以建議初學(xué)者使用完整的 case 結(jié)構(gòu)而不使用 casex 或casez。

例:某 FSM 的狀態(tài)轉(zhuǎn)移用 case/endcase 結(jié)構(gòu)描述如下:

 case (CS) IDLE: begin IDLE_out; if (~i1) NS = IDLE; if (i1 && i2) NS = S1; if (i1 && ~i2) NS = ERROR; end  S1: begin S1_out; if (~i2) NS = S1; if (i2 && i1) NS = S2; if (i2 && (~i1)) NS = ERROR; end  S2: begin S2_out; if (i2) NS = S2; if (~i2 && i1) NS = IDLE; if (~i2 && (~i1)) NS = ERROR; end  ERROR: begin ERROR_out; if (i1) NS = ERROR; if (~i1) NS = IDLE; end  default: begin Default_out; NS = ERROR; end endcase


Verilog 的 case 結(jié)構(gòu)雖然與 C 等高級(jí)語言的 case 結(jié)構(gòu)雖然形式相似,但是本質(zhì)不同。Verilog 的 case 結(jié)構(gòu)對(duì)應(yīng)并行判斷的硬件結(jié)構(gòu),而且當(dāng) case_expression 與任意一個(gè)case_item 匹配后,將忽略對(duì)其它 case_item 的判斷,執(zhí)行完匹配的 case_item_statement 后直接跳出 case 結(jié)構(gòu)。





  • task/endtask

task/endtask 在描述狀態(tài)機(jī)是主要用途是將不同狀態(tài)對(duì)應(yīng)的輸出用task/endtask 封裝,增強(qiáng)了代碼的可維護(hù)性和可讀性。例:某狀態(tài)機(jī)的 IDLE 狀態(tài)的輸出可以用 task/endtask 封裝為“IDEL_out”任務(wù):

task IDLE_out; begin {w_o1,w_o2,w_err} = 3'b000; endendtask

當(dāng)然描述狀態(tài)機(jī)時(shí)也會(huì)使用到其它一些常用的 RTL 級(jí)語法,如 if/else,assign等等,它們的功能和一般 RTL 描述方法一致,這里不在敘述。



推薦的狀態(tài)機(jī)描述方法

狀態(tài)機(jī)描述時(shí)關(guān)鍵是要描述清楚前面提到的幾個(gè)狀態(tài)機(jī)的要素,即如何進(jìn)行狀態(tài)轉(zhuǎn)移;每個(gè)狀態(tài)的輸出是什么;狀態(tài)轉(zhuǎn)移是否和輸入條件相關(guān)等。具體描述時(shí)方法各種各樣,有的設(shè)計(jì)者習(xí)慣將整個(gè)狀態(tài)機(jī)寫到 1 個(gè) always 模塊里面,在該模塊中即描述狀態(tài)轉(zhuǎn)移,又描述狀態(tài)的輸入和輸出,這種寫法一般被稱為一段式 FSM 描述方法;還有一種寫法是用 2 個(gè)always 模塊,其中一個(gè) always 模塊采用同步時(shí)序描述狀態(tài)轉(zhuǎn)移;另一個(gè)模塊采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律,這種寫法被稱為兩段式 FSM 描述方法;還有一種寫法是在兩段式描述方法基礎(chǔ)上發(fā)展出來的,這種寫法使用 3 個(gè) always 模塊,一個(gè) always模塊采用同步時(shí)序描述狀態(tài)轉(zhuǎn)移;第二個(gè)采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律;第三個(gè) always 模塊使用同步時(shí)序電路描述每個(gè)狀態(tài)的輸出,這種寫法稱為三段式寫法。

一般而言,推薦的 FSM 描述方法是后兩種,即兩段式和三段式 FSM 描述方法。其原因?yàn)椋篎SM 和其他設(shè)計(jì)一樣,最好使用同步時(shí)序方式設(shè)計(jì),以提高設(shè)計(jì)的穩(wěn)定性,消除毛刺。狀態(tài)機(jī)實(shí)現(xiàn)后,一般來說,狀態(tài)轉(zhuǎn)移部分是同步時(shí)序電路而狀態(tài)的轉(zhuǎn)移條件的判斷是組合邏輯。兩段式之所以比一段式編碼合理,就在于兩段式編碼將同步時(shí)序和組合邏輯分別放到不同的 always 程序塊中實(shí)現(xiàn)。這樣做的好處不僅僅是便于閱讀、理解、維護(hù),更重要的是利于綜合器優(yōu)化代碼,利于用戶添加合適的時(shí)序約束條件,利于布局布線器實(shí)現(xiàn)設(shè)計(jì)。而一段式 FSM 描述不利于時(shí)序約束、功能更改、調(diào)試等,而且不能很好的表示米勒 FSM 的輸出,容易寫出 Latches,導(dǎo)致邏輯功能錯(cuò)誤。

在一般兩段式描述中,為了便于描述當(dāng)前狀態(tài)的輸出,很多設(shè)計(jì)者習(xí)慣將當(dāng)前狀態(tài)的輸出用組合邏輯實(shí)現(xiàn)。但是這種組合邏輯仍然有產(chǎn)生毛刺的可能性,而且不利于約束,不利于綜合器和布局布線器實(shí)現(xiàn)高性能的設(shè)計(jì)。因此如果設(shè)計(jì)運(yùn)行額外的一個(gè)時(shí)鐘節(jié)拍的插入(latency),則要求盡量對(duì)狀態(tài)機(jī)的輸出用寄存器寄存一拍。但是很多實(shí)際情況不允許插入一個(gè)寄存節(jié)拍,此時(shí)則可以通過三段式描述方法進(jìn)行解決。三段式與兩段式相比,關(guān)鍵在于根據(jù)狀態(tài)轉(zhuǎn)移規(guī)律,在上一狀態(tài)根據(jù)輸入條件判斷出當(dāng)前狀態(tài)的輸出,從而在不插入額外時(shí)鐘節(jié)拍的前提下,實(shí)現(xiàn)了寄存器輸出。

為了便于理解,我們通過一個(gè)實(shí)例討論這三種不同的寫法。

【例1-1】 使用不同的 FSM 描述風(fēng)格描述狀態(tài)機(jī),在這個(gè)范例中我們將用一段式、兩段式、三段式分別描述圖 1-3 所示的狀態(tài)機(jī)。這里我們選用了一個(gè)非常典型的米勒型狀態(tài)機(jī),共有 4 個(gè)狀態(tài):IDEL, S1, S2, ERROR;輸入信號(hào)為時(shí)鐘 clk,低電平異步復(fù)位信號(hào) nrst,輸入信號(hào) i1,i2,輸出信號(hào)為 o1,o2 和 err,狀態(tài)關(guān)系如圖 1-2 所示。狀態(tài)的輸出如下:

IDLE 狀態(tài)的輸出為:{o1,o2,err} = 3'b000;

S1 狀態(tài)的輸出為:{o1,o2,err} = 3'b100;

S2 狀態(tài)的輸出為:{o1,o2,err} = 3'b010;

ERROR 狀態(tài)的輸出為:{o1,o2,err} = 3'b111。

圖1-3 例子的狀態(tài)轉(zhuǎn)移圖
一段式狀態(tài)機(jī)描述方法(應(yīng)該避免的寫法)該例的一段式描述代碼如下:
//1-paragraph method to describe FSM//Describe state transition, state output, input condition in 1 always blockmodule state1 ( nrst,clk,i1,i2,o1,o2,err); input nrst,clk; input i1,i2; output o1,o2,err; reg o1,o2,err; reg [2:0] NS; //NextState parameter [2:0] //one hot with zero idle IDLE = 3'b000, S1 = 3’b001, S2 = 3’b010, ERROR = 3’b100; //1 always block to describe state transition, state output, input condition always @ (posedge clk or negedge nrst)  begin if (!nrst) begin NS <= IDLE; {o1,o2,err} <= 3'b000; end else begin NS <= 3'bx; {o1,o2,err} <= 3'b000; case (NS) IDLE: begin if (~i1) begin{o1,o2,err}<=3'b000;NS <= IDLE; end if (i1 && i2) begin{o1,o2,err}<=3'b100;NS <= S1;end if (i1 && ~i2) begin{o1,o2,err}<=3'b111;NS <= ERROR;end end  S1: begin if (~i2) begin{o1,o2,err}<=3'b100;NS <= S1; end if (i2 && i1) begin{o1,o2,err}<=3'b010;NS <= S2; end if (i2 && (~i1)) begin{o1,o2,err}<=3'b111;NS <= ERROR;end end  S2: begin if (i2) begin{o1,o2,err}<=3'b010;NS <= S2; end if (~i2 && i1) begin{o1,o2,err}<=3'b000;NS <= IDLE; end if (~i2 && (~i1))begin{o1,o2,err}<=3'b111;NS <= ERROR;end end  ERROR: begin if (i1) begin{o1,o2,err}<=3'b111;NS <= ERROR;end if (~i1) begin{o1,o2,err}<=3'b000;NS <= IDLE; end end endcase end endmodule

如前面介紹,一段式寫法就是將狀態(tài)的同步轉(zhuǎn)移,狀態(tài)輸出和狀態(tài)的輸入條件都寫在一個(gè) always 模塊中,一段式寫法可以概括為圖 1-4 描述的結(jié)構(gòu)。

圖1-4 一段式 FSM 描述結(jié)構(gòu)圖
一段式描述方法將狀態(tài)轉(zhuǎn)移判斷的組合邏輯和狀態(tài)寄存器轉(zhuǎn)移的時(shí)序邏輯混寫在同一個(gè)always 模塊中,不符合將時(shí)序和組合邏輯分開描述的 Coding Style(代碼風(fēng)格),而且在描述當(dāng)前狀態(tài)時(shí)要考慮下個(gè)狀態(tài)的輸出,整個(gè)代碼不清晰,不利于維護(hù)修改,并且不利于附加約束,不利于綜合器和布局布線器對(duì)設(shè)計(jì)的優(yōu)化。另外,這種描述相對(duì)于兩段式描述比較冗長。本例為了便于初學(xué)者掌握,選擇了一個(gè)非常簡單的米勒型狀態(tài)機(jī),不能很好的反應(yīng)一段式比較冗長的缺點(diǎn),但是如果狀態(tài)機(jī)相對(duì)復(fù)雜些,一般來說,一段式代碼長度會(huì)比兩段式冗長大約 80%到 150%左右。所以一段式 FSM 描述是不推薦的 FSM 描述方式,請(qǐng)大俠一定要避免。
兩段式狀態(tài)機(jī)描述方法(推薦寫法)為了使 FSM 描述清晰簡潔,易于維護(hù),易于附加時(shí)序約束,使綜合器和布局布線器更好的優(yōu)化設(shè)計(jì),推薦使用兩段式 FSM 描述方法。本例的兩段式描述代碼如下:
//2-paragraph method to describe FSM//Describe sequential state transition in 1 sequential always block//State transition conditions in the other combinational always block//Package state output by task. Then register the outputmodule state2 ( nrst,clk,i1,i2,o1,o2,err); input nrst,clk; input i1,i2; output o1,o2,err; reg o1,o2,err; reg [2:0] NS,CS; parameter [2:0] //one hot with zero idle IDLE = 3'b000, S1 = 3’b001, S2 = 3’b010, ERROR = 3’b100;  //sequential state transition always @ (posedge clk or negedge nrst) if (!nrst)  CS <= IDLE;  else  CS <=NS;   //combinational condition judgment always @ (CS or i1 or i2) begin NS = 3'bx; ERROR_out; case (CS) IDLE: begin IDLE_out; if (~i1) NS = IDLE; if (i1 && i2) NS = S1; if (i1 && ~i2) NS = ERROR; end  S1: begin S1_out; if (~i2) NS = S1; if (i2 && i1) NS = S2; if (i2 && (~i1)) NS = ERROR; end  S2: begin S2_out; if (i2) NS = S2; if (~i2 && i1) NS = IDLE; if (~i2 && (~i1)) NS = ERROR; end  ERROR: begin ERROR_out; if (i1) NS = ERROR; if (~i1) NS = IDLE; end endcase end   //output task task IDLE_out; {o1,o2,err} = 3'b000; endtask  task S1_out; {o1,o2,err} = 3'b100; endtask  task S2_out; {o1,o2,err} = 3'b010; endtask  task ERROR_out; {o1,o2,err} = 3'b111; endtask endmodule

兩段式寫法是推薦的 FSM 描述方法之一,在此我們仔細(xì)討論一下代碼結(jié)構(gòu)。兩段式FSM 的核心就是:一個(gè) always 模塊采用同步時(shí)序描述狀態(tài)轉(zhuǎn)移;另一個(gè)模塊采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律。兩段式寫法可以概括為圖 1-5 描述的結(jié)構(gòu)。

圖1-5 兩段式 FSM 描述結(jié)構(gòu)圖

本例中,同步時(shí)序描述狀態(tài)轉(zhuǎn)移的 always 模塊代碼如下:
always @ (posedge clk or negedge nrst) if (!nrst)  CS <= IDLE;  else  CS <=NS;

其實(shí)這是一種程式化的描述結(jié)構(gòu),無論具體到何種 FSM 設(shè)計(jì),都可以定義兩個(gè)狀態(tài)寄存器“CS”和“NS”,分別代表當(dāng)前狀態(tài)和下一狀態(tài),然后根據(jù)所需的復(fù)位方式(同步復(fù)位或異步復(fù)位),在時(shí)鐘沿到達(dá)時(shí)將 NS 賦給 CS。需要注意的是這個(gè)同步時(shí)序模塊的賦值要采用非阻塞賦值“<=”。本例中,另一個(gè)采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件的 always 模塊代碼如下:
//combinational condition judgmentalways @ (nrst or CS or i1 or i2) begin NS = 3'bx; ERROR_out; case (CS) IDLE: begin IDLE_out; if (~i1) NS = IDLE; if (i1 && i2) NS = S1; if (i1 && ~i2) NS = ERROR; end  S1: begin S1_out; if (~i2) NS = S1; if (i2 && i1) NS = S2; if (i2 && (~i1)) NS = ERROR; end  S2: begin S2_out; if (i2) NS = S2; if (~i2 && i1) NS = IDLE; if (~i2 && (~i1)) NS = ERROR; end  ERROR: begin ERROR_out; if (i1) NS = ERROR; if (~i1) NS = IDLE; end endcase end 
這個(gè)使用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件的 always 模塊也可以看成格式化的書寫結(jié)構(gòu)。其中 always 的敏感列表為當(dāng)前狀態(tài)“CS”,復(fù)位信號(hào)和輸入條件(如果是米勒狀態(tài)機(jī),則必須有輸入條件;如果是摩爾狀態(tài)機(jī),一般敏感表和后續(xù)邏輯判定沒有輸入),請(qǐng)大俠注意電平敏感表必須列完整。本例中這段電平敏感列表為:
always @ (nrst or CS or i1 or i2)

一般來說,在這個(gè)組合 always 敏感表下先寫一個(gè)默認(rèn)的下一狀態(tài)“NS”的描述,然后根據(jù)實(shí)際的狀態(tài)轉(zhuǎn)移條件由內(nèi)部的 case 或者 if...else 條件判斷確定正確的轉(zhuǎn)移。如本例中下面這段代碼:
 …… begin NS = ERROR; ERROR_out; case (CS) ……
推薦在敏感表下的默認(rèn)狀態(tài)為不定狀態(tài) X,這樣描述的好處有兩個(gè):第一在仿真時(shí)可以很好的考察所設(shè)計(jì)的 FSM 的完備性,如果所設(shè)計(jì)的 FSM 不完備,則會(huì)進(jìn)入任意狀態(tài),仿真很容易發(fā)現(xiàn);第二個(gè)好處是綜合器對(duì)不定態(tài) X 的處理是“Don’t Care”,即任何沒有定義的狀態(tài)寄存器向量都會(huì)被忽略。這里賦值不定態(tài)的效果和使用 casez 或 casex 替代 case 的效果非常相似。在每個(gè) case 模塊的內(nèi)部的結(jié)構(gòu)也非常相似,都是先描述當(dāng)前狀態(tài)的組合邏輯輸出,然后根據(jù)輸入條件(米勒 FSM)判定下一個(gè)狀態(tài)。該組合邏輯模塊中所有的賦值推薦采用阻塞賦值“=”。

請(qǐng)大家注意,雖然下一狀態(tài)寄存器 NS 為寄存器類型,但是在兩段式 FSM 的判斷狀態(tài)轉(zhuǎn)移條件的 always 模塊中,實(shí)際上對(duì)應(yīng)的真實(shí)硬件電路是純組合邏輯電路。





對(duì)于每個(gè)輸出,一般用組合邏輯描述,比較簡便的方法是用 task/endtask 將輸出封裝起來,這樣做的好處不僅僅是寫法簡單,而且利于復(fù)用共同的輸出。例如本例中 S1 狀態(tài)的輸出被封裝為 S1_out,在組合邏輯 always 模塊中直接調(diào)用即可。

task S1_out; {o1,o2,err} = 3'b100;endtask

組合邏輯容易產(chǎn)生毛刺,因此如果時(shí)序允許,請(qǐng)盡量對(duì)組合邏輯的輸出插入一個(gè)寄存器節(jié)拍,這樣可以很好的保證輸出信號(hào)的穩(wěn)定性。

三段式狀態(tài)機(jī)描述方法(推薦寫法)兩段式 FSM 描述方法雖然有很多好處,但是它有一個(gè)明顯的弱點(diǎn)就是其輸出一般使用組合邏輯描述,而組合邏輯易產(chǎn)生毛刺等不穩(wěn)定因素,并且在 FPGA/CPLD 等邏輯器件中過多的組合邏輯會(huì)影響實(shí)現(xiàn)的速率(這點(diǎn)與 ASIC 設(shè)計(jì)不同)。所以在上面我們特別提到了在兩段式 FSM 描述方法中,如果時(shí)序允許插入一個(gè)額外的時(shí)鐘節(jié)拍,則盡量在在后級(jí)電路對(duì)FSM 的組合邏輯輸出用寄存器寄存一個(gè)節(jié)拍,則可以有效地消除毛刺。但是很多情況下,設(shè)計(jì)并不允許額外的節(jié)拍插入(Latency),此時(shí),解決之道就是采用 3 段式 FSM 描述方法。三段式描述方法與兩段式描述方法相比,關(guān)鍵在于使用同步時(shí)序邏輯寄存 FSM 的輸出。本例的三段式描述代碼如下:
//3-paragraph method to describe FSM//Describe sequential state transition in the 1st sequential always block//State transition conditions in the 2nd combinational always block//Describe the FSM out in the 3rd sequential always blockmodule state2 ( nrst,clk,i1,i2,o1,o2,err); input nrst,clk; input i1,i2; output o1,o2,err; reg o1,o2,err; reg [2:0] NS,CS; parameter [2:0] //one hot with zero idle IDLE = 3'b000, S1 = 3'b001, S2 = 3'b010, ERROR = 3'b100;  //1st always block, sequential state transition always @ (posedge clk or negedge nrst) if (!nrst)  CS <= IDLE;  else  CS <=NS;   //2nd always block, combinational condition judgment always @ (nrst or CS or i1 or i2) begin NS = 3'bx; case (CS) IDLE: begin if (~i1) NS = IDLE; if (i1 && i2) NS = S1; if (i1 && ~i2) NS = ERROR; end  S1: begin if (~i2) NS = S1; if (i2 && i1) NS = S2; if (i2 && (~i1)) NS = ERROR; end  S2: begin if (i2) NS = S2; if (~i2 && i1) NS = IDLE; if (~i2 && (~i1)) NS = ERROR; end  ERROR: begin if (i1) NS = ERROR; if (~i1) NS = IDLE; end endcase end  //3rd always block, the sequential FSM output always @ (posedge clk or negedge nrst) begin if (!nrst) {o1,o2,err} <= 3'b000; else begin {o1,o2,err} <= 3'b000; case (NS) IDLE: {o1,o2,err}<=3'b000; S1: {o1,o2,err}<=3'b100; S2: {o1,o2,err}<=3'b010; ERROR: {o1,o2,err}<=3'b111; endcase end endendmodule

三段式寫法可以概括為圖 1-6 描述的結(jié)構(gòu)。

圖6-6 三段式 FSM 描述結(jié)構(gòu)圖

對(duì)比一下上面兩段式 FSM 的描述,大俠可以清晰發(fā)現(xiàn)三段式與兩段式 FSM 描述的最大區(qū)別在于兩段式采用了組合邏輯輸出,而三段式巧妙地根據(jù)下一狀態(tài)的判斷,用同步時(shí)序邏輯寄存 FSM 的輸出。本例中就是下面一段代碼:
always @ (posedge clk or negedge nrst) if (!nrst) {o1,o2,err} <= 3'b000; else begin {o1,o2,err} <= 3'b000; case (NS) IDLE: {o1,o2,err}<=3'b000; S1: {o1,o2,err}<=3'b100; S2: {o1,o2,err}<=3'b010; ERROR: {o1,o2,err}<=3'b111; endcase end

有的大俠可能會(huì)問,一段式寫法也是用寄存器同步了 FSM 的輸出,為什么前面介紹一段式的輸出代碼容易混淆,不利于維護(hù)呢?請(qǐng)大家對(duì)比一下這段一段式輸出的代碼:

case (NS) IDLE: begin if (~i1) begin{o1,o2,err}<=3'b000;NS <= IDLE; end if (i1 && i2) begin{o1,o2,err}<=3'b100;NS <= S1; end if (i1 && ~i2) begin{o1,o2,err}<=3'b111;NS <= ERROR;end end

通過對(duì)比,可以清晰地看到:使用一段式建模 FSM 的寄存器輸出的時(shí)候,必須要綜合考慮現(xiàn)態(tài)在何種狀態(tài)轉(zhuǎn)移條件下會(huì)進(jìn)入哪些次態(tài),然后在每個(gè)現(xiàn)態(tài)的 case 分支下分別描述每個(gè)次態(tài)的輸出,這顯然不符合思維習(xí)慣;而三段式建模描述 FSM 的狀態(tài)機(jī)輸出時(shí),只需指定 case 敏感表為次態(tài)寄存器,然后直接在每個(gè)次態(tài)的 case 分支中描述該狀態(tài)的輸出即可,根本不用考慮狀態(tài)轉(zhuǎn)移條件。本例的 FSM 很簡單,如果設(shè)計(jì)的 FSM 相對(duì)復(fù)雜,三段式的描述優(yōu)勢(shì)就會(huì)凸顯出來。

另一方面,三段式描述方法與兩段式描述相比,雖然代碼結(jié)構(gòu)復(fù)雜了一些,但是換來的優(yōu)勢(shì)是使 FSM 做到了同步寄存器輸出,消除了組合邏輯輸出的不穩(wěn)定與毛刺的隱患,而且更利于時(shí)序路徑分組,一般來說在 FPGA/CPLD 等可編程邏輯器件上的綜合與布局布線效果更佳。



請(qǐng)大俠注意,在三段式 FSM 描述方法中,判斷狀態(tài)轉(zhuǎn)移的 always 模塊的 case 語句判斷的條件是當(dāng)前狀態(tài)“CS”而在同步時(shí)序 FSM 輸出的 always 模塊的 case 語句判斷的條件是下一狀態(tài)“NS”。





三種描述方法與狀態(tài)機(jī)建模問題的引申

可以說合理的狀態(tài)機(jī)描述與狀態(tài)機(jī)的建模技巧是本篇的重中之重。這里需要引申討論幾個(gè)問題。

  • n 段式描述方法和 always 語法塊的個(gè)數(shù)通過學(xué)習(xí),大家知道標(biāo)準(zhǔn)的一段式、兩段式、三段式 FSM 描述方法分別使用了 1、2、3 個(gè) always 語法塊。但是請(qǐng)大俠注意這個(gè)命題的反命題不成立,不能說一段 FSM 的描述中,使用了 n 個(gè) always 語法塊,就是 n 段式描述方法。這是因?yàn)樘刂傅囊欢问健啥问?、三段?FSM 描述方法中每個(gè) always 語法塊都有固定的描述內(nèi)容和格式化的結(jié)構(gòu),其實(shí)也就是通過這些特定的描述內(nèi)容和格式化的結(jié)構(gòu),確立了 3 種 FSM 建模方式。例如兩段式寫法中,第一個(gè)always 模塊格式化地使用同步時(shí)序電路描述次態(tài)寄存器到現(xiàn)態(tài)寄存器的轉(zhuǎn)移;而第二個(gè) always 模塊格式化地使用純組合邏輯描述狀態(tài)轉(zhuǎn)移條件。也就是說兩段式描述對(duì)應(yīng)的建模方式的硬件電路就是圖 1-5 所示的電路結(jié)構(gòu)。其實(shí)站在語法角度上,我們總可以將一個(gè) always 模塊拆分成多個(gè) always 模塊,或者反之將多個(gè) always 模塊合并為一個(gè) always 模塊。所以請(qǐng)讀者注意,n 段式 FSM描述方法強(qiáng)調(diào)的是一種建模思路,絕不是簡單的 always 語法塊個(gè)數(shù)。
  • FSM 的建模方式這里我們反復(fù)強(qiáng)調(diào) n 段式描述方法其實(shí)是 FSM 的三種建模方式。大家回顧一下狀態(tài)轉(zhuǎn)移圖 1-3 描述的 FSM,在學(xué)習(xí)本篇之前,大家可能會(huì)有產(chǎn)生各種不同的描述思路,通過本節(jié)的學(xué)習(xí),希望大俠能夠自然而然地想到用圖 1-5(對(duì)應(yīng)兩段式思路)和圖 1-6(對(duì)應(yīng)三段式思路)的結(jié)構(gòu)建模。其實(shí)對(duì)于絕大多數(shù)FSM,都可以采樣圖 1-4,或圖 1-5,或圖 1-6 的結(jié)構(gòu)建模。一般來說,推薦使用后兩種結(jié)構(gòu)建模。這是因?yàn)?/span>兩段式思路建模結(jié)構(gòu)清晰,描述簡潔,便于約束,而且如果允許輸出邏輯允許插入一個(gè)節(jié)拍,就可以通過插入輸出寄存器改善輸出邏輯的時(shí)序并避免組合邏輯的毛刺;三段式思路建模結(jié)構(gòu)清晰,格式化的結(jié)構(gòu),解決了不改變時(shí)序要求的前提下用寄存器做狀態(tài)輸出的問題。請(qǐng)大家仔細(xì)研究圖 1-4、圖 1-5、圖 1-6 體會(huì)三種建模方式。
  • 一段式建模和三段式建模的關(guān)系這里我們引申比較一下 3 種 FSM 建模的關(guān)系。請(qǐng)讀者比較圖 1-4 與圖 1-6,如果將圖 1-4 的兩部分組合邏輯合并起來,則三段式建模電路與一段式建模電路的結(jié)構(gòu)完全一致了,如圖 1-7 所示。反過來,大家可以看到三段式與一段式的最大區(qū)別在于:使用一段式建模 FSM 的寄存器輸出的時(shí)候,必須要綜合考慮現(xiàn)態(tài)在何種狀態(tài)轉(zhuǎn)移條件下會(huì)進(jìn)入哪些次態(tài),然后在每個(gè)現(xiàn)態(tài)的 case 分支下分別描述每個(gè)次態(tài)的輸出,這顯然不符合思維習(xí)慣;而三段式建模描述 FSM 的狀態(tài)機(jī)輸出時(shí),只需指定 case 敏感表為次態(tài)寄存器,然后直接在每個(gè)次態(tài)的case 分支中描述該狀態(tài)的輸出即可,根本不用考慮狀態(tài)轉(zhuǎn)移條件。對(duì)于簡單的FSM,三段式建模的寄存器輸出的優(yōu)勢(shì)還不是十分明顯,但是對(duì)于復(fù)雜一些的FSM,三段式建模的優(yōu)勢(shì)就會(huì)十分顯著。


圖1-7 三段式建模結(jié)構(gòu)與一段式建模結(jié)構(gòu)的關(guān)系圖
  • 兩段式建模和三段式建模的關(guān)系

    從代碼上看,三段式建模的前兩段與兩段式建模完全相同,僅僅多了一段寄存器 FSM 輸出。一般來說,使用寄存器輸出可以改善輸出的時(shí)序條件,還能避免組合電路的毛刺,所以是更為推薦的描述方式。但是電路設(shè)計(jì)不是一成不變的,在某些情況下,兩段式結(jié)構(gòu)比三段式結(jié)構(gòu)更有優(yōu)勢(shì)。請(qǐng)大家再分析一下圖1-5、圖 1-6 的結(jié)構(gòu),細(xì)心的讀者會(huì)發(fā)現(xiàn),兩段式用狀態(tài)寄存器分割了兩部分組合邏輯(狀態(tài)轉(zhuǎn)移條件組合邏輯和輸出組合邏輯);而三段式結(jié)構(gòu)中,從輸入到寄存器狀態(tài)輸出的路徑上,要經(jīng)過兩部分組合邏輯(狀態(tài)轉(zhuǎn)移條件組合邏輯和輸出組合邏輯),從時(shí)序上,這兩部分組合邏輯完全可以看為一體。這樣這條路徑的組合邏輯就比較繁雜,該路徑的時(shí)序相對(duì)緊張。也就是說,兩段式建模中用狀態(tài)寄存器分割了組合邏輯,而三段式將寄存器移到組合邏輯的最后端。如果寄存器前的組合邏輯過于復(fù)雜,勢(shì)必會(huì)成為整個(gè)設(shè)計(jì)的關(guān)鍵路徑,此時(shí)就不宜再使用三段式建模,而要使用兩段式建模。解決兩段式建模組合邏輯輸出產(chǎn)生毛刺的方法是,額外的在 FSM 后級(jí)電路插入寄存器,調(diào)整時(shí)序,完成功能。

  • 三種描述 FSM 方法的比較

    一般來說,三種 FSM 描述方法可以用表 1-1 進(jìn)行比較。但是請(qǐng)讀者注意,任何一種描述的優(yōu)劣只是一般規(guī)律,而不是絕對(duì)性規(guī)律。例如一般來說不推薦一段式描述,但是如果 FSM 的結(jié)構(gòu)十分簡單,狀態(tài)很少,狀態(tài)轉(zhuǎn)移條件和狀態(tài)輸出都十分簡化,則使用一段式建模的效率很高。這些經(jīng)驗(yàn)需要讀者逐步積累,但是筆者在這里推薦的是一般性規(guī)律,請(qǐng)讀者結(jié)合電路,體會(huì)這幾種FSM 建模方法。


表 1-1 三種 FSM 描述方法比較表



狀態(tài)機(jī)設(shè)計(jì)的其他技巧

本節(jié)討論 FSM 設(shè)計(jì)的其他技巧。

  • FSM 的編碼

Binary(二進(jìn)制編碼)、gray-code(格雷碼)編碼使用最少的觸發(fā)器,較多的組合邏輯,而 one-hot(獨(dú)熱碼)編碼反之。one-hot 編碼的最大優(yōu)勢(shì)在于狀態(tài)比較時(shí)僅僅需要比較一個(gè) bit,一定程度上從而簡化了比較邏輯,減少了毛刺產(chǎn)生的概率。由于 CPLD 更多地提供組合邏輯資源,而 FPGA 更多地提供觸發(fā)器資源,所以 CPLD 多使用 gray-code,而 FPGA 多使用 one-hot 編碼。另一方面,對(duì)于小型設(shè)計(jì)使用 gray-code binary 編碼更有效,而大型狀態(tài)機(jī)使用one-hot 更高效。

在代碼中添加綜合器的綜合約束屬性或者在圖形界面下設(shè)置綜合約束屬性可以比較方便地改變狀態(tài)的編碼。需要注意的是:Synplicity、Synopsys、Exemplar 等綜合工具關(guān)于 FSM 的綜合約束屬性的語法格式各不相同。


  • FSM 初始化狀態(tài)

一個(gè)完備的狀態(tài)機(jī)(健壯性強(qiáng))應(yīng)該具備初始化狀態(tài)和默認(rèn)狀態(tài)。當(dāng)芯片加電或者復(fù)位后,狀態(tài)機(jī)應(yīng)該能夠自動(dòng)將所有判斷條件復(fù)位,并進(jìn)入初始化狀態(tài)。需要注明的一點(diǎn)是,大多數(shù) FPGA 有 GSR(Global Set/Reset)信號(hào),當(dāng)FPGA 加電后,GSR 信號(hào)拉高,對(duì)所有的寄存器、RAM 等單元復(fù)位/置位,這時(shí)配置于 FPGA 的邏輯并未生效,所以不能保證正確地進(jìn)入初始化狀態(tài)。所以使用 GSR 企圖進(jìn)入 FPGA 的初始化狀態(tài),常常會(huì)產(chǎn)生種種不必要的麻煩。一般的方法是采用異步復(fù)位信號(hào),當(dāng)然也可以使用同步復(fù)位,但是要注意同步復(fù)位邏輯的設(shè)計(jì)。解決這個(gè)問題的另一種方法是將默認(rèn)的初始狀態(tài)的編碼設(shè)為全零,這樣 GSR 復(fù)位后,狀態(tài)機(jī)自動(dòng)進(jìn)入初始狀態(tài)。


  • FSM 狀態(tài)編碼定義

狀態(tài)機(jī)的定義可以用 parameter 定義,但是不推薦使用`define 宏定義的方式,因?yàn)?define 宏定義在編譯時(shí)自動(dòng)替換整個(gè)設(shè)計(jì)中所定義的宏,而parameter 僅僅定義模塊內(nèi)部的參數(shù),定義的參數(shù)不會(huì)與模塊外的其他狀態(tài)機(jī)混淆。例如一個(gè)工程里面有兩個(gè) module 各包含一個(gè) FSM,如果設(shè)計(jì)時(shí)都有IDLE 這一名稱的狀態(tài),如果使用'define 宏定義就會(huì)混淆起來,如果使用parameter 則不會(huì)造成任何不良影響。


  • FSM 輸出

如果使用 2 段式 FSM 描述 Mealy 狀態(tài)機(jī),輸出邏輯可以用"?語句"描述,或者使用 case 語句判斷轉(zhuǎn)移條件與輸入信號(hào)即可。如果輸出條件比較復(fù)雜,而且多個(gè)狀態(tài)共用某些輸出,則建議使用 task/endtask 將輸出封裝起來,達(dá)到模塊復(fù)用的目的。


  • 阻塞和非阻塞賦值

為了避免不必要的競(jìng)爭(zhēng)冒險(xiǎn),不論是做兩段式還是三段式 FSM 描述時(shí),必須遵循時(shí)序邏輯 always 模塊使用非阻塞賦值“<=”,即當(dāng)前狀態(tài)向下一狀態(tài)時(shí)序轉(zhuǎn)移,和寄存 FSM 輸出等時(shí)序 always 模塊中都要使用非阻塞賦值;而組合邏輯 always 模塊使用阻塞賦值“=”,即狀態(tài)轉(zhuǎn)移條件判斷,組合邏輯輸出等always 模塊中都要使用阻塞賦值。


  • FSM 的默認(rèn)狀態(tài)

完整的狀態(tài)機(jī)應(yīng)該包含一個(gè)默認(rèn)(default)狀態(tài),當(dāng)轉(zhuǎn)移條件不滿足,或者狀態(tài)發(fā)生了突變時(shí),要能保證邏輯不會(huì)陷入“死循環(huán)”。這是對(duì)狀態(tài)機(jī)健壯性的一個(gè)重要要求,也就是常說的要具備“自恢復(fù)”功能。對(duì)應(yīng)于編碼就是對(duì)case 和 if…else 語句要特別注意,盡量使用完備的條件判斷語句。Verilog 中,使用 case 語句的時(shí)候要用 default 建立默認(rèn)狀態(tài)。讀者可能注意到,在上節(jié)舉例中的 case 語句中,我們沒有寫 default 默認(rèn)狀態(tài),其實(shí)我們可以將其中一個(gè)狀態(tài)不編碼,指定其為 default 默認(rèn)狀態(tài),則任何與所列狀態(tài)機(jī)不匹配的狀態(tài)都會(huì)轉(zhuǎn)到 default 狀態(tài),從而增強(qiáng)了 FSM 的健壯性,另外我們也可以添加一個(gè)額外的 default 狀態(tài),這個(gè)一旦進(jìn)入這個(gè)狀態(tài)就會(huì)自動(dòng)轉(zhuǎn)到 IDLE 狀態(tài),從新啟動(dòng)狀態(tài)機(jī),這樣做也增強(qiáng)了狀態(tài)機(jī)的可塑性。

 ……  begin  case (CS) IDLE: begin IDLE_out; if (~i1) NS = IDLE; if (i1 && i2) NS = S1; if (i1 && ~i2) NS = ERROR; end  S1: begin S1_out; if (~i2) NS = S1; if (i2 && i1) NS = S2; if (i2 && (~i1)) NS = ERROR; end  S2: begin S2_out; if (i2) NS = S2; if (~i2 && i1) NS = IDLE; if (~i2 && (~i1)) NS = ERROR; end  ERROR: begin ERROR_out; if (i1) NS = ERROR; if (~i1) NS = IDLE; end  default: begin IDLE_out; NS = IDLE; end  endcase end


在 case 語句結(jié)構(gòu)中增加 default 默認(rèn)狀態(tài)是推薦的代碼風(fēng)格。





  • Full Case 與 Parallel Case 綜合屬性

所謂 Full Case 是指:FSM 的所有編碼向量都可以與 case 結(jié)構(gòu)的某個(gè)分支或 default 默認(rèn)情況匹配起來。如果一個(gè) FSM 的狀態(tài)編碼是 8bit,則對(duì)應(yīng)的256 個(gè)狀態(tài)編碼(全狀態(tài)編碼是 n 2 個(gè))都可以與 case 的某個(gè)分支或者 default映射起來。

所謂 Parallel Case 是指:在 case 結(jié)構(gòu)中,每個(gè) case 的判斷條件表達(dá)式,有且僅有唯一的 case 語句的分支(與之對(duì)應(yīng),即兩者關(guān)系是一一對(duì)應(yīng)關(guān)系。

目前知名綜合器如 Synplify Pro、Precision RTL 和 Synopys 綜合工具等都支持“ synthesis full_case”和“ synthesis parallel_case”這些綜合約束屬性,合理使用 Full Case 約束屬性,可以增強(qiáng)設(shè)計(jì)的安全性;合理使用 Parallel Case約束屬性,可以改善狀態(tài)機(jī)譯碼邏輯。但是設(shè)計(jì)者必須具體情況具體分析,對(duì)于有的設(shè)計(jì),不當(dāng)使用這兩條語句,會(huì)占用大量邏輯資源,并惡化 FSM 的時(shí)序表現(xiàn)。



使用 Synplify Pro 分析 FSM


代碼走讀時(shí)分析 FSM 是一件比較耗時(shí)的事情,如果代碼不符合式或三段式 FSM 描述規(guī)范,走讀他人代碼則是一件異常痛苦的事情。這里以 SynplifyPro 為例,介紹一下如何利于 EDA 工具分析 FSM,綜合 FSM,提高 FSM 性能。

Synplify Pro 提供了 3 個(gè)有限狀態(tài)機(jī)設(shè)計(jì)工具,F(xiàn)SM Compiler、FSM Explorer 和 FSM Viewer,靈活地使用這 3 個(gè)有限狀態(tài)機(jī)工具分析、編譯、優(yōu)化 FSM,可使 FSM 的綜合結(jié)果達(dá)到最優(yōu)。下面逐一討論它們的使用方法。

(1) 有限狀態(tài)機(jī)編譯器(FSM Compiler)

一般的綜合工具將 FSM 按照普通邏輯綜合,而 Synplify Pro 與之不同。Synplify Pro 使 用 FSM Compiler,先將 FSM 編譯為類似狀態(tài)轉(zhuǎn)移圖的連接圖,然后對(duì) FSM 重新編碼、優(yōu)化以達(dá)到更好的綜合效果。

FSM Compiler 適應(yīng)于有以下需求的場(chǎng)合:需要優(yōu)化 FSM 設(shè)計(jì),達(dá)到更好的綜合效果;使用 FSM Viewer 調(diào)試狀態(tài)機(jī);使用 FSM Explorer 進(jìn)一步優(yōu)化有限狀態(tài)機(jī)。

FSM Complier 的使用非常靈活,可以對(duì)整個(gè)設(shè)計(jì)的所有狀態(tài)機(jī)都用 FSM Compiler 進(jìn)行優(yōu)化,也可以僅僅對(duì)指定的狀態(tài)機(jī)進(jìn)行優(yōu)化。對(duì)整個(gè)設(shè)計(jì)使用 FSM Compiler 進(jìn)行優(yōu)化,只需在主界面重要綜合優(yōu)化參數(shù)中選擇【FSM Compiler】選項(xiàng),或者在綜合優(yōu)化參數(shù)設(shè)置時(shí)選中【FSM Compiler】選項(xiàng)即可。如果覺得設(shè)計(jì)其他 FSM 已經(jīng)滿意,而僅對(duì)某個(gè) FSM 不滿意時(shí),可以在源代碼或綜合約束文件中手動(dòng)添加綜合屬性,指定對(duì)單獨(dú)狀態(tài)機(jī)的編譯與優(yōu)化。FSM Compiler 綜合屬性如表 1-2 所示。

表 1-2 FSM Compiler 綜合屬性用法


(2) 有限狀態(tài)機(jī)探測(cè)器(FSM Explorer)

FSM Explorer 使用 FSM Compiler 的編譯結(jié)果,精選不同的編碼方式進(jìn)行狀態(tài)機(jī)編碼試探,從而達(dá)到對(duì) FSM 編碼的最佳優(yōu)化效果。與 FSM Compiler 相比,F(xiàn)SM Explorer 的優(yōu)化效果往往更好,編譯優(yōu)化所花費(fèi)的時(shí)間也更長。

對(duì)設(shè)計(jì)使用 FSM Explorer 的方法也有兩種:第一種是對(duì)整個(gè)設(shè)計(jì)的所有 FSM 自動(dòng)運(yùn)用FSM Explorer;第二種是對(duì)設(shè)計(jì)中特定的 FSM 使用 FSM Explorer。第一種方法可以在Synplify Pro 主界面重要綜合優(yōu)化參數(shù)中選擇 FSM Explorer 有效,或者在綜合優(yōu)化參數(shù)設(shè)置對(duì)話框選中【FSM Explorer】選項(xiàng);第二種方法需要在源代碼或者綜合約束文件中添加使用FSM Explorer 的綜合屬性聲明。FSM Explorer 綜合屬性如表 1-3 所示。


(3) 有限狀態(tài)機(jī)觀察器(FSM Viewer)

在 Synplify Pro 中除了可以使用 RTL 視圖和結(jié)構(gòu)視圖觀察、分析 FSM 外,還可以使用專用 FSM 觀察器(FSM Viewer)分析 FSM。FSM Viewer 將源代碼中描述的 FSM 根據(jù) FSM Compiler 和 FSM Explorer 的編譯優(yōu)化結(jié)果,用狀態(tài)轉(zhuǎn)移圖顯示有限狀態(tài)機(jī)。

表 1-3 FSM Explorer 綜合屬性用法


下面以前面所述舉例的 FSM 為例,講述 FSM Viewer 的使用方法。

【例1-2】 使用 FSM Viewer 分析有限狀態(tài)機(jī)

1. 啟動(dòng) Synplify Pro,單擊打開“Example-1-1\FSM\state2”目錄下state2.prj,單擊按鈕啟動(dòng) RTL 視圖,選擇狀態(tài)機(jī)模塊“statemachine”,單擊按鈕進(jìn)入狀態(tài)機(jī)層次結(jié)構(gòu),或者單擊鼠標(biāo)右鍵,在彈出命令菜單中選擇【View FSM】命令,如圖 1-7 所示。

圖1-8 啟動(dòng) FSM Viewer 分析有限狀態(tài)機(jī)
FSM Viewer 的主界面主要由狀態(tài)轉(zhuǎn)移圖和 FSM 信息顯示選項(xiàng)卡組成。狀態(tài)轉(zhuǎn)移圖是源代碼經(jīng)過編譯再現(xiàn)的狀態(tài)機(jī)。FSM 信息顯示包含轉(zhuǎn)移條件(Transitions)、寄存器傳輸級(jí)狀態(tài)編碼(RTL Encodings)和映射后狀態(tài)編碼(Mapped Encodings)等 3 個(gè)選項(xiàng)卡,如圖 1-8 所示。

圖1-9 FSM Viewer 主界面

選擇某個(gè)狀態(tài),單擊鼠標(biāo)右鍵,在彈出的菜單中可以完成顯示對(duì)象的選擇和屏蔽,有利于理解狀態(tài)之間關(guān)系,增加狀態(tài)轉(zhuǎn)移圖的可讀性,如圖 1-9 所示。

圖1-10 在 FSM Viewer 中選擇和屏蔽狀態(tài)


小結(jié)


狀態(tài)機(jī)不僅僅是一種時(shí)序電路設(shè)計(jì)工具,它更是一種思想方法。狀態(tài)機(jī)的本質(zhì)就是對(duì)具有邏輯順序或時(shí)序規(guī)律事件的一種描述方法。這個(gè)論斷的最重要的兩個(gè)詞就是“邏輯順序”和“時(shí)序規(guī)律”,這兩點(diǎn)就是狀態(tài)機(jī)所要描述的核心和強(qiáng)項(xiàng),換言之,所有具有邏輯順序和時(shí)序規(guī)律的事情都適合用狀態(tài)機(jī)描述。根據(jù) FSM 描述使用的 always 模塊數(shù)和功能可以將 FSM 的描述分為 3 種寫法:
  • 不推薦使用一段式描述方法。因?yàn)橐欢问矫枋龇椒▽顟B(tài)轉(zhuǎn)移判斷的組合邏輯和狀態(tài)寄存器轉(zhuǎn)移的時(shí)序邏輯混寫在同一個(gè) always 模塊中,不符合將時(shí)序和組合邏輯分開描述的 Coding Style(代碼風(fēng)格),而且在描述當(dāng)前狀態(tài)時(shí)要考慮下個(gè)狀態(tài)的輸出,整個(gè)代碼不清晰,不利于維護(hù)修改,并且不利于附加約束,不利于綜合器和布局布線器對(duì)設(shè)計(jì)的優(yōu)化。

  • 推薦使用兩段式狀態(tài)機(jī)描述方法。兩段式描述方法用 2 個(gè) always 模塊,其中一個(gè) always 模塊采用同步時(shí)序描述狀態(tài)轉(zhuǎn)移;另一個(gè)模塊采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律。這種方法使 FSM 描述清晰簡潔,易于維護(hù),易于附加時(shí)序約束,使綜合器和布局布線器更好的優(yōu)化設(shè)計(jì)。

  • 強(qiáng)烈推薦使用三段式描述方法。與一段式描述方法相比較,三段式 FSM 描述方法對(duì) FSM 寄存器輸出的描述只需判斷下一狀態(tài),然后直接將下一狀態(tài)的輸出用寄存器輸出即可,根本不用考慮狀態(tài)轉(zhuǎn)移條件(米勒狀態(tài)機(jī))。與兩段式描述相比,三段式雖然代碼結(jié)構(gòu)復(fù)雜了一些,但是換來的優(yōu)勢(shì)是使 FSM 做到了同步寄存器輸出,消除了組合邏輯輸出的不穩(wěn)定與毛刺的隱患,而且更利于時(shí)序路徑分組,一般來說在 FPGA/CPLD 等可編程邏輯器件上的綜合與布局布線效果更佳。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉