FPGA需要良好的數(shù)電模電基礎(chǔ),verilog需要良好C語言基礎(chǔ)。
FPGA的準(zhǔn)備工作:下載Quartus II,Modelsim和notepad++(notepad++是文本編輯器,quartus有自帶的,可以不裝,也可以用其他的)。安裝完成后,實現(xiàn)Quartus II與Modelsim和notepad++的關(guān)聯(lián)(不關(guān)聯(lián)notepad++的話默認(rèn)用quartus自帶的)。方法是:tools欄的option,如下圖選中Win64。
關(guān)聯(lián)notepad++如圖,在文件夾中選擇安裝好的exe應(yīng)用程序。
Verilog可能是FPGA路上的第一個絆腳石,但是代碼類的學(xué)習(xí)都是熟能生巧,掌握規(guī)律只需3天即可上手。
基礎(chǔ)語法 :
1、區(qū)分大小寫,分號結(jié)尾(空格、換行無意義),單行注釋用//,多行注釋用/* 代碼 */,標(biāo)識符區(qū)分大小寫,關(guān)鍵字小寫。
2、0表示假,1表示真,X/x表示未知,Z/z表示高阻。
3、十進制('d 或 'D),十六進制('h 或 'H),二進制('b 或 'B),八進制('o 或 'O),4'b1011中4表示位數(shù),b表示進制,1011是數(shù)值。 字符串用雙引號且不能換行。
4、最常用的數(shù)據(jù)類型:wire和reg,wire 表示物理連線,reg表示存儲單元。
5、表達式由操作符和操作數(shù)構(gòu)成,其中操作符有算術(shù)、關(guān)系、等價、邏輯、按位、歸約、移位、拼接、條件共9種,操作數(shù)可以是任意的數(shù)據(jù)類型。注意邏輯與(&&)、按位與(&)。
數(shù)電中有組合邏輯電路和時序邏輯電路。組合邏輯電路模塊:
6、連續(xù)賦值語句以assign開頭用于對 wire 型變量進行賦值
7、普通時延:assign #10 Z = A & B ;把A與B的結(jié)果延時10個單位再賦值給Z。隱式時延:wire #10 Z = A & B;聲明wire型變量時對其進行包含一定時延的連續(xù)賦值。A 或 B 任意一個變量發(fā)生變化,那么 Z會有 10 個時間單位的時延。如果在這 10 個時間單位內(nèi),A 或 B 任意一個值又發(fā)生了變化,那么計算 Z 的新值時會取 A 或 B 當(dāng)前的新值。所以稱之為慣性時延,即信號脈沖寬度小于時延時,對輸出沒有影響。因此仿真時,時延一定要合理設(shè)置,防止某些信號不能進行有效的延遲。
時序邏輯電路模塊:
8、一個模塊中可以包含多個 initial 和 always 語句,但 2 種語句不能嵌套使用。語句在模塊間并行執(zhí)行,與前后順序無關(guān)。語句內(nèi)部是順序執(zhí)行的(非阻塞賦值除外)。**initial **語句從 0 時刻開始執(zhí)行,只執(zhí)行一次,多個 initial 塊之間是相互獨立的。如果 initial 塊內(nèi)包含多個語句,需要使用關(guān)鍵字 begin 和 end 組成一個塊語句。只包含一條語句可以不用。**always **語句是重復(fù)執(zhí)行的。always 語句塊從 0 時刻開始執(zhí)行其中的行為語句;當(dāng)執(zhí)行完最后一條語句后,便再次執(zhí)行語句塊中的第一條語句,如此循環(huán)反復(fù)。always 語句多用于仿真時鐘的產(chǎn)生,信號行為的檢測等。
后面會結(jié)合數(shù)電詳細(xì)講解。
1、熟悉wire
module top_module(
input a,
input b,
input c,
input d,
output out,
output out_n );
assign out=(a&b)|(c&d);
assign out_n=~((a&b)|(c&d));
endmodule
verilog采用自頂向下的設(shè)計方法,分模塊設(shè)計,這樣做的好處是,不同的人可以負(fù)責(zé)不同的模塊,最后組裝起來。每個模塊都以Module 模塊名開始,以endmodule結(jié)尾,且需要定義輸入輸出,以及輸出與輸入的關(guān)系。在這個實例中,需要填入的就是兩個assign語句,得到out和out_n。
2、熟悉向量
當(dāng)位寬大于 1 時,wire 或 reg 即可聲明為向量的形式。
module top_module(
input [2:0] a,
input [2:0] b,
output [2:0] out_or_bitwise,
output out_or_logical,
output [5:0] out_not
);
assign out_or_bitwise=a|b;
assign out_or_logical=a||b;
assign out_not={~b,~a};
endmodule
邏輯或||和位或|的區(qū)別:位或是兩個 N 位向量之間的每一位都進行或運算形成N位新向量,而邏輯運算將整個向量視為布爾值(true = 非零,false = 零)并生成 1 位輸出。{向量1,向量2,...}可以用于合并向量。位數(shù)少時可以用于向量反轉(zhuǎn),例如in[3:0]反轉(zhuǎn)可以使out={in[0],in[1],in[2],in[3]}。
module top_module (
input a, b, c, d, e,
output [24:0] out );//
assign out=~{{5{a}},{5},{5{c}},{5fxvch99},{5{e}}}^{5{a,b,c,d,e}};
endmodule
向量復(fù)制的格式是{復(fù)制次數(shù){向量}},注意復(fù)制后的向量需要用{}。異或是a^b,同或是~a^b。
3、熟悉模塊
和之前在python中一樣,模塊實例化有非常重要的作用。如果事先定義一個模塊的功能,后面每一次使用時,都只需要讓自己定義的端口對應(yīng)上原模塊的端口,就可以調(diào)用。如果不這樣做,每一次使用都需要寫一次這個模塊的代碼。
實例化有兩種方式,按位置:mod_a instance1 ( wa, wb, wc );按名稱:mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );前一種不建議使用,因為如果模塊的端口列表發(fā)生更改,則還需要查找并更改模塊的所有實例化以匹配新模塊。后一種雖然寫起來比較復(fù)雜,但是將每一個端口都對應(yīng)上,與位置無關(guān)。
按名稱:
module top_module ( input a, input b, output out );
mod_a instance1 (
.out(out),
.in1(a),
.in2(b)
);
endmodule
按位置:
module top_module ( input a, input b, output out );
mod_a instance1 (a,b,out);
endmodule
top_module是模塊名,這個模塊有兩個輸入端口和一個輸出端口。這個模塊里用到了一個事先定義好的函數(shù)mod_a,也有兩個輸入端口和輸出端口。將端口對應(yīng)起來,這個模塊就可以實現(xiàn)mod_a的功能。
下面看幾個復(fù)雜的例子:
移位寄存器
module top_module ( input clk, input d, output q );
wire q1,q2;
my_dff d0(.clk(clk),.d(d),.q(q1));
my_dff d1(.clk(clk),.d(q1),.q(q2));
my_dff d2(.clk(clk),.d(q2),.q(q));
endmodule
這個模塊名是top_module,有時鐘,輸入和輸出。實現(xiàn)定義了一個函數(shù)my_dff,整個模塊使用了三次D觸發(fā)器,因此需要實例化三次。對于函數(shù)d0,d1,d2都需要把端口對應(yīng)上,由于q1,q2是引入的變量,用來將前一級觸發(fā)器輸出和后一級觸發(fā)器輸入連接上,所以需要先聲明q1,q2是wire型變量。
評論
查看更多