一個(gè)主機(jī)可以建設(shè)多少個(gè)網(wǎng)站seo推廣培訓(xùn)資料
實(shí)例:點(diǎn)燈學(xué)習(xí)
一、Verilog
語法學(xué)習(xí)
1. 參考文章
剛接觸
Verilog
,作為一個(gè)硬件小白,只能嘗試著去理解,文章未完…持續(xù)更新。
參考博客文章:
- Verilog語言入門學(xué)習(xí)(1)
- Verilog語法
- 【
Verilog
】一文帶你了解Verilog
基礎(chǔ)語法 - 子墨祭的文章 - 知乎 - 關(guān)于Verilog中的幾種賦值語句
這里抄點(diǎn),那里扣點(diǎn),整理了一下,感謝以上各位作者。具體的實(shí)例項(xiàng)目是同事給的,他讓我學(xué)著編出個(gè)流水燈,這不要我的命嘛,慢慢學(xué)吧。
你還可以在哪里看到這篇文章:
- 知乎
2. Verilog
模塊
Verilog
的基本設(shè)計(jì)單元是“模塊”。一個(gè)模塊是由兩部分組成的,一部分描述接口,另一部分描述邏輯功能,即定義輸入是如何影響輸出的。下面舉例說明:
可以看到模塊由關(guān)鍵字module....endmodule
確定。
module
模塊名(接口信號(hào));
? //信號(hào)聲明
? //功能描述
endmodule
要求: 1. 模塊名具有意義;2. 一個(gè).v文件只有一個(gè)模塊。
3. Verilog
語法
Verilog
是一種硬件描述語言,以文本形式來描述數(shù)字系統(tǒng)硬件的結(jié)構(gòu)和行為的語言,用它可以表示邏輯電路圖、邏輯表達(dá)式,還可以表示數(shù)字邏輯系統(tǒng)所完成的邏輯功能。
Verilog
和C
的區(qū)別:
Verilog
是硬件描述語言,編譯下載到FPGA
之后,會(huì)生成電路,所以Verilog
全部是并行處理與運(yùn)行的C
語言是軟件語言,編譯下載到單片機(jī)CPU
之后,還是軟件指令,而不會(huì)根據(jù)代碼生成相應(yīng)的硬件電路,而單片機(jī)CPU
處理軟件指令需要取址、譯碼、執(zhí)行,是串行執(zhí)行的。
**可綜合描述:**綜合tool
能夠Verilog
描述轉(zhuǎn)化(complie
)成基本的數(shù)字電路底層cell
(與或非gate
,寄存器等)的描述。
assign y = a & b;
**不可綜合描述:**綜合tool
不能把Verilog
描述轉(zhuǎn)換為基本的數(shù)字電路底層cell
的描述。
$display("hello word.\n")
Verilog
設(shè)計(jì)仿真與實(shí)現(xiàn):通過EDA TOOL
,可以在計(jì)算機(jī)上對(duì)Verilog
設(shè)計(jì)的功能進(jìn)行仿真。
數(shù)字電路設(shè)計(jì)方法學(xué):
Bottom-Up
:從底層cell
開始,逐漸往上加功能;top-Down
:從底層結(jié)構(gòu),協(xié)議算法開始,向下逐步劃分功能模塊;再細(xì)分各功能模塊與IO
。
目前,基于Verilog
的數(shù)字電路通常使用TOP-Down
的設(shè)計(jì)方法。因?yàn)閿?shù)字IP/IC
的規(guī)模很大,需要先抽象思維再細(xì)化;
Verilog
給數(shù)字電路的設(shè)計(jì)的抽象思維提供了一種設(shè)計(jì)語言,但是:數(shù)字設(shè)計(jì)和軟件設(shè)計(jì)不同的,需要Think in Hardware
,寫代碼前先設(shè)計(jì)電路結(jié)構(gòu)。Verilog
的功能描述:
Top-Dowan
描述數(shù)字電路功能:通過模塊module的層次化設(shè)計(jì),實(shí)現(xiàn)一個(gè)復(fù)雜的數(shù)字邏輯功能
Verilog
邏輯值:
邏輯電路中有四種值,即四種狀態(tài):
- 邏輯0:表示低電平,對(duì)應(yīng)電路的
GND
; - 邏輯1:表示高電平,對(duì)應(yīng)電路的
VCC
; - 邏輯X:表示未知,有可能是高電平,也有可能是低電平;
- 邏輯Z:表示高組態(tài),外部沒有激勵(lì)信號(hào)是一個(gè)懸空狀態(tài);
Verilog
的數(shù)字進(jìn)制
Verilog
數(shù)字進(jìn)制格式包括二進(jìn)制、八進(jìn)制、十進(jìn)制和十六進(jìn)制,一般常用的為二進(jìn)制、十進(jìn)制和十六進(jìn)制。
- 二進(jìn)制表示如下:
4'b0101
表示4位二進(jìn)制數(shù)字0101 - 十進(jìn)制表示如下:
4'd2
表示4位十進(jìn)制數(shù)字2 - 十六進(jìn)制表示如下:
4'ha
表示4位十六進(jìn)制數(shù)字a
當(dāng)沒有指定數(shù)字的位寬與進(jìn)制時(shí),默認(rèn)為32位的十進(jìn)制,比如100,實(shí)際上表示的值為
32'd100
4. Verilog
語法詳細(xì)介紹
(1)標(biāo)識(shí)符:
用于定義code
中的各種名字,比如:信號(hào),module
,define
,parameter
;
- 標(biāo)識(shí)符由:字符,數(shù)字,下劃線組成;
- 首字母必須是字母或者下劃線;
- 標(biāo)識(shí)符是區(qū)分大小寫的;
- 信號(hào)名字與信號(hào)功能相對(duì)應(yīng);
不建議大小寫混合使用,普通內(nèi)部信號(hào)建議全部小寫,參數(shù)定義建議大寫
- 用有意義的有效的名字如
sum
、cpu_addr
等- 用下劃線區(qū)分詞語組合,如
cpu_addr
- 采用一些前綴或后綴
- 比如:時(shí)鐘采用
clk
前綴:clk_50m
,clk_cpu
;低電平采用_n
后綴:enable_n
- 統(tǒng)一縮寫,如全局復(fù)位信號(hào)
rst
- 同一信號(hào)在不同層次保持一致,如同一時(shí)鐘信號(hào)必須在各模塊保持一致。
- 自定義的標(biāo)識(shí)符不能與保留字(關(guān)鍵字)同名
- 參數(shù)統(tǒng)一采用大寫,如定義參數(shù)使用
SIZE
(2)關(guān)鍵字
優(yōu)先記錄常用關(guān)鍵字:
關(guān)鍵字 | 含義 |
---|---|
module | 模塊開始定義 |
input | 輸入端口定義 |
output | 輸出端口定義 |
inout | 雙向端口定義 |
parameter | 信號(hào)的參數(shù)定義 |
wire | wire信號(hào)定義 |
reg | reg信號(hào)定義 |
always | 產(chǎn)生reg信號(hào)語句的關(guān)鍵字 |
assign | 產(chǎn)生wire信號(hào)語句的關(guān)鍵字 |
begin | 語句的起始標(biāo)志 |
end | 語句的結(jié)束標(biāo)志 |
posedge、negedge | 時(shí)序電路的標(biāo)志 |
case | Case語句起始標(biāo)記 |
default | Case語句的默認(rèn)分支標(biāo)志 |
endcase | Case語句結(jié)束標(biāo)志 |
if | if/else語句標(biāo)志 |
else | if/else語句標(biāo)記 |
for | for語句標(biāo)記 |
endmodule | 模塊結(jié)束定義 |
(3)注釋:
-
注釋一行:以//開始,到行末;
-
注釋多行:以
/*
開始,到*/
為止的所有內(nèi)容;
(4)數(shù)據(jù)類型:
主要有三大類數(shù)據(jù)類型,
- 寄存器類型;
- 線網(wǎng)類型;
- 參數(shù)類型;
線性數(shù)據(jù):用于連續(xù)賦值語句(assign
)描述組合邏輯或者module
間的信號(hào)連接線;
1) 寄存器類型
寄存器類型表示一個(gè)抽象的數(shù)據(jù)存儲(chǔ)單元,它只能在always
語句和initial
語句中被賦值,并且它的值從一個(gè)賦值到另一個(gè)賦值過程中被保存下來。
如果語句描述的是時(shí)序邏輯,即always
語句帶有時(shí)鐘信號(hào),則該寄存器變量對(duì)應(yīng)為寄存器;如果該過程語句描述的是組合邏輯,即always
語句不帶有時(shí)鐘信號(hào)則該寄存器變量對(duì)應(yīng)為硬件連線
寄存器類型的缺省值是x
(未知狀態(tài))。
寄存器數(shù)據(jù)類型有很多種,如reg
、integer
、real
等,其中最常用的就是reg
類型
reg [31:0] delay_cnt; // 延時(shí)計(jì)數(shù)器
reg key_flag; // 按鍵標(biāo)志wire [3:0] din;
reg [3:0] d0; //4bit
reg d1;//1bit
initial begin //過程賦值語句d1 = 0;#10;d1 = 1;
end
always(posedge clk)begin //clk端一般就是寄存器if(d1) d0 <= din;
end
2)線網(wǎng)類型
線網(wǎng)表示Verilog
結(jié)構(gòu)化元件間的物理連線。
值由驅(qū)動(dòng)元件的值決定,例如連續(xù)賦值或門的輸出。
如果沒有驅(qū)動(dòng)元件連接到線網(wǎng),線網(wǎng)的缺省值為z
(高阻態(tài))。
線網(wǎng)類型,如tri
和wire
等,其中最常用的就是wire
類型,它的使用方法如下:
wire data_en; //數(shù)據(jù)使能信號(hào)
wire [7:0] data;//數(shù)據(jù)wire a;//1bit位寬
wire [3:0] b; //4bit
wire [7:0] c;//8bit
assign a = 1'b0;//連續(xù)賦值語句
assign c = 8'h5a;//8bit的十六進(jìn)制數(shù)
//tri0、tri1:帶下拉、上拉電阻的特性,沒有驅(qū)動(dòng)時(shí),會(huì)由默認(rèn)的值為0/1,一般綜合代碼不用
tri0 s0;
tri1 [20:0] s1;
3)參數(shù)類型
參數(shù)其實(shí)就是一個(gè)常量,常被用于定義狀態(tài)機(jī)的狀態(tài)、數(shù)據(jù)位寬和延遲大小等
可以在編譯時(shí)修改參數(shù)的值,因此又常被用于一些參數(shù)可調(diào)的模塊中,使用戶在實(shí)例化模塊時(shí),可以根據(jù)需要配置參數(shù)。
在定義參數(shù)時(shí),可以一次定義多個(gè)+參數(shù),參數(shù)與參數(shù)之間需要用逗號(hào)隔開。
要注意的是參數(shù)的定義是局部的,只在當(dāng)前模塊中有效。
parameter DATA_WIDTH = 8;//數(shù)據(jù)位寬為8
(5)Verilog
運(yùn)算符
1)算術(shù)運(yùn)算符
+
-
*
/
%
Verilog
實(shí)現(xiàn)乘除比較浪費(fèi)組合邏輯資源,尤其是除法。一般2的指數(shù)次冪的乘除法使用移位運(yùn)算來完成運(yùn)算.
非2的指數(shù)次冪的乘除法一般是調(diào)用現(xiàn)成的IP
,QUARTUS/ISE
等工具軟件會(huì)有提供,不過這些工具軟件提供的IP
也是由最底層的組合邏輯(與或非門等)搭建而成的。
2)關(guān)系運(yùn)算符
>
<
>=
<=
==
!=
用來進(jìn)行條件判斷,在進(jìn)行關(guān)系運(yùn)算符時(shí),如果聲明的關(guān)系是假的,則返回值是0,如果聲明的關(guān)系是真的,則返回值是1;
所有的關(guān)系運(yùn)算符有著相同的優(yōu)先級(jí)別,關(guān)系運(yùn)算符的優(yōu)先級(jí)別低于算術(shù)運(yùn)算符的優(yōu)先級(jí)別。
3)邏輯運(yùn)算符
!
&&
||
連接多個(gè)關(guān)系表達(dá)式,可實(shí)現(xiàn)更加復(fù)雜的判斷,一般不單獨(dú)使用,都需要配合具體語句來實(shí)現(xiàn)完整意思。
4)條件運(yùn)算符
?
:
從兩個(gè)輸入中選擇一個(gè)作為輸出的條件選擇結(jié)構(gòu),功能等同于always
中的if-else
語句。
5)位運(yùn)算符
~
&
|
^
直接對(duì)應(yīng)數(shù)字邏輯中的與、或、非門等邏輯門
位運(yùn)算符一般用在信號(hào)賦值上。
6)移位運(yùn)算符
<<
>>
移位運(yùn)算符包括左移位運(yùn)算符和右移位運(yùn)算符,這兩種移位運(yùn)算符都用0來填補(bǔ)移出的空位。
一般使用左移位運(yùn)算代替乘法,右移位運(yùn)算代替除法,但是只能表示2的指數(shù)次冪的乘除法。
7)拼接運(yùn)算符
{a,b}
可以把兩個(gè)或多個(gè)信號(hào)的某些位拼接起來進(jìn)行運(yùn)算操作
5. 阻塞賦值(Blocking)和非阻塞賦值(Non-Blocking)
(1)阻塞賦值
在一個(gè)always
塊中,后面的語句會(huì)受到前語句的影響,具體來說,在同一個(gè)always
中,一條阻塞賦值語句如果沒有執(zhí)行結(jié)束,那么該語句后面的語句就不能被執(zhí)行,即被“阻塞”。
也就是說always塊內(nèi)的語句是一種順序關(guān)系
符號(hào)“=”用于阻塞的賦值(如:b=a;),阻塞賦值“=”在begin和end之間的語句是順序執(zhí)行,屬于串行語句。其后面的賦值語句從概念上來講是在前面一條語句賦值完成之后才執(zhí)行的。
(2)非阻塞賦值
符號(hào)"<="用于非阻塞賦值(如:b<=a;
),非阻塞賦值是由時(shí)鐘節(jié)拍決定,在時(shí)鐘上升到來時(shí),執(zhí)行賦值語句右邊,然后將begin-end
之間的所有賦值語句同時(shí)賦值到賦值語句的左邊。
begin-end
之間的所有語句,一起執(zhí)行,且是個(gè)時(shí)鐘只執(zhí)行一次,屬于并行執(zhí)行語句。
非阻塞賦值的操作過程可以看作兩個(gè)步驟:
- 賦值開始的時(shí)候,計(jì)算
RHS
(等號(hào)右邊的表達(dá)式); - 賦值結(jié)束的時(shí)候,更新
LHS
(等號(hào)左邊的表達(dá)式)。
非阻塞的概念是指,在計(jì)算非阻塞賦值的RHS
以及LHS
期間,允許其他的非阻塞賦值語句同時(shí)計(jì)算RHS
和更新LHS
。
6. assign和always的區(qū)別
assign
語句使用時(shí)不能帶時(shí)鐘;always
語句可以帶時(shí)鐘,也可以不帶時(shí)鐘;- 在
always
不帶時(shí)鐘是,邏輯功能和assign
完全一致,都是只產(chǎn)生組合邏輯。 - 比較簡單的組合邏輯推薦使用
assign
語句,比較復(fù)雜的組合邏輯推薦使用always
語句。
(1)帶時(shí)鐘和不帶時(shí)鐘的always
always
語句可以帶時(shí)鐘,也可以不帶時(shí)鐘。
- 在
always
不帶時(shí)鐘時(shí),邏輯功能和assign
完全一致,雖然產(chǎn)生的信號(hào)定義為reg
類型,但是該語句產(chǎn)生的還是組合邏輯; - 在
always
帶時(shí)鐘信號(hào)時(shí),這個(gè)邏輯語句才能產(chǎn)生真正的寄存器。
(2)latch
latch
指鎖存器,是一種對(duì)脈沖點(diǎn)平敏感的存儲(chǔ)單元電路
鎖存器和寄存器都是基本存儲(chǔ)單元,鎖存器是電平觸發(fā)的存儲(chǔ)器,寄存器是邊沿觸發(fā)的存儲(chǔ)器。
兩者的基本功能是一樣的,都可以存儲(chǔ)數(shù)據(jù)。
鎖存器是組合邏輯產(chǎn)生的,而寄存器是在時(shí)序電路中使用,由時(shí)鐘觸發(fā)產(chǎn)生的。
latch
的主要危害是產(chǎn)生毛刺(glitch
),這種毛刺對(duì)一級(jí)電路是很危險(xiǎn)的。并且其隱蔽性很強(qiáng),不易查出。
在設(shè)計(jì)中,應(yīng)盡量避免
latch
的使用。
代碼里出現(xiàn)latch
的兩個(gè)原因是在組合邏輯中,if
或者case
語句不完整的描述,比如if
缺少else
分支,case
缺少default
分支,導(dǎo)致代碼在綜合過程中出現(xiàn)了latch
。解決辦法就是if
必須帶else
分支,case
必須帶default
分支。
只有不帶時(shí)鐘的always
語句if
語句或者case
語句不完整才會(huì)產(chǎn)生latch
,帶時(shí)鐘的語句if
或者case
語句不完整描述不會(huì)產(chǎn)生latch
。
7. 狀態(tài)機(jī)
Verilog
是硬件描述語言,硬件電路是并行執(zhí)行的,當(dāng)需要按照流程或者步驟來完成某個(gè)功能是,代碼中通常會(huì)使用很多個(gè)if
嵌套語句來實(shí)現(xiàn),這樣就增加了代碼的復(fù)雜度,以及降低了代碼的可讀性,這個(gè)時(shí)候就可以使用狀態(tài)機(jī)來編寫代碼。
狀態(tài)機(jī)相當(dāng)于一個(gè)控制器,它將一項(xiàng)功能的完成分解為若干步,每一步對(duì)應(yīng)二進(jìn)制的一個(gè)狀態(tài),通過預(yù)先設(shè)計(jì)的順序在各狀態(tài)之間進(jìn)行轉(zhuǎn)換,狀態(tài)轉(zhuǎn)換的過程就是實(shí)現(xiàn)邏輯功能的過程。
狀態(tài)機(jī),全程是有限狀態(tài)機(jī)(Finite State Machine
,縮寫為FSM
),是一種在有限狀態(tài)之間按一定規(guī)律轉(zhuǎn)換的時(shí)序電路,可以認(rèn)為是組合邏輯和時(shí)序邏輯的一種組合。狀態(tài)機(jī)通過控制各個(gè)狀態(tài)的跳轉(zhuǎn)來控制流程,使得整個(gè)代碼看上去更加清晰易懂,在控制復(fù)雜流程的時(shí)候,狀態(tài)機(jī)優(yōu)勢(shì)明顯,因此基本上都會(huì)用到狀態(tài)機(jī),如SDRAM
控制器等。
根據(jù)狀態(tài)機(jī)的輸出是否與輸入條件相關(guān),可將狀態(tài)機(jī)分為兩大類,即摩爾(Moore
)狀態(tài)機(jī)和米勒(Mealy
)型狀態(tài)機(jī)
Mealy
狀態(tài)機(jī):組合邏輯的輸出不僅取決于當(dāng)前狀態(tài),還取決于輸入狀態(tài)
Moore
狀態(tài)機(jī):組合邏輯的輸出只取決于當(dāng)前狀態(tài)
(1)三段式狀態(tài)機(jī)
根據(jù)狀態(tài)機(jī)的實(shí)際寫法,狀態(tài)機(jī)還可以分為一段式、和二段式和三段式狀態(tài)機(jī)。
- 一段式:整個(gè)狀態(tài)機(jī)寫到一個(gè)
always
模塊里面,在該模塊中即描述狀態(tài)轉(zhuǎn)移,又描述狀態(tài)的輸入和輸出。
不推薦,一般都會(huì)要求把組合邏輯和時(shí)序邏輯分開,組合邏輯和時(shí)序邏輯混合在一起不利于代碼維護(hù)和修改
- 二段式:用兩個(gè)
always
模塊來描述狀態(tài)機(jī),其中一個(gè)always
模塊采用同步時(shí)序描述狀態(tài)轉(zhuǎn)移;另一個(gè)模塊采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律以及輸出,需要定義兩個(gè)狀態(tài),現(xiàn)態(tài)和次態(tài),然后通過現(xiàn)態(tài)和次態(tài)的轉(zhuǎn)換來實(shí)現(xiàn)時(shí)序邏輯。 - 三段式:在兩個(gè)
always
模塊描述方法基礎(chǔ)上,使用三個(gè)always
模塊,一個(gè)always
模塊采用同步時(shí)序描述狀態(tài)轉(zhuǎn)移,一個(gè)always
采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律,另一個(gè)always
模塊描述狀態(tài)輸出(可以用組合電路輸出,也可以時(shí)序電路輸出)。- 三段式狀態(tài)機(jī)的基本格式是:
- 第一個(gè)
always
語句實(shí)現(xiàn)同步狀態(tài)跳轉(zhuǎn); - 第二個(gè)
always
語句采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件; - 第三個(gè)
always
語句描述狀態(tài)輸出(可以用組合電路輸出,也可以時(shí)序電路輸出)。
- 第一個(gè)
- 三段式狀態(tài)機(jī)的基本格式是:
8. 模塊化設(shè)計(jì)
劃分模塊的基本原則是子模塊功能相對(duì)獨(dú)立、模塊內(nèi)部聯(lián)系盡量緊密、模塊間的連接盡量簡單。
在進(jìn)行模塊化設(shè)計(jì)中,對(duì)于復(fù)雜的數(shù)字系統(tǒng),我們一般采用自頂向下的設(shè)計(jì)方式??梢园严到y(tǒng)劃分成幾個(gè)功能模塊,每個(gè)功能模塊再劃分成下一層的子模塊;每個(gè)模塊的設(shè)計(jì)對(duì)應(yīng)一個(gè)module
,一個(gè)module
設(shè)計(jì)成一個(gè)Verilog
程序文件。因此,對(duì)一個(gè)系統(tǒng)的頂層模塊,我們采用結(jié)構(gòu)化的設(shè)計(jì),即頂層模塊分別調(diào)用了各個(gè)功能模塊。
FPGA
邏輯設(shè)計(jì)中通常是一個(gè)大的模塊中包含了一個(gè)或多個(gè)功能子模塊,Verilog
通過模塊調(diào)用或稱為模塊實(shí)例化的方式來實(shí)現(xiàn)這些子模塊與高層模塊的連接,有利于簡化每一個(gè)模塊的代碼,易于維護(hù)和修改。
如果子模塊內(nèi)部使用parameter
定義了一些參數(shù),Verilog
也支持對(duì)參數(shù)的例化(也叫參數(shù)的傳遞),即頂層模塊可以通過例化參數(shù)來修改子模塊內(nèi)定義的參數(shù)。
子模塊名是指被例化模塊的模塊名,而例化模塊名相當(dāng)于標(biāo)識(shí),當(dāng)例化多個(gè)相同模塊時(shí),可以通過例化名來識(shí)別哪一個(gè)例化,一般命名為“u_”+“子模塊名”
參數(shù)的例化,參數(shù)的例化是在模塊例化的基礎(chǔ)上,增加了對(duì)參數(shù)的信號(hào)定義
// 例子
time_count #(.MAX_NUM (TIME_SHOW) // 參數(shù)例化
)u_time_count(.clk (sys_clk),.rst_n (sys_rst_n), // 信號(hào)例化.flag (add_flag)
);
9. Verilog
的編程規(guī)范
工程的組織形式一般包括如下幾個(gè)部分,分別是doc、par、rtl
和sim
四個(gè)部分
doc
:一般存放工程相關(guān)的文檔,包括該項(xiàng)目用到的datasheet(數(shù)據(jù)手冊(cè))、設(shè)計(jì)方案等。par
:主要存放工程文件和使用到的一些IP
文件rtl
:主要存放工程的rtl
代碼,是工程的核心,文件名與module
名稱應(yīng)當(dāng)一致,建議按照模塊的層次分開存放sim
:主要存放工程的仿真代碼,復(fù)雜的工程里面,仿真也是不可或缺的部分,可以極大減少調(diào)試的工作量。
(1)文件頭聲明
每一個(gè)Verilog
文件的開頭,都必須有一段聲明的文字。包含文件的版權(quán)、作者、創(chuàng)建日期,以及內(nèi)容簡介等等
//*************************************Copyright(c)*******************//
// FileName:
// Last modified Date:
// Last Version:
// Descriptions:
//*******************************************************************//
(2)輸入輸出定義
module led(input sys_clk, // 系統(tǒng)時(shí)鐘input sys_rst_n , // 系統(tǒng)復(fù)位output reg [3:0] led // 4位LED燈
);
- 一行只定義一個(gè)信號(hào)
- 信號(hào)全部對(duì)齊
- 同一組的信號(hào)放在一起
(3)parameter定義
module
中的parameter
聲明,不建議隨處亂放,將parameter
定義放在緊跟著module
的輸入輸出定義之后- parameter等常量命名全部使用大寫
(4)wire/reg定義
一個(gè)module
中的wire/reg
變量聲明需要集中放在一起,不建議隨處亂放
- 將
reg
與wire
的定義放在緊跟著parameter
之后 - 建議具有相同功能的信號(hào)集中放在一起
- 信號(hào)需要對(duì)齊,
reg
和位寬需要空2
格,位寬和信號(hào)名字至少空四格 - 位寬使用降序描述,
[6:0]
- 時(shí)鐘使用前綴
clk
,復(fù)位使用后綴rst
- 一行只定義一個(gè)信號(hào)
(5)信號(hào)命名
- 內(nèi)部信號(hào)不要使用大寫,也不要使用大小寫混合,建議全部使用小寫
- 模塊名字使用小寫
- 異步信號(hào),使用
_a
作為信號(hào)后綴
(6)always塊
- 一個(gè)
always
需要配一個(gè)begin
和end
always
前面需要有注釋- 一個(gè)
always
和下一個(gè)always
空一行即可,不要空多行 - 時(shí)序邏輯使用非阻塞賦值
(7)assign塊
assign
的邏輯不能太復(fù)雜,否則易讀性不好assign
前面需要有注釋- 組合邏輯使用阻塞賦值
(8)空格 和 TAB
- 由于不同的解釋器對(duì)于
TAB
翻譯不一致,所以建議不使用TAB
,全部使用空格
二、環(huán)境Lattice Dimond環(huán)境的搭建
-
從
Lattice
的官網(wǎng)下載Dimond
,下一步下一步安裝; -
獲取電腦的
MAC
地址,注意是有線網(wǎng)卡的MAC
地址,不能是無線的; -
在官網(wǎng)申請(qǐng)免費(fèi)的證書,這里有問題,官網(wǎng)不會(huì)跳出來,所以是請(qǐng)同事幫忙生成的;
-
打開軟件添加證書文件,即可。
-
Lattice官網(wǎng)鏈接
-
證書申請(qǐng)網(wǎng)址
(有的會(huì)跳出來什么聯(lián)系管理員,我這里是把IP
改為馬來西亞打開網(wǎng)址的)
填寫物理網(wǎng)卡MAC地址質(zhì)料:
新建工程項(xiàng)目:
選擇芯片,我的板子上的芯片是:
生成項(xiàng)目文件夾:
添加Verilog
文件;
這樣就可以編寫Verilog
代碼了。
三、點(diǎn)燈實(shí)例分析
同事給出的一段實(shí)例,能夠點(diǎn)亮兩個(gè)燈;
實(shí)例環(huán)境硬件如下:
- 電腦
- 可調(diào)電源
module clk_div
(
in_clk,
clk_8hz,
clk_1hz,
pg_rstn
);input in_clk;
output clk_8hz;
output clk_1hz;
input pg_rstn; reg [4:0] count0_r;
reg [8:0] count1_r;
reg [9:0] count2_r;reg div0_clk;
reg div1_clk;
reg div2_clk;wire clk_1hz;
wire clk_8hz;assign clk_1hz = count2_r[9];
assign clk_8hz = count2_r[6];always @(posedge in_clk or negedge pg_rstn) //25M--1M
beginif (!pg_rstn)begindiv0_clk<= 1'b1;count0_r <= 5'b0; endelse if (count0_r==5'b11001)begindiv0_clk<=1'b1; count0_r<=5'b0;end elsebegincount0_r<=count0_r+1'b1;div0_clk<= 1'b0; end
endalways @(posedge div0_clk or negedge pg_rstn) //1M--1k
beginif (!pg_rstn)begincount1_r <= 9'b0;div1_clk <= 1'b0;endelse if (count1_r==9'h1ff)begindiv1_clk<=~div1_clk; count1_r<=9'h0;endelsecount1_r<=count1_r+1'b1;
endalways @(posedge div1_clk or negedge pg_rstn) //1k--1Hz
beginif (!pg_rstn)begincount2_r <= 10'b0;endelse if (count2_r==10'h3ff)begin count2_r <= 10'b0; endelsebegincount2_r <= count2_r+1'b1;end
endOSCH #("10.23") osc_int (.STDBY(1'b0),.OSC(clk_i),.SEDSTDBY());endmodule
1. 實(shí)例代碼分析
module clk_div
(
in_clk,
clk_8hz,
clk_1hz,
pg_rstn
);
input in_clk;
output clk_8hz;
output clk_1hz;
input pg_rstn;
....
endmodule
這一段是接口定義,定義了兩個(gè)輸出信號(hào)clk_8hz
、clk_1hz
,代表兩個(gè)燈不同的頻率。兩個(gè)輸入信號(hào)in_clk
、pg_rstn
指芯片的時(shí)鐘和復(fù)位。
模塊由關(guān)鍵字module....endmodule
確定。
clk_div
模塊名
reg [4:0] count0_r;//5bit
reg [8:0] count1_r;//9bit
reg [9:0] count2_r;//10bit
reg
定義寄存器,寄存器數(shù)據(jù)類型有很多種,如reg、integer、real
等,其中最常用的就是reg
類型。
reg div0_clk;
reg div1_clk;
reg div2_clk;
默認(rèn)位寬是1。
wire clk_1hz;
wire clk_8hz;
wire
定義的是線網(wǎng),線網(wǎng)指的是Verilog
結(jié)構(gòu)化元件間的物理連線
assign clk_1hz = count2_r[9];
assign clk_8hz = count2_r[6];
-
assign
產(chǎn)生wire
信號(hào)語句的關(guān)鍵字,連續(xù)賦值語句assign -
比較簡單的組合邏輯推薦使用
assign
語句,比較復(fù)雜的組合邏輯推薦使用always
語句。 -
reg與wire的區(qū)別詳細(xì)
always @(posedge in_clk or negedge pg_rstn) //25M--1M
beginif (!pg_rstn)begindiv0_clk<= 1'b1;//一位二進(jìn)制數(shù)1count0_r <= 5'b0;//五位二進(jìn)制數(shù)0endelse if (count0_r==5'b11001)//五位二進(jìn)制數(shù)11001begindiv0_clk<=1'b1;count0_r<=5'b0;end
-
時(shí)序邏輯 ,帶異步復(fù)位 ;
-
posedge
是上升沿,電平從低到高跳變 -
negedge
是下降沿,電平從高到低跳變 -
參考文章
文章持續(xù)更新,由于剛接觸,所以很多東西也分析不錯(cuò)來,之后慢慢補(bǔ)充。
2. 編譯運(yùn)行
- 編譯代碼
- 生成
JED
文件
- 引腳設(shè)置
- 找到項(xiàng)目中的
.jed
文件
- 設(shè)備上電,插上燒錄器插上電腦。點(diǎn)擊燒錄
- 等待
- 完成
四、總結(jié)
這東西對(duì)于像我這樣跨專業(yè)的初學(xué)者來說真難,慢慢學(xué)吧,之后會(huì)找有關(guān)書或者視頻,更新Verilog
語言的基礎(chǔ)學(xué)習(xí)筆記。