挺久沒有更新,今天更新一篇小文章。最近正在整理一個(gè)SDRAM控制器的教程(VHDL),現(xiàn)在更新的小文章是想為后續(xù)的SDRAM教程以及其它比較大的教程做鋪墊。本文主要講關(guān)于VHDL編碼風(fēng)格(Verilog也可以用同樣的思想),這篇文章的核心思想就是:設(shè)計(jì)中的所有狀態(tài)都應(yīng)該被明確聲明在寄存器中。
這句話什么意思先不談,直接上兩段代碼,第一段如下:
library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use work.ff.all; -- 一些常用的元件包,這里面是可以自己寫的
-- 這篇文章主要就調(diào)用了基本的D觸發(fā)器,里面還有什么可以先忽略
entity Bad_Counter is generic( n: integer := 4 ); port( clk, rst: in std_logic;
output: buffer std_logic_vector(n-1 downto 0) );end Bad_Counter;
architecture impl of Bad_Counter issignal nxt: std_logic_vector(n-1 downto 0);begin process(clk) begin
if rising_edge(clk) then
if rst then
output 《= (others =》 ‘0’);
else
output 《= output + 1;
end if;
end if; end process;end impl;
一個(gè)4位計(jì)數(shù)器,能實(shí)現(xiàn)設(shè)計(jì)的功能,但其中output 《= output + 1存在一點(diǎn)問題,這種寫法非常C語言化,這也是很多人習(xí)慣的寫法。為什么說這種寫法不好,因?yàn)樗煜水?dāng)前狀態(tài)和下一狀態(tài)。先不多解釋,看下一段代碼如下:
library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use work.ff.all; -- 一些常用的元件包,這里面是可以自己寫的
-- 這篇文章主要就調(diào)用了基本的D觸發(fā)器,里面還有什么可以先忽略
entity Good_Counter is generic( n: integer := 4 ); port( clk, rst: in std_logic;
output: buffer std_logic_vector(n-1 downto 0) );end Good_Counter;
architecture impl of Good_Counter is signal nxt: std_logic_vector(n-1 downto 0);begin nxt 《= (others=》‘0’) when rst else output+1;
count: vDFF generic map(n) port map(clk, nxt, output);end impl;
這段代碼同樣的是4位計(jì)數(shù)器,為什么用這兩段代碼做比較,非常典型,第一段代碼的思想就是C語言的思想來寫的,很多人可能沒有注意自己在寫“數(shù)字電路”,也沒有特別關(guān)注寫出來的代碼綜合出來是什么樣子。第二段代碼明確表明nxt是下一狀態(tài),并且nxt是通過當(dāng)前狀態(tài)output得到的,這很重要,與此同時(shí)還調(diào)用了一個(gè)D觸發(fā)器元件,這個(gè)D觸發(fā)器為什么用,之前在異步FIFO(二)中有談到:在實(shí)現(xiàn)所有的狀態(tài)變量都應(yīng)該被明確的聲明位D觸發(fā)器,不要讓編譯器去推斷應(yīng)該用什么觸發(fā)器。
講到這里,可能還是不懂這兩份代碼有什么具體的差別,我做了一個(gè)實(shí)驗(yàn),把兩份代碼都綜合了一遍,使用了兩個(gè)不同的版本,Quartus20.3和Quartus13.1(不同版本的軟件,無論是效率還是開發(fā)便捷程度還是有一定差別的)
先看Quartus13.1綜合出的兩份原理圖
這幅原理圖是第一份代碼綜合出來了,大概看一下沒什么問題,代碼也是這樣寫的。
再看第二份代碼綜合出來的原理圖
區(qū)別來了,很明顯,第一份代碼因?yàn)橛胦utput <= output + 1的原因,左右兩端使用了相同的信號(hào),混淆當(dāng)前狀態(tài)和下一狀態(tài),下一狀態(tài)被隱藏起來。但第二份代碼綜合出來的很明顯,nxt是下一狀態(tài),并且nxt是通過當(dāng)前狀態(tài)output得到的。當(dāng)然還要個(gè)比較好的地方,第二份代碼直接調(diào)用D觸發(fā)器元件(在package里面寫了),告訴編譯器狀態(tài)變量要聲明為D觸發(fā)器,而不是讓編譯器自己判斷(盡管它可以)。
再看Quartus20.3綜合出來的原理圖
這個(gè)原理圖是第一份代碼Bad_Counter 綜合出來的,很顯然現(xiàn)在的EDA真行,可以把不那么優(yōu)秀的代碼綜合出優(yōu)秀代碼才能綜合出的原理圖了。當(dāng)然這是很簡單代碼的情況下。
這個(gè)原理圖是第二份代碼Good_Counter綜合出來的,除了下一狀態(tài)的命名和位數(shù)區(qū)間不一樣外,其它的兩個(gè)代碼綜合出來的沒有區(qū)別!
小結(jié):從上面的四幅原理圖看,盡管隨著EDA的發(fā)展讓不那么優(yōu)秀的代碼綜合出和優(yōu)秀代碼一樣的原理圖,但良好編碼風(fēng)格的代碼仍然非常必要,即使是13.1和20.3巨大版本差異的情況下,良好編碼風(fēng)格的代碼綜合出來的原理圖也是一樣的。但在代碼風(fēng)格不好的情況下,13.1和20.3卻有比較大的差距。人作為設(shè)計(jì)的主體,不能完全依靠EDA的優(yōu)化,編譯器也不是萬能的,有些其它地方未必會(huì)優(yōu)化的那么好,在大型復(fù)雜項(xiàng)目中不太好的編碼風(fēng)格可能編譯器也未必能夠給出比較好的優(yōu)化,好的編碼風(fēng)格可以讓我們更好的理解一些底層的設(shè)計(jì),也能知道代碼會(huì)如何綜合。更重要的是需要知道自己數(shù)字設(shè)計(jì)師!用數(shù)字的思想去設(shè)計(jì)FPGA。這些只是自己的意見,大家可以做一個(gè)參考,有不對(duì)的地方也歡迎批評(píng)指正。
審核編輯 :李倩
-
寄存器
+關(guān)注
關(guān)注
31文章
5343瀏覽量
120363 -
vhdl
+關(guān)注
關(guān)注
30文章
817瀏覽量
128137
原文標(biāo)題:VHDL的編碼風(fēng)格(Verilog也可參考思想)
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論