IP:知識產權核
Verilog HDL/VHDL:硬件描述語言 .qpf是工程文件,.v是源代碼文件。
integer是有符號數,而人是無符號數。
將負數賦值給變量時使用二進制的補碼運算。
位操做時都是從低位對齊,位數不齊的會在高位自動補零。
邏輯運算符的運算結果只有一位,即1,0,X(未知/高阻態)。異步
Verilog代碼詳細講解
代碼重點關注:1).輸入輸出。2).信號位寬。3).計數 等功能。
外面信號給到FPGA裏面的是輸入,用input; 從FPGA裏面出來的信號是輸出,用output;
位寬例:output[x:0] led;在led這條線上有(x+1)個管腳(通常是I/O管腳,即led的位寬=(x+1)位,也是有(x+1)比特。比特(bit)就是位的意思。
取x=1,則led賦值就要寫成led <= 2'b00(阻塞賦值);或led = 2'b00(阻塞賦值);等號後面的格式爲: 位寬'b(比特)xx..(信號個數狀態)
注意:數在機器裏面是用二進制表示的,即用時注意位寬;如:reg[7:0] aa;aa最大表示只能=1111 1111,即aa=2^8-1=255。
通常的信號(輸入輸出信號)賦值最好用 :信號x = 位寬'b(比特)xx.. 這種形式表示。
注:Verilog代碼是不按順序執行的,好比各個always塊是同時執行的。測試
1.1設計時用不到的語法
①initial【設計時不用,仿真時用】
②task/function【設計時不用,仿真時不多用】
③for/while/repeat/forever【設計時不用,仿真時不多用】
④integer【設計時不用】
⑤模塊內不能有X態,Z態,內部不能有三態接口
⑥cases/casez【設計時仿真時都不用】
⑦force/wait/fork【設計時不用,仿真時不多用】
⑧#5【設計時不用,仿真時用】設計
1.2設計時使用語法
①reg/wire,parameter
②assign【建議更名時使用】,always
③只容許使用if else和case兩種條件語句
④各類運算符接口
2.1電路設計的3種結構 【posedge是上升沿,negedge是降低沿】
①組合邏輯(無clk信號)【always @ (*)】//若是沒有@,那就是不會知足特定條件才執行,而是執行完一次後立馬又重複執行,
always @ (*) //*表明敏感變量,敏感變量由綜合器根據always裏面的輸入變量自動添加,不用本身考慮。
begin
語句...
end
②時序邏輯(兩種(必有clk信號))【always @ (posedge clk)】
第一種:同步復位的時序電路(只和時鐘信號有關)
always @ (posedge clk)begin
if(rst_n == 1'b0)begin
語句...
else begin
語句...
end
end
第一種:異步復位的時序電路(與復位信號和時鐘信號有關)
always @ (posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
語句
else begin
語句
end
endinput
3.電路規範設計的要點注意:(三種電路,兩種條件,一一法則。注意理解字面意思)
①一個always只產生一個信號,就是說always裏面最好只能有一個信號變化(方便信號觀察),可是--》請看下面的引用同步
爲何會有一個「always裏面只輸出/產生一個信號,避免互相干擾」這樣的說法?由於在很早的時候,綜合器功能還不是很健全,把多個信號寫在一個always塊裏,可能會獲得與你期待不一樣的結果。而將每一個信號單獨寫在一個always塊裏,綜合器能夠比較容易識別,獲得你想要的結果。可是,如今不同的了,綜合器已經十分智能。因此,在always裏寫多個信號也是能夠的,可是須要注意,組合邏輯和時序邏輯最好分開,另外不能用程序化的思惟去思考。這段解釋來自(https://www.zhihu.com/question/37293913/answer/72097040)it
②一個信號只能在一個always裏面產生(這點重點注意,就是說信號變量只能在單獨的一個always語句中賦值,不能出如今兩個或以上的always語句中賦值的狀況)
③always是描述一個信號產生的方法,記載什麼狀況下,這個信號的值是多少;在其餘狀況下,值爲多少(要所有考慮)
④條件判斷只容許使用if else和case,其餘全都不用。
⑤有posedge或negedge的,必定是D觸發器,是時序電路
⑥設計時,若是想當即有結果的,那就用組合邏輯;若是想延時一拍有結果,那就用時序邏輯;io
4例化(本身去了解)
4.1例化()
4.2例化方法舉例:
module qq( ------->>>>>> qq(設計模塊名) u_qq(例化模塊名)(
clk; ------->>>>>> .clk ();
rst_n; ------->>>>>> .rst_n ();
vld_in; ------->>>>>> .vld_in ();
. .
. .
. .
rdy_in ------->>>>>> .rdy_in (裏面放例化模塊的信號)
); );
4.3參數例化。function
5.1信號類型(reg/wire)講解
①設計代碼僅用reg和wire。
②設計代碼:由本模塊產生且是用always產生的信號,則用reg類型
③測試代碼:用initial產生的信號(通常是對測試模塊的輸入),用reg類型
④其餘都用wire。
⑤reg信號,不必定產生寄存器。
5.2參數paramete
①如:parameter QQ=12;----->>>>> :就是將整個模塊內的QQ替換成12.
②要求參數名要大寫。變量
5.2運算符(注意運算以後位寬的問題,運算以後的位寬可能會改變,注意 )
算術運算符(FPGA裏面儘可能用+,-,*不用或少用/,%(用到大量的邏輯塊))
①時序邏輯用 "<=" (注:"<="不是判斷,它在判斷裏面使用才被認爲是判斷符,在其餘地方都是賦值符號)
②組合邏輯或assign語句裏面用 "="。(組合邏輯敏感列表是*號,時序邏輯是posedge信號或者negedge信號)
③邏輯運算符(&&,||,!),通常兩邊都是1比特信號,通常用於條件判斷
④位運算符(~,|,^,&)通常用於賦值語句,在不一樣長度的數據進行位運算時,系統會自動的將兩個數右端對齊,
位數少的操做數會在相應的高位補0,一時的兩個操做數按位進行操做。
⑤移位運算符(<<,>>)通常用於乘除運算。右移多少位,至關於除以2的多少次方,左移相反。注意一下:
4'b1001<<1=5'b10010; 4'b1001<<2=6'b100100; (左移會使得位數增長?)
1<<6=32'b1000000; 4'b1001>>1=4'b0100; (右移不會改變位數?)
可是若是操做數已經定義了位寬,則進行移位後操做數改變,可是其位寬不變。
4‘b1001>>4=4'b0000;
⑥拼接運算符({}),{信號1的某幾位,信號2的某幾位,......信號n的某幾位} 將某些信號的某些爲列出來,中間用逗號分開,最後用大括號括起來表示一個總體的信號。
在位拼接的表達式中不容許存在沒有指明位數的信號。
{a,b[3:0],w,3'b101} //等同於{a,b[3],b[2],b[1],b[0],w,1b'1,1'b0,1'b1}
{4{w}} //等同於{w,w,w,w}
{b,{3{a,b}}} //等同於{b,a,b,a,b,a,b} 這裏面的三、4必須是常量表達式。
⑦縮減運算符
這是單目運算符,也包括與、或、非運算。運算規則與位運算類似,不過是對單個運算符的每一位逐步運算,最後的運算結果是一位的二進制數。
c=&B; //意思同c=((B[0]&B[1]) &B[2] ) & B[3];
6賦值語句在Verilog HDL語言中,信號有兩種賦值方式。A)非阻塞賦值(Non-Blocking)方式(如:b<=a;)(1)在語句塊中,上面語句所賦值的變量不能當即爲下面的語句所用;(2)塊結束後才能完成此次賦值操做,賦值的職位上次賦值獲得的;(3)在編寫可綜合的時序邏輯模塊時,這是最經常使用的複製方法。B)阻塞賦值(Blocking)方式(如:b=a;)(1)賦值語句完成後,塊才結束;(2)b的值在賦值語句執行完後馬上改變。(3)在時序邏輯中使用時,可能會產生意想不到的結果。