0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【ZYNQ Ultrascale+ MPSOC FPGA教程】第三章Verilog基礎(chǔ)模塊介紹

FPGA技術(shù)專欄 ? 來源:芯驛電子科技 ? 作者:芯驛電子科技 ? 2021-01-21 13:25 ? 次閱讀

原創(chuàng)聲明:

本原創(chuàng)教程由芯驛電子科技(上海)有限公司(ALINX)創(chuàng)作,版權(quán)歸本公司所有,如需轉(zhuǎn)載,需授權(quán)并注明出處。

適用于板卡型號:

AXU2CGA/AXU2CGB/AXU3EG/AXU4EV-E/AXU4EV-P/AXU5EV-E/AXU5EV-P /AXU9EG/AXU15EG

簡介

本文主要介紹verilog基礎(chǔ)模塊,夯實(shí)基礎(chǔ),對深入學(xué)習(xí)FPGA會有很大幫助。

數(shù)據(jù)類型

常量

整數(shù):整數(shù)可以用二進(jìn)制b或B,八進(jìn)制o或O,十進(jìn)制d或D,十六進(jìn)制h或H表示,例如, 8’b00001111表示8位位寬的二進(jìn)制整數(shù),4’ha表示4位位寬的十六進(jìn)制整數(shù)。

X和Z:X代表不定值,z代表高阻值,例如,5’b00x11,第三位不定值,3’b00z表示最低位為高阻值。

下劃線:在位數(shù)過長時可以用來分割位數(shù),提高程序可讀性,如8’b0000_1111

參數(shù)parameter: parameter可以用標(biāo)識符定義常量,運(yùn)用時只使用標(biāo)識符即可,提高可讀性及維護(hù)性,如定義parameter width = 8 ; 定義寄存器reg [width-1:0] a; 即定義了8位寬度的寄存器。

參數(shù)的傳遞:在一個模塊中如果有定義參數(shù),在其他模塊調(diào)用此模塊時可以傳遞參數(shù),并可以修改參數(shù),如下所示,在module后用#()表示。

例如定義模塊如下調(diào)用模塊

modulerom#(parameterdepth=15,parameterwidth=8)(input[depth-1:0]addr,input[width-1:0]data,outputresult);endmodulemoduletop();wire[31:0]addr;wire[15:0]data;wireresult;rom#(.depth(32),.width(16))r1(.addr(addr),.data(data),.result(result));endmodule

Parameter可以用于模塊間的參數(shù)傳遞,而localparam僅用于本模塊內(nèi)使用,不能用于參數(shù)傳遞。Localparam多用于狀態(tài)機(jī)狀態(tài)的定義。

變量

變量是指程序運(yùn)行時可以改變其值的量,下面主要介紹幾個常用了變量類型

1.Wire 型

Wire 類型變量,也叫網(wǎng)絡(luò)類型變量,用于結(jié)構(gòu)實(shí)體之間的物理連接,如門與門之間,不能儲存值,用連續(xù)賦值語句assign賦值,定義為wire [n-1:0] a ; 其中n代表位寬,如定義wire a ; assign a = b ; 是將b的結(jié)點(diǎn)連接到連線a上。如下圖所示,兩個實(shí)體之間的連線即是wire類型變量。

pIYBAGAJEDOATu7AAAAdYMTnkac433.jpg

2.Reg 型

Reg 類型變量,也稱為寄存器變量,可用來儲存值,必須在always語句里使用。其定義為

reg [n-1:0] a ; 表示n位位寬的寄存器,如reg [7:0] a; 表示定義8位位寬的寄存器a。如下所示定義了寄存器q,生成的電路為時序邏輯,右圖為其結(jié)構(gòu),為D觸發(fā)器。

moduletop(d,clk,q);inputd;inputclk;outputregq;always@(posedgeclk)begin
q<=?d?;endendmodule

o4YBAGAJEDSAN2RJAAAiJabSDIs653.jpg

也可以生成組合邏輯,如數(shù)據(jù)選擇器,敏感信號沒有時鐘,定義了reg Mux,最終生成電路為組合邏輯。

moduletop(a,b,c,d,sel,Mux);inputa;inputb;inputc;inputd;input[1:0]sel;outputregMux;always@(seloraorborcord)begincase(sel)2'b00:Mux=a;2'b01:Mux=b;2'b10:Mux=c;2'b11:Mux=d;endcaseendendmodule

pIYBAGAJEDWAVb_bAAAlhI0kTfs738.jpg

3.Memory型

可以用memory類型來定義RAM,ROM等存儲器,其結(jié)構(gòu)為reg [n-1:0] 存儲器名[m-1:0],意義為m個n位寬度的寄存器。例如,reg [7:0] ram [255:0]表示定義了256個8位寄存器,256也即是存儲器的深度,8為數(shù)據(jù)寬度。

運(yùn)算符

運(yùn)算符可分為以下幾類:

  1. 算術(shù)運(yùn)算符(+,-,*,/,%)

  2. 賦值運(yùn)算符(=,<=)

  3. 關(guān)系運(yùn)算符(>,<,>=,<=,==,!=)

  4. 邏輯運(yùn)算符(&&,||,!)

  5. 條件運(yùn)算符(?:)

  6. 位運(yùn)算符(~,|,^,&,^~)

  7. 移位運(yùn)算符(<<,>>)

  8. 拼接運(yùn)算符({ })

算術(shù)運(yùn)算符

“+”(加法運(yùn)算符),”-“(減法運(yùn)算符),”*”(乘法運(yùn)算符),”/”(除法運(yùn)算符,如7/3 =2),“%”(取模運(yùn)算符,也即求余數(shù),如7%3=1,余數(shù)為1)

賦值運(yùn)算符

“=”阻塞賦值,”<=”非阻塞賦值。阻塞賦值為執(zhí)行完一條賦值語句,再執(zhí)行下一條,可理解為順序執(zhí)行,而且賦值是立即執(zhí)行;非阻塞賦值可理解為并行執(zhí)行,不考慮順序,在always塊語句執(zhí)行完成后,才進(jìn)行賦值。如下面的阻塞賦值:

代碼如下:激勵文件如下

moduletop(din,a,b,c,clk);inputdin;inputclk;outputrega,b,c;always@(posedgeclk)begin
a=din;
b=a;
c=b;endendmodule	`timescale1ns/1nsmoduletop_tb();regdin;regclk;wirea,b,c;initialbegin
din=0;
clk=0;foreverbegin#({$random}%100)
din=~din;endendalways#10clk=~clk;topt0(.din(din),.a(a),.b(b),.c(c),.clk(clk));endmodule

可以從仿真結(jié)果看到,在clk的上升沿,a的值等于din,并立即賦給b,b的值賦給c。

o4YBAGAJEDWAa1ZxAAAvAwbJUv4629.jpg

如果改為非阻塞賦值,仿真結(jié)果如下,在clk上升沿,a的值沒有立即賦值給b,b為a原來的值,同樣,c為b原來的值

pIYBAGAJEDeAOA1AAAAwQed_xzw608.jpg

可以從兩者的RTL圖看出明顯不同:

o4YBAGAJEDeATqasAAAnWbFsG_Y582.jpgpIYBAGAJEDiAS-4gAAAuAZGKuRM445.jpg

阻塞賦值RTL圖非阻塞賦值RTL圖

一般情況下,在時序邏輯電路中使用非阻塞賦值,可避免仿真時出現(xiàn)競爭冒險現(xiàn)象;在組合邏輯中使用阻塞賦值,執(zhí)行賦值語句后立即改變;在assign語句中必須用阻塞賦值。

  • 關(guān)系運(yùn)算符

用于表示兩個操作數(shù)之間的關(guān)系,如a>b,a

If (a>=b) q <=1’b1 ;
else q <= 1’b0 ;表示如果a的值大于等于b的值,則q的值為1,否則q的值為0
  • 邏輯運(yùn)算符

“&&”(兩個操作數(shù)邏輯與),”||”(兩個操作數(shù)邏輯或),”!”(單個操作數(shù)邏輯非)例如:

If (a>b && c b并且c

  • 條件運(yùn)算符

“?:”為條件判斷,類似于if else,例如assign a = (i>8)?1’b1:1’b0 ;判斷i的值是否大于8,如果大于8則a的值為1,否則為0。

  • 位運(yùn)算符

“~”按位取反,”|”按位或,”^”按位異或,”&”按位與,”^”按位同或,除了”~”只需要一個操作數(shù)外,其他幾個都需要兩個操作數(shù),如a&b,a|b。具體應(yīng)用在后面的組合邏輯一節(jié)中有講解。

  • 移位運(yùn)算符

“<<”左移位運(yùn)算符,”>>”右移位運(yùn)算符,如a<<1表示,向左移1位,a>>2,向右移兩位。

  • 拼接運(yùn)算符

“{ }”拼接運(yùn)算符,將多個信號按位拼接,如{a[3:0], b[1:0]},將a的低4位,b的低2位拼接成6位數(shù)據(jù)。另外,{n{a[3:0]}}表示將n個a[3:0]拼接,{n{1’b0}}表示n位的0拼接。如{8{1’b0}}表示為8’b0000_0000.

  • 優(yōu)先級別

各種運(yùn)算符的優(yōu)先級別如下:

o4YBAGAJEDmAU0jwAAAqr45e88k829.jpg

組合邏輯

本節(jié)主要介紹組合邏輯,組合邏輯電路的特點(diǎn)是任意時刻的輸出僅僅取決于輸入信號,輸入信號變化,輸出立即變化,不依賴于時鐘。

  • 與門

在verilog中以“&”表示按位與,如c=a&b,真值表如下,在a和b都等于1時結(jié)果才為1,RTL表示如右圖

pIYBAGAJEDmAPO-kAAAOeXTjVtw603.jpgo4YBAGAJEDmAURKGAAAIZ9G2Azc508.jpg

代碼實(shí)現(xiàn)如下:激勵文件如下:

moduletop(a,b,c);inputa;inputb;outputc;assignc=a&b;endmodule`timescale1ns/1nsmoduletop_tb();rega;regb;wirec;initialbegin
a=0;
b=0;foreverbegin#({$random}%100)
a=~a;#({$random}%100)
b=~b;endendtopt0(.a(a),.b(b),.c(c));endmodule

仿真結(jié)果如下:

pIYBAGAJEDqAVXF_AAAT-T7c21U747.jpg

如果a和b的位寬大于1,例如定義input [3:0] a, input [3:0]b,那么a&b則指a與b的對應(yīng)位相與。如a[0]&b[0],a[1]&b[1]。

  • 或門

在verilog中以“|”表示按位或,如c = a|b , 真值表如下,在a和b都為0時結(jié)果才為0。

o4YBAGAJEDqAPZDDAAAT4HoxqU8739.jpgpIYBAGAJEDuAWzpEAAA02MNKmUQ996.jpg

代碼實(shí)現(xiàn)如下:激勵文件如下

moduletop(a,b,c);inputa;inputb;outputc;assignc=a|b;endmodule	`timescale1ns/1nsmoduletop_tb();rega;regb;wirec;initialbegin
a=0;
b=0;foreverbegin#({$random}%100)
a=~a;#({$random}%100)
b=~b;endendtopt0(.a(a),.b(b),.c(c));endmodule

仿真結(jié)果如下:

o4YBAGAJEDuAOMLaAAAUcqxF15A463.jpg

同理,位寬大于1,則是按位或。

  • 非門

在verilog中以“~”表示按位取反,如b=~a,真值表如下,b等于a的相反數(shù)。

pIYBAGAJEDuAfm9FAAAJggh4wQI042.jpgo4YBAGAJEDyAc7c6AAAxmdfXPB8792.jpg

代碼實(shí)現(xiàn)如下:激勵文件如下:

moduletop(a,b);inputa;outputb;assignb=~a;endmodule	`timescale1ns/1nsmoduletop_tb();rega;wireb;initialbegin
a=0;foreverbegin#({$random}%100)
a=~a;endendtopt0(.a(a),.b(b));endmodule

仿真結(jié)果如如下:

pIYBAGAJEDyACfvZAAATRyvB80U398.jpg

  • 異或

在verilog中以“^”表示異或,如c= a^b ,真值表如下,當(dāng)a和b相同時,輸出為0。

o4YBAGAJED2AETY7AAAKk1iBfZg853.jpgpIYBAGAJED2AQtpaAAAp9KXhXz8610.jpg

代碼實(shí)現(xiàn)如下:激勵文件如下:

moduletop(a,b,c);inputa;inputb;outputc;assignc=a^b;endmodule
	`timescale1ns/1nsmoduletop_tb();rega;regb;wirec;initialbegin
a=0;
b=0;foreverbegin#({$random}%100)
a=~a;#({$random}%100)
b=~b;endendtopt0(.a(a),.b(b),.c(c));endmodule

仿真結(jié)果如下:

o4YBAGAJED6AbQ__AAApgT1Q7x0905.jpg

在verilog中以大于“>”,等于”==”,小于”<”,大于等于”>=”,小于等于”<=”,不等于”!=”表示,以大于舉例,如c= a > b ;表示如果a大于b,那么c的值就為1,否則為0。真值表如下:

pIYBAGAJED6ACZadAAAKj3MoyNk511.jpgo4YBAGAJED-AGNh0AAAkkGvBjfU666.jpg

代碼實(shí)現(xiàn)如下:激勵文件如下:

moduletop(a,b,c);inputa;inputb;outputc;assignc=a>b;endmodule	`timescale1ns/1nsmoduletop_tb();rega;regb;wirec;initialbegin
a=0;
b=0;foreverbegin#({$random}%100)
a=~a;#({$random}%100)
b=~b;endendtopt0(.a(a),.b(b),.c(c));endmodule

仿真結(jié)果如下:

pIYBAGAJEECADiHvAAApldnbsqA845.jpg

  • 半加器

半加器和全加器是算術(shù)運(yùn)算電路中的基本單元,由于半加器不考慮從低位來的進(jìn)位,所以稱之為半加器,sum表示相加結(jié)果,count表示進(jìn)位,真值表可表示如下:

o4YBAGAJEECAYvXLAAALco5i8MI203.jpgpIYBAGAJEECANVDbAAAUmzcCxKw784.jpg

可根據(jù)真值表寫出代碼如下:激勵文件如下:

moduletop(a,b,sum,count);inputa;inputb;outputsum;outputcount;assignsum=a^b;assigncount=a&b;endmodule	`timescale1ns/1nsmoduletop_tb();rega;regb;wiresum;wirecount;initialbegin
a=0;
b=0;foreverbegin#({$random}%100)
a=~a;#({$random}%100)
b=~b;endendtopt0(.a(a),.b(b),.sum(sum),.count(count));endmodule

仿真結(jié)果如下:

o4YBAGAJEEGAFtQuAAAsKY8uAcI047.jpg

  • 全加器

而全加器需要加上低位來的進(jìn)位信號cin,真值表如下:

pIYBAGAJEEGAIHJBAAANPVl-XAc692.jpgo4YBAGAJEEGAesNWAAAW0hLAwRY181.jpg

代碼如下:激勵文件如下:

moduletop(cin,a,b,sum,count);inputcin;inputa;inputb;outputsum;outputcount;assign{count,sum}=a+b+cin;endmodule	`timescale1ns/1nsmoduletop_tb();rega;regb;regcin;wiresum;wirecount;initialbegin
a=0;
b=0;
cin=0;foreverbegin#({$random}%100)
a=~a;#({$random}%100)b=~b;#({$random}%100)
cin=~cin;endendtopt0(.cin(cin),.a(a),.b(b),.sum(sum),.count(count));endmodule

仿真結(jié)果如下:

pIYBAGAJEEKAbaFvAAAWdbVI6MM917.jpg

  • 乘法器

乘法的表示也很簡單,利用”*”即可,如a*b,舉例代碼如下:

moduletop(a,b,c);input[1:0]a;input[1:0]b;output[3:0]c;assignc=a*b;endmodule	`timescale1ns/1nsmoduletop_tb();reg[1:0]a;reg[1:0]b;wire[3:0]c;initialbegin
a=0;
b=0;foreverbegin#({$random}%100)
a=~a;#({$random}%100)
b=~b;endendtopt0(.a(a),.b(b),.c(c));
	endmodule

仿真結(jié)果如下:

o4YBAGAJEEKATa6DAAATtpUX-o8500.jpg

  • 數(shù)據(jù)選擇器

在verilog中經(jīng)常會用到數(shù)據(jù)選擇器,通過選擇信號,選擇不同的輸入信號輸出到輸出端,如下圖真值表,四選一數(shù)據(jù)選擇器,sel[1:0]為選擇信號,a,b,c,d為輸入信號,Mux為輸出信號。

pIYBAGAJEEOAGr2HAAAN3odP1aw798.jpgo4YBAGAJEESAQR_DAAAycQ6wPhY618.jpg

代碼如下:激勵文件如下:

moduletop(a,b,c,d,sel,Mux);inputa;inputb;inputc;inputd;input[1:0]sel;outputregMux;always@(seloraorborcord)begincase(sel)2'b00:Mux=a;2'b01:Mux=b;2'b10:Mux=c;2'b11:Mux=d;endcaseendendmodule`timescale1ns/1nsmoduletop_tb();rega;regb;regc;regd;reg[1:0]sel;wireMux;initialbegin
a=0;
b=0;
c=0;
d=0;foreverbegin#({$random}%100)
a={$random}%3;#({$random}%100)
b={$random}%3;#({$random}%100)
c={$random}%3;#({$random}%100)
d={$random}%3;endendinitialbegin
sel=2'b00;#2000sel=2'b01;#2000sel=2'b10;#2000sel=2'b11;endtopt0(.a(a),.b(b),.c(c),.d(d),.sel(sel),.Mux(Mux));endmodule

仿真結(jié)果如下

pIYBAGAJEESAK-BQAAAbdAs15ew895.jpg

  • 3-8譯碼器

3-8譯碼器是一個很常用的器件,其真值表如下所示,根據(jù)A2,A1,A0的值,得出不同的結(jié)果。

o4YBAGAJEESAIlN4AAAVDKpH5fE429.jpg

pIYBAGAJEEWAa8WlAAAjRZ19Dko919.jpg

代碼如下:激勵文件如下:

moduletop(addr,decoder);input[2:0]addr;outputreg[7:0]decoder;always@(addr)begincase(addr)3'b000:decoder=8'b1111_1110;3'b001:decoder=8'b1111_1101;3'b010:decoder=8'b1111_1011;3'b011:decoder=8'b1111_0111;3'b100:decoder=8'b1110_1111;3'b101:decoder=8'b1101_1111;3'b110:decoder=8'b1011_1111;3'b111:decoder=8'b0111_1111;endcaseendendmodule
	`timescale1ns/1nsmoduletop_tb();reg[2:0]addr;wire[7:0]decoder;initialbegin
addr=3'b000;#2000addr=3'b001;#2000addr=3'b010;#2000addr=3'b011;#2000addr=3'b100;#2000addr=3'b101;#2000addr=3'b110;#2000addr=3'b111;endtopt0(.addr(addr),.decoder(decoder));endmodule

仿真結(jié)果如下:

o4YBAGAJEEWAKpkMAAApBhsiw8w051.jpg

  • 三態(tài)門

在FPGA使用中,經(jīng)常會用到雙向IO,需要用到三態(tài)門,如bio = en? din: 1’bz ;其中en為使能信號,用于打開關(guān)閉三態(tài)門,下面的RTL圖即是實(shí)現(xiàn)了雙向IO,可參考代碼。激勵文件實(shí)現(xiàn)兩個雙向IO的對接。

pIYBAGAJEEaAamNpAAARtuEcVo8429.jpg

moduletop(en,din,dout,bio);inputdin;inputen;outputdout;inoutbio;assignbio=en?din:1'bz;assigndout=bio;endmodule`timescale1ns/1nsmoduletop_tb();regen0;regdin0;wiredout0;regen1;regdin1;wiredout1;wirebio;initialbegin
din0=0;
din1=0;foreverbegin#({$random}%100)
din0=~din0;#({$random}%100)din1=~din1;endendinitialbegin
en0=0;
en1=1;#100000
en0=1;
en1=0;endtopt0(.en(en0),.din(din0),.dout(dout0),.bio(bio));topt1(.en(en1),.din(din1),.dout(dout1),.bio(bio));endmodule

激勵文件結(jié)構(gòu)如下圖

o4YBAGAJEEaAGvvbAAAfwFq-shM522.jpg

仿真結(jié)果如下,en0為0,en1為1時,1通道打開,雙向IO bio就等于1通道的din1,1通道向外發(fā)送數(shù)據(jù),0通道接收數(shù)據(jù),dout0等于bio;當(dāng)en0為1,en1為0時,0通道打開,雙向IO bio就等于0通道的din0,0通道向外發(fā)送數(shù)據(jù),1通道接收數(shù)據(jù),dout1等于bio

pIYBAGAJEEeAbl5tAAAdyT7pu00011.jpg

時序邏輯

組合邏輯電路在邏輯功能上特點(diǎn)是任意時刻的輸出僅僅取決于當(dāng)前時刻的輸入,與電路原來的狀態(tài)無關(guān)。而時序邏輯在邏輯功能上的特點(diǎn)是任意時刻的輸出不僅僅取決于當(dāng)前的輸入信號,而且還取決于電路原來的狀態(tài)。下面以典型的時序邏輯分析。

  • D觸發(fā)器

D觸發(fā)器在時鐘的上升沿或下降沿存儲數(shù)據(jù),輸出與時鐘跳變之前輸入信號的狀態(tài)相同。

代碼如下激勵文件如下

moduletop(d,clk,q);inputd;inputclk;outputregq;always@(posedgeclk)begin
q<=?d?;endendmodule






	`timescale1?ns/1?ns?module?top_tb();reg?d?;reg?clk?;wire?q?;initialbegin
??d?=0;
??clk?=0;foreverbegin#({$random}%100)
????d?=~d?;endendalways#10?clk?=~clk?;top??t0(.d(d),.clk(clk),.q(q));endmodule

RTL圖表示如下

o4YBAGAJEEeAOZRZAAAi8easSgk727.jpg

仿真結(jié)果如下,可以看到在t0時刻時,d的值為0,則q的值也為0;在t1時刻d發(fā)生了變化,值為1,那么q相應(yīng)也發(fā)生了變化,值變?yōu)???梢钥吹皆趖0-t1之間的一個時鐘周期內(nèi),無論輸入信號d的值如何變化,q的值是保持不變的,也就是有存儲的功能,保存的值為在時鐘的跳變沿時d的值。

pIYBAGAJEEiANblIAAAVauy8dRg071.jpg

  • 兩級D觸發(fā)器

軟件是按照兩級D觸發(fā)器的模型進(jìn)行時序分析的,具體可以分析在同一時刻兩個D觸發(fā)器輸出的數(shù)據(jù)有何不同,其RTL圖如下:

o4YBAGAJEEiAG2O8AAA1koNR9Vo348.jpg

代碼如下:激勵文件如下:

moduletop(d,clk,q,q1);inputd;inputclk;outputregq;outputregq1;always@(posedgeclk)begin
q<=?d?;endalways@(posedge?clk)begin
??q1?<=?q?;endendmodule`timescale1?ns/1?ns?module?top_tb();reg?d?;reg?clk?;wire?q?;wire?q1?;initialbegin
??d?=0;
??clk?=0;foreverbegin#({$random}%100)
????d?=~d?;endendalways#10?clk?=~clk?;top??t0(.d(d),.clk(clk),.q(q),.q1(q1));endmodule

仿真結(jié)果如下,可以看到t0時刻,d為0,q輸出為0,t1時刻,q隨著d的數(shù)據(jù)變化而變化,而此時鐘跳變之前q的值仍為0,那么q1的值仍為0,t2時刻,時鐘跳變前q的值為1,則q1的值相應(yīng)為1,q1相對于q落后一個周期。

pIYBAGAJEEmAfINnAAAVqQDEpPI864.jpg

  • 帶異步復(fù)位的D觸發(fā)器

異步復(fù)位是指獨(dú)立于時鐘,一旦異步復(fù)位信號有效,就觸發(fā)復(fù)位操作。這個功能在寫代碼時會經(jīng)常用到,用于給信號復(fù)位,初始化。其RTL圖如下:

o4YBAGAJEEmAS_j7AABQ4ZNWkQo576.jpg

代碼如下,注意要把異步復(fù)位信號放在敏感列表里,如果是低電平復(fù)位,即為negedge,如果是高電平復(fù)位,則是posedge

moduletop(d,rst,clk,q);inputd;inputrst;inputclk;outputregq;always@(posedgeclkornegedgerst)beginif(rst==1'b0)
q<=0;else
????q?<=?d?;endendmodule`timescale1?ns/1?ns?module?top_tb();reg?d?;reg?rst?;reg?clk?;wire?q?;initialbegin
??d?=0;
??clk?=0;foreverbegin#({$random}%100)
????d?=~d?;endendinitialbegin
??rst?=0;#200?rst?=1;endalways#10?clk?=~clk?;top??t0(.d(d),.rst(rst),.clk(clk),.q(q));endmodule

仿真結(jié)果如下,可以看到在復(fù)位信號之前,雖然輸入信號d數(shù)據(jù)有變化,但由于正處于復(fù)位狀態(tài),輸入信號q始終為0,在復(fù)位之后q的值就正常了。

pIYBAGAJEEqAGFVjAAApVGy8vj0512.jpg

  • 帶異步復(fù)位同步清零的D觸發(fā)器

前面講到異步復(fù)位獨(dú)立于時鐘操作,而同步清零則是同步于時鐘信號下操作的,當(dāng)然也不僅限于同步清零,也可以是其他的同步操作,其RTL圖如下:

o4YBAGAJEEqAYwBvAAAzKIal4ks813.jpg

代碼如下,不同于異步復(fù)位,同步操作不能把信號放到敏感列表里

moduletop(d,rst,clr,clk,q);inputd;inputrst;inputclr;inputclk;outputregq;always@(posedgeclkornegedgerst)beginif(rst==1'b0)
q<=0;elseif(clr?==1'b1)
????q?<=0;else
????q?<=?d?;endendmodule`timescale1?ns/1?ns?module?top_tb();reg?d?;reg?rst?;reg?clr?;reg?clk?;wire?q?;initialbegin
??d?=0;
??clk?=0;foreverbegin#({$random}%100)
????d?=~d?;endendinitialbegin
??rst?=0;
??clr?=0;#200?rst?=1;#200?clr?=1;#100?clr?=0;endalways#10?clk?=~clk?;top??t0(.d(d),.rst(rst),.clr(clr),.clk(clk),.q(q));endmodule

仿真結(jié)果如下,可以看到clr信號拉高后,q沒有立即清零,而是在下個clk上升沿之后執(zhí)行清零操作,也就是clr同步于clk。

pIYBAGAJEEuAe5q3AAAYHIA2jn4631.jpg

  • 移位寄存器

移位寄存器是指在每個時鐘脈沖來時,向左或向右移動一位,由于D觸發(fā)器的特性,數(shù)據(jù)輸出同步于時鐘邊沿,其結(jié)構(gòu)如下,每個時鐘來臨,每個D觸發(fā)器的輸出q等于前一個D觸發(fā)器輸出的值,從而實(shí)現(xiàn)移位的功能。

o4YBAGAJEEuASuO5AAAjsGcOS2c111.jpg

代碼實(shí)現(xiàn):

moduletop(d,rst,clk,q);inputd;inputrst;inputclk;outputreg[7:0]q;always@(posedgeclkornegedgerst)beginif(rst==1'b0)
q<=0;else
????q?<={q[6:0],?d};//向左移位//q?<=?{d,?q[7:1]}?;??//向右移位endendmodule激勵文件:`timescale1?ns/1?ns?module?top_tb();reg?d?;reg?rst?;reg?clk?;wire[7:0]?q?;initialbegin
??d?=0;
??clk?=0;foreverbegin#({$random}%100)
????d?=~d?;endendinitialbegin
??rst?=0;#200?rst?=1;endalways#10?clk?=~clk?;top?t0(.d(d),.rst(rst),.clk(clk),.q(q));endmodule

仿真結(jié)果如下,可以看到復(fù)位之后,每個clk上升沿左移一位

pIYBAGAJEEyAMX5GAAAWn6PT2Fo115.jpg

  • 單口RAM

單口RAM的寫地址與讀地址共用一個地址,代碼如下,其中reg [7:0] ram [63:0]意思是定義了64個8位寬度的數(shù)據(jù)。其中定義了addr_reg,可以保持住讀地址,延遲一周期之后將數(shù)據(jù)送出。

moduletop(input[7:0]data,input[5:0]addr,inputwr,inputclk,output[7:0]q);reg[7:0]ram[63:0];//declareram
reg[5:0]addr_reg;//addrregister
always@(posedgeclk)beginif(wr)//write
ram[addr]<=?data;
	
??addr_reg?<=?addr;endassign?q?=?ram[addr_reg];//read?data?
endmodule	`timescale1?ns/1?ns?module?top_tb();reg[7:0]?data?;reg[5:0]?addr?;reg?wr?;reg?clk?;wire[7:0]?q?;initialbegin
??data?=0;
??addr?=0;
??wr?=1;
??clk?=0;endalways#10?clk?=~clk?;always@(posedge?clk)begin
??data?<=?data?+1'b1;
??addr?<=?addr?+1'b1;endtop??t0(.data(data),.addr(addr),.clk(clk),.wr(wr),.q(q));endmodule

仿真結(jié)果如下,可以看到q的輸出與寫入的數(shù)據(jù)一致

o4YBAGAJEE2AUn-MAAAf2bQ6veM253.jpg

  • 偽雙口RAM

偽雙口RAM的讀寫地址是獨(dú)立的,可以隨機(jī)選擇寫或讀地址,同時進(jìn)行讀寫操作。代碼如下,在激勵文件中定義了en信號,在其有效時發(fā)送讀地址。

moduletop(input[7:0]data,input[5:0]write_addr,input[5:0]read_addr,inputwr,inputrd,inputclk,outputreg[7:0]q);reg[7:0]ram[63:0];//declareram
reg[5:0]addr_reg;//addrregister
always@(posedgeclk)beginif(wr)//write
ram[write_addr]<=?data;if(rd)//read?
?????q?<=?ram[read_addr];endendmodule`timescale1?ns/1?ns?module?top_tb();reg[7:0]?data?;reg[5:0]?write_addr?;reg[5:0]?read_addr?;reg?wr?;reg?clk?;reg?rd?;wire[7:0]?q?;initialbegin
??data?=0;
??write_addr?=0;
??read_addr?=0;
??wr?=0;
??rd?=0;
??clk?=0;#100?wr?=1;#20?rd?=1;endalways#10?clk?=~clk?;always@(posedge?clk)beginif(wr)begin
?????data?<=?data?+1'b1;
?????write_addr?<=?write_addr?+1'b1;if(rd)
???????read_addr?<=?read_addr?+1'b1;endendtop??t0(.data(data),.write_addr(write_addr),.read_addr(read_addr),.clk(clk),.wr(wr),.rd(rd),.q(q));endmodule

仿真結(jié)果如下,可以看到在rd有效時,對讀地址進(jìn)行操作,讀出數(shù)據(jù)

pIYBAGAJEE2Af1XbAAAiVsGdQpc975.jpg

  • 真雙口RAM

真雙口RAM有兩套控制線,數(shù)據(jù)線,允許兩個系統(tǒng)對其進(jìn)行讀寫操作,代碼如下:

moduletop(input[7:0]data_a,data_b,input[5:0]addr_a,addr_b,inputwr_a,wr_b,inputrd_a,rd_b,inputclk,outputreg[7:0]q_a,q_b);reg[7:0]ram[63:0];//declareram
//PortA
always@(posedgeclk)beginif(wr_a)//write
begin
ram[addr_a]<=?data_a;
?????q_a?<=?data_a?;end
	if(rd_a)//read?
?????q_a?<=?ram[addr_a];end//Port?B?
always@(posedge?clk)beginif(wr_b)//write?
begin
?????ram[addr_b]<=?data_b;
?????q_b?<=?data_b?;endif(rd_b)//read?
?????q_b?<=?ram[addr_b];endendmodule	`timescale1?ns/1?ns?module?top_tb();reg[7:0]?data_a,?data_b?;reg[5:0]?addr_a,?addr_b?;reg?wr_a,?wr_b?;reg?rd_a,?rd_b?;reg?clk?;wire[7:0]?q_a,?q_b?;initialbegin
??data_a?=0;
??data_b?=0;
??addr_a?=0;
??addr_b?=0;
??wr_a?=0;
??wr_b?=0;
??rd_a?=0;
??rd_b?=0;
??clk?=0;#100?wr_a?=1;#100?rd_b?=1;endalways#10?clk?=~clk?;always@(posedge?clk)beginif(wr_a)begin
????data_a?<=?data_a?+1'b1;
????addr_a?<=?addr_a?+1'b1;endelsebegin
?????data_a?<=0;
?????addr_a?<=0;endendalways@(posedge?clk)beginif(rd_b)begin
?????addr_b?<=?addr_b?+1'b1;endelse?addr_b?<=0;endtop??t0(.data_a(data_a),.data_b(data_b),.addr_a(addr_a),.addr_b(addr_b),.wr_a(wr_a),.wr_b(wr_b),.rd_a(rd_a),.rd_b(rd_b),.clk(clk),.q_a(q_a),.q_b(q_b));endmodule

仿真結(jié)果如下

o4YBAGAJEE6ASLVsAABhlKin5IM104.jpg

  • 單口ROM

ROM是用來存儲數(shù)據(jù)的,可以按照下列代碼形式初始化ROM,但這種方法處理大容量的ROM就比較麻煩,建議用FPGA自帶的ROM IP核實(shí)現(xiàn),并添加初始化文件。

代碼實(shí)現(xiàn)

moduletop(input[3:0]addr,inputclk,outputreg[7:0]q);always@(posedgeclk)begincase(addr)4'd0:q<=8'd15;4'd1:?q?<=8'd24;4'd2:?q?<=8'd100;4'd3:?q?<=8'd78;4'd4:?q?<=8'd98;4'd5:?q?<=8'd105;4'd6:?q?<=8'd86;4'd7:?q?<=8'd254;4'd8:?q?<=8'd76;4'd9:?q?<=8'd35;4'd10:?q?<=8'd120;4'd11:?q?<=8'd85;4'd12:?q?<=8'd37;4'd13:?q?<=8'd19;4'd14:?q?<=8'd22;4'd15:?q?<=8'd67;default:?q?<=8'd0;endcaseendendmodule	`timescale1?ns/1?ns?module?top_tb();reg[3:0]?addr?;reg?clk?;wire[7:0]?q?;initialbegin
??addr?=0;
??clk?=0;endalways#10?clk?=~clk?;always@(posedge?clk)begin
?????addr?<=?addr?+1'b1;endtop??t0(.addr(addr),.clk(clk),.q(q));endmodule

仿真結(jié)果如下

pIYBAGAJEE-AKp8PAAA0Nj7yUAY199.jpg

  • 有限狀態(tài)機(jī)

在verilog里經(jīng)常會用到有限狀態(tài)機(jī),處理相對復(fù)雜的邏輯,設(shè)定好不同的狀態(tài),根據(jù)觸發(fā)條件跳轉(zhuǎn)到對應(yīng)的狀態(tài),在不同的狀態(tài)下做相應(yīng)的處理。有限狀態(tài)機(jī)主要用到always及case語句。下面以一個四狀態(tài)的有限狀態(tài)機(jī)舉例說明。

o4YBAGAJEE-AZtCbAAAPlrXJRbg090.jpg

在程序中設(shè)計了8位的移位寄存器,在Idle狀態(tài)下,判斷shift_start信號是否為高,如果為高,進(jìn)入Start狀態(tài),在Start狀態(tài)延遲100個周期,進(jìn)入Run狀態(tài),進(jìn)行移位處理,如果shift_stop信號有效了,進(jìn)入Stop狀態(tài),在Stop狀態(tài),清零q的值,再跳轉(zhuǎn)到Idle狀態(tài)。

Mealy有限狀態(tài)機(jī),輸出不僅與當(dāng)前狀態(tài)有關(guān),也與輸入信號有關(guān),在RTL中會與輸入信號有連接。

moduletop(inputshift_start,inputshift_stop,inputrst,inputclk,inputd,outputreg[7:0]q);parameterIdle=2'd0;//Idlestate
parameterStart=2'd1;//Startstate
parameterRun=2'd2;//Runstate
parameterStop=2'd3;//Stopstate
reg[1:0]state;//statement
reg[4:0]delay_cnt;//delaycounter
always@(posedgeclkornegedgerst)beginif(!rst)begin
state<=?Idle?;
???delay_cnt?<=0;
???q?<=0;endelsecase(state)
????Idle??:beginif(shift_start)state?<=?Start?;end
????Start?:beginif(delay_cnt?==5'd99)begindelay_cnt?<=0;
?state?<=?Run?;endelsedelay_cnt?<=?delay_cnt?+1'b1;end
????Run???:beginif(shift_stop)state?<=?Stop?;elseq?<={q[6:0],?d};end
????Stop??:begin
??????????????q?<=0;state?<=?Idle?;enddefault:?state?<=?Idle?;endcaseendendmodule

Moore有限狀態(tài)機(jī),輸出只與當(dāng)前狀態(tài)有關(guān),與輸入信號無關(guān),輸入信號只影響狀態(tài)的改變,不影響輸出,比如對delay_cnt和q的處理,只與state狀態(tài)有關(guān)。

moduletop(inputshift_start,inputshift_stop,inputrst,inputclk,inputd,outputreg[7:0]q);parameterIdle=2'd0;//Idlestate
parameterStart=2'd1;//Startstate
parameterRun=2'd2;//Runstate
parameterStop=2'd3;//Stopstate
reg[1:0]current_state;//statement
reg[1:0]next_state;reg[4:0]delay_cnt;//delaycounter
//Firstpart:statementtransition
always@(posedgeclkornegedgerst)beginif(!rst)
current_state<=?Idle?;else
???current_state?<=?next_state?;end//Second?part:?combination?logic,?judge?statement?transition?condition?
always@(*)begincase(current_state)
????Idle??:beginif(shift_start)next_state?<=?Start?;elsenext_state?<=?Idle?;end
????Start?:beginif(delay_cnt?==5'd99)next_state?<=?Run?;else
??????????????????next_state?<=?Start?;end
????Run???:beginif(shift_stop)next_state?<=?Stop?;else
?????????????????next_state?<=?Run?;end
????Stop??:?next_state?<=?Idle?;default:next_state?<=?Idle?;endcaseend//Last?part:?output?data?
always@(posedge?clk?ornegedge?rst)beginif(!rst)
????delay_cnt?<=0;elseif(current_state?==?Start)
????delay_cnt?<=?delay_cnt?+1'b1;else
????delay_cnt?<=0;endalways@(posedge?clk?ornegedge?rst)beginif(!rst)
????q?<=0;elseif(current_state?==?Run)
????q?<={q[6:0],?d};else
????q?<=0;endendmodule

在上面兩個程序中用到了兩種方式的寫法,第一種的Mealy狀態(tài)機(jī),采用了一段式的寫法,只用了一個always語句,所有的狀態(tài)轉(zhuǎn)移,判斷狀態(tài)轉(zhuǎn)移條件,數(shù)據(jù)輸出都在一個always語句里,缺點(diǎn)是如果狀態(tài)太多,會使整段程序顯的冗長。第二個Moore狀態(tài)機(jī),采用了三段式的寫法,狀態(tài)轉(zhuǎn)移用了一個always語句,判斷狀態(tài)轉(zhuǎn)移條件是組合邏輯,采用了一個always語句,數(shù)據(jù)輸出也是單獨(dú)的 always語句,這樣寫起來比較直觀清晰,狀態(tài)很多時也不會顯得繁瑣。

pIYBAGAJEFCAdYMFAABtlCBJh7k434.jpg

Mealy有限狀態(tài)機(jī)RTL圖

o4YBAGAJEFGAILd0AAA0OJFe1kg142.jpg

Moore有限狀態(tài)機(jī)RTL圖

激勵文件如下:

`timescale1ns/1nsmoduletop_tb();regshift_start;regshift_stop;regrst;regclk;regd;wire[7:0]q;initialbegin
rst=0;
clk=0;
d=0;#200rst=1;foreverbegin#({$random}%100)
d=~d;endendinitialbegin
shift_start=0;
shift_stop=0;#300shift_start=1;#1000shift_start=0;
shift_stop=1;#50shift_stop=0;endalways#10clk=~clk;topt0(.shift_start(shift_start),.shift_stop(shift_stop),.rst(rst),.clk(clk),.d(d),.q(q));endmodule

仿真結(jié)果如下:

pIYBAGAJEFGALXE4AABUvPqswiQ691.jpg

總結(jié)

本文檔介紹了組合邏輯以及時序邏輯中常用的模塊,其中有限狀態(tài)機(jī)較為復(fù)雜,但經(jīng)常用到,希望大家能夠深入理解,在代碼中多運(yùn)用,多思考,有利于快速提升水平。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1624

    文章

    21573

    瀏覽量

    600704
  • Verilog
    +關(guān)注

    關(guān)注

    28

    文章

    1339

    瀏覽量

    109881
  • Zynq
    +關(guān)注

    關(guān)注

    9

    文章

    607

    瀏覽量

    47084
  • MPSoC
    +關(guān)注

    關(guān)注

    0

    文章

    195

    瀏覽量

    24215
收藏 人收藏

    評論

    相關(guān)推薦

    用于LiDAR的Zynq UltraScale+ MPSoC系統(tǒng)級模塊

    LiDAR 技術(shù)的 Zynq UltraScale+ MPSoC 適應(yīng)性 Zynq UltraScale+
    的頭像 發(fā)表于 11-05 16:52 ?1w次閱讀
    用于LiDAR的<b class='flag-5'>Zynq</b> <b class='flag-5'>UltraScale+</b> <b class='flag-5'>MPSoC</b>系統(tǒng)級<b class='flag-5'>模塊</b>

    如何利用ZYNQ MPSoC玩DOOM?

    ,在詳細(xì)介紹具體步驟之前,我們先來了解什么是管理程序,以及它們?nèi)绾闻cZynq UltraScale+ MPSoC 上的處理器協(xié)同工作。
    發(fā)表于 10-09 06:21

    如何調(diào)試Zynq UltraScale+ MPSoC VCU DDR控制器

      如何調(diào)試Zynq UltraScale+ MPSoC VCU DDR控制器  Zynq UltraScale+
    發(fā)表于 01-07 16:02

    如何調(diào)試Zynq UltraScale+ MPSoC VCU DDR控制器

    如何調(diào)試 Zynq UltraScale+ MPSoC VCU DDR 控制器?
    發(fā)表于 01-22 06:29

    ZYNQ Ultrascale+ MPSOC FPGA教程

    ZYNQ Ultrascale+ MPSOC FPGA教程
    發(fā)表于 02-02 07:53

    Zynq UltraScale+ MPSoC存儲器接口系統(tǒng)的介紹

    該視頻重點(diǎn)介紹UltraScale +產(chǎn)品系列的第一個成員Zynq?UltraScale+?MPSoC,并展示了使用可編程邏輯中的DDR4
    的頭像 發(fā)表于 11-29 06:36 ?3263次閱讀

    Zynq UltraScale+ MPSoC的發(fā)售消息

    Zynq?UltraScale+?MPSoC,現(xiàn)已開始發(fā)售。視頻向您重點(diǎn)介紹了Xilinx UltraScale +產(chǎn)品組合的第一位成員
    的頭像 發(fā)表于 11-27 06:47 ?3534次閱讀

    米爾科技Zynq UltraScale+ MPSoC技術(shù)參考手冊介紹

    Zynq UltraScale+ MPSoC是Xilinx推出的第二代多處理SoC系統(tǒng),在第一代Zynq-7000的基礎(chǔ)上做了全面升級,在單芯片上融合了功能強(qiáng)大的處理器系統(tǒng)(PS)和用
    的頭像 發(fā)表于 11-18 11:03 ?3069次閱讀
    米爾科技<b class='flag-5'>Zynq</b> <b class='flag-5'>UltraScale+</b> <b class='flag-5'>MPSoC</b>技術(shù)參考手冊<b class='flag-5'>介紹</b>

    ZYNQ Ultrascale+ MPSOC FPGA教程】第三章 Verilog基礎(chǔ)模塊介紹

    本文主要介紹verilog基礎(chǔ)模塊,夯實(shí)基礎(chǔ),對深入學(xué)習(xí)FPGA會有很大幫助。
    發(fā)表于 01-22 10:41 ?5次下載
    【<b class='flag-5'>ZYNQ</b> <b class='flag-5'>Ultrascale+</b> <b class='flag-5'>MPSOC</b> <b class='flag-5'>FPGA</b>教程】<b class='flag-5'>第三章</b> <b class='flag-5'>Verilog</b>基礎(chǔ)<b class='flag-5'>模塊</b><b class='flag-5'>介紹</b>

    如何調(diào)試 Zynq UltraScale+ MPSoC VCU DDR 控制器?

    Zynq UltraScale+ MPSoC VCU DDR 控制器是一款專用 DDR 控制器,只支持在 Zynq UltraScale+
    發(fā)表于 02-23 06:00 ?15次下載
    如何調(diào)試 <b class='flag-5'>Zynq</b> <b class='flag-5'>UltraScale+</b> <b class='flag-5'>MPSoC</b> VCU DDR 控制器?

    米爾電子zynq ultrascale+ mpsoc底板外設(shè)資源清單分享

    米爾電子推出的國內(nèi)首款zynq ultrascale+ mpsoc平臺核心板(及開發(fā)板):MYC-CZU3EG吸引了人工智能、工業(yè)控制、嵌入式視覺、ADAS、算法加速、云計算、有線/無線通信等
    發(fā)表于 01-07 15:20 ?3次下載
    米爾電子<b class='flag-5'>zynq</b> <b class='flag-5'>ultrascale+</b> <b class='flag-5'>mpsoc</b>底板外設(shè)資源清單分享

    ZYNQ Ultrascale+ MPSoC系列FPGA芯片設(shè)計

    基于 Xilinx 公司ZYNQ Ultrascale+ MPSoC系列 FPGA 芯片設(shè)計,應(yīng)用于工廠自動化、機(jī)器視覺、工業(yè)質(zhì)檢等工業(yè)領(lǐng)域
    發(fā)表于 11-02 14:35 ?1529次閱讀

    Zynq UltraScale+ MPSoC中的隔離方法

    電子發(fā)燒友網(wǎng)站提供《Zynq UltraScale+ MPSoC中的隔離方法.pdf》資料免費(fèi)下載
    發(fā)表于 09-13 17:11 ?1次下載
    <b class='flag-5'>Zynq</b> <b class='flag-5'>UltraScale+</b> <b class='flag-5'>MPSoC</b>中的隔離方法

    Zynq UltraScale+ MPSoC的隔離設(shè)計示例

    電子發(fā)燒友網(wǎng)站提供《Zynq UltraScale+ MPSoC的隔離設(shè)計示例.pdf》資料免費(fèi)下載
    發(fā)表于 09-13 11:28 ?3次下載
    <b class='flag-5'>Zynq</b> <b class='flag-5'>UltraScale+</b> <b class='flag-5'>MPSoC</b>的隔離設(shè)計示例

    Zynq UltraScale+ MPSoC驗(yàn)證數(shù)據(jù)手冊

    電子發(fā)燒友網(wǎng)站提供《Zynq UltraScale+ MPSoC驗(yàn)證數(shù)據(jù)手冊.pdf》資料免費(fèi)下載
    發(fā)表于 09-15 10:13 ?0次下載
    <b class='flag-5'>Zynq</b> <b class='flag-5'>UltraScale+</b> <b class='flag-5'>MPSoC</b>驗(yàn)證數(shù)據(jù)手冊