Verilog HDL高級程序設(shè)計(jì)舉例_第1頁
Verilog HDL高級程序設(shè)計(jì)舉例_第2頁
Verilog HDL高級程序設(shè)計(jì)舉例_第3頁
Verilog HDL高級程序設(shè)計(jì)舉例_第4頁
Verilog HDL高級程序設(shè)計(jì)舉例_第5頁
已閱讀5頁,還剩244頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

VerilogHDL高級程序設(shè)計(jì)舉例6.1數(shù)字電路系統(tǒng)設(shè)計(jì)的層次化描述方法

6.2典型電路設(shè)計(jì)

6.3總線控制器設(shè)計(jì)本章小結(jié)

集成電路設(shè)計(jì)中大量采用的是結(jié)構(gòu)性的描述方法,歸納起來主要有兩種:自下而上(Bottom-Up)的設(shè)計(jì)方法與自上而下(Top-Down)的設(shè)計(jì)方法。在實(shí)際運(yùn)用中,可以根據(jù)實(shí)際設(shè)計(jì)的情況選擇這兩種方法相結(jié)合的設(shè)計(jì)方法,即混合設(shè)計(jì)方法。6.1數(shù)字電路系統(tǒng)設(shè)計(jì)的層次化描述方法Top-Down方法主要是從系統(tǒng)設(shè)計(jì)的角度進(jìn)行,系統(tǒng)工程師往往會(huì)在項(xiàng)目的規(guī)劃階段將數(shù)字電路系統(tǒng)進(jìn)行劃分,明確主要單元模塊的功能、時(shí)序和接口參數(shù)等系統(tǒng)方案,這種方法可以有效協(xié)調(diào)ULSI和VLSI芯片設(shè)計(jì)中眾多開發(fā)人員的工作。Bottom-Up方法主要是在實(shí)際系統(tǒng)執(zhí)行過程中,底層設(shè)計(jì)人員提出底層功能模塊的優(yōu)化方案,系統(tǒng)設(shè)計(jì)人員分析這些優(yōu)化對系統(tǒng)的影響,通過調(diào)整系統(tǒng)結(jié)構(gòu),提高芯片整體性能。

1.

Bottom-Up設(shè)計(jì)方法

Bottom-Up設(shè)計(jì)方法是一種傳統(tǒng)的設(shè)計(jì)方法,它要求電路設(shè)計(jì)者將系統(tǒng)進(jìn)行模塊劃分,從底層模塊設(shè)計(jì)開始,運(yùn)用各底層模塊搭建一個(gè)完整的系統(tǒng)。在這種設(shè)計(jì)方法中,首先根據(jù)系統(tǒng)設(shè)計(jì)的要求,定義并建立所需要的葉子模塊,通過模塊連接方式建成較大的模塊,然后把這些比較大的模塊組合成具有一定功能的模塊,最后將這些功能模塊組合,直到完成整個(gè)系統(tǒng)。這就如同搭積木,用小的模塊不斷組合,最后完成系統(tǒng)的設(shè)計(jì)。其設(shè)計(jì)方法示意圖如圖6.1-1所示。圖6.1-1Bottom-Up設(shè)計(jì)方法示意圖一個(gè)典型的Bottom-Up設(shè)計(jì)例子是在第4章中提到的串行加法器的設(shè)計(jì)。一個(gè)4位串行加法器由4個(gè)全加器構(gòu)成,如圖6.1-2所示。全加器是串行加法器的子模塊,而全加器是由基本的邏輯門構(gòu)成的,如圖6.1-3所示,這些基本的邏輯門就是所說的葉子模塊。這個(gè)設(shè)計(jì)中運(yùn)用葉子模塊(基本邏輯門)搭建成子模塊(全加器),再用子模塊搭建成所需要的電路(串行加法器)。

圖6.1-24位串行加法器

圖6.1-3全加器邏輯電路顯然,Bottom-Up設(shè)計(jì)方法沒有明顯的規(guī)律可循,主要依靠設(shè)計(jì)者的實(shí)踐經(jīng)驗(yàn)和熟練的設(shè)計(jì)技巧,用逐步試探的方法最后設(shè)計(jì)出一個(gè)完整的數(shù)字系統(tǒng)。系統(tǒng)的各項(xiàng)性能指標(biāo)只有在系統(tǒng)構(gòu)成后才能分析測試。

Bottom-Up設(shè)計(jì)方法常用于原理圖的設(shè)計(jì)中,相比于其它方法,該方法對于實(shí)現(xiàn)各個(gè)子模塊電路所需的時(shí)間較短。但是該方法仍存在著許多不足之處,例如采用該設(shè)計(jì)方法容易對系統(tǒng)的整體功能把握不足,整個(gè)系統(tǒng)的設(shè)計(jì)周期比較長、效率低、設(shè)計(jì)質(zhì)量難以保證等。因此,這種方法只適用于小規(guī)模電路的設(shè)計(jì)。

2.?Top-Down設(shè)計(jì)方法

隨著電子技術(shù)的快速發(fā)展,傳統(tǒng)的設(shè)計(jì)方法已經(jīng)不能滿足日益增長的系統(tǒng)要求,Top-Down設(shè)計(jì)方法成為數(shù)字系統(tǒng)設(shè)計(jì)的主流設(shè)計(jì)方法。在這種設(shè)計(jì)方法中,首先從系統(tǒng)級入手,把系統(tǒng)劃分為若干個(gè)子功能單元,并編制出相應(yīng)的行為或結(jié)構(gòu)模型;再將這些子功能單元進(jìn)一步進(jìn)行拆分,就這樣不斷地拆分直到整個(gè)系統(tǒng)中各個(gè)模塊的邏輯關(guān)系合理,便于邏輯電路級的設(shè)計(jì)和實(shí)現(xiàn),這種最底層的功能模塊被稱為葉子模塊。其設(shè)計(jì)方法示意圖如圖6.1-4所示。

圖6.1-4Top-Down設(shè)計(jì)方法示意圖例如,使用Top-Down設(shè)計(jì)方法對一個(gè)典型CPU進(jìn)行設(shè)計(jì),如圖6.1-5所示。根據(jù)CPU的功能將CPU分為控制單元、邏輯運(yùn)算單元、存儲(chǔ)單元??刂茊卧饕刂普麄€(gè)CPU的工作,用于調(diào)控整個(gè)CPU按照指令執(zhí)行相應(yīng)的規(guī)定動(dòng)作,控制單元又由指令控制器、時(shí)序控制器、總線控制器和中斷控制器構(gòu)成。邏輯運(yùn)算單元可以分為算術(shù)邏輯運(yùn)算單元ALU和浮點(diǎn)運(yùn)算單元FPU。存儲(chǔ)單元可以分為通用寄存器和專用寄存器。這樣通過功能的不斷細(xì)化,將大模塊劃分成了更小的模塊,當(dāng)劃分到指令控制器這一級時(shí),就可以通過各種邏輯電路來實(shí)現(xiàn)了。

圖6.1-5Top-Down設(shè)計(jì)CPU流程

Top-Down設(shè)計(jì)方法的優(yōu)點(diǎn)是顯而易見的,在整個(gè)設(shè)計(jì)過程中主要的仿真和調(diào)試過程是在高層次完成的,所以能夠在設(shè)計(jì)的早期發(fā)現(xiàn)結(jié)構(gòu)設(shè)計(jì)上的錯(cuò)誤,及時(shí)進(jìn)行調(diào)整,最大限度地不將錯(cuò)誤帶入到后續(xù)的設(shè)計(jì)環(huán)節(jié)中。同時(shí)方便了從系統(tǒng)進(jìn)行劃分和管理整個(gè)項(xiàng)目,使得大規(guī)模的復(fù)雜的數(shù)字電路實(shí)現(xiàn)成為可能,避免了不必要的重復(fù)設(shè)計(jì),提高了設(shè)計(jì)效率。然而這種設(shè)計(jì)方法仍然存在著不足,在設(shè)計(jì)的開始并不能準(zhǔn)確地確定最終功能單元的設(shè)計(jì),需要根據(jù)具體的設(shè)計(jì)情況,不斷進(jìn)行系統(tǒng)設(shè)計(jì)的修正?,F(xiàn)在的數(shù)字電路設(shè)計(jì)越來越復(fù)雜,單一的設(shè)計(jì)方法往往很難滿足設(shè)計(jì)要求,因此通常將這兩種設(shè)計(jì)方法結(jié)合起來,即采用混合的設(shè)計(jì)方法來進(jìn)行設(shè)計(jì)。這樣可以綜合每種方法的優(yōu)點(diǎn),在高層系統(tǒng)設(shè)計(jì)時(shí)采用Top-Down設(shè)計(jì)方法,便于系統(tǒng)的劃分;而在底層的設(shè)計(jì)時(shí)采用Top-Down設(shè)計(jì)方法,這樣可以縮短各個(gè)模塊的設(shè)計(jì)時(shí)間。例6.1-1采用模塊層次化設(shè)計(jì)方法,設(shè)計(jì)4維向量點(diǎn)積乘法器,其中向量a

=

(a1,a2,a3,a44),b

=

(b1,b2,b3,b4)。點(diǎn)積乘法的規(guī)則為

(6.1-1)向量點(diǎn)積乘法是將向量的對應(yīng)位置的值相乘,然后相加。其對應(yīng)電路結(jié)構(gòu)如圖6.1-6所示。

圖6.1-6向量點(diǎn)積乘法器電路結(jié)構(gòu)可以看出,4位點(diǎn)積向量乘法器由4個(gè)乘法器和3個(gè)加法器構(gòu)成,而加法器和乘法器又由半加器和全加器構(gòu)成,其中半加器和全加器又由基本的邏輯門組成,其構(gòu)成關(guān)系如圖6.1-7所示。

圖6.1-7向量點(diǎn)積乘法器層次化功能模塊具體的VerilogHDL設(shè)計(jì)包括頂層模塊vector、加法器模塊add和乘法器模塊mul_addtree。VerilogHDL程序代碼如下:

modulevector(a1,a2,a3,a4,b1,b2,b3,b4,out);

input[3:0]a1,a2,a3,a4,b1,b2,b3,b4;

output[9:0]out;

wire[7:0]out1,out2,out3,out4;

wire[8:0]out5,out6;

wire[9:0]out;

mul_addtreeU1(.x(a1),.y(b1),.out(out1));

mul_addtreeU2(.x(a2),.y(b2),.out(out2));

mul_addtreeU3(.x(a3),.y(b3),.out(out3));

mul_addtreeU4(.x(a4),.y(b4),.out(out4));

add#(8)U5(.a(out1),.b(out2),.out(out5));

add#(8)U6(.a(out3),.b(out4),.out(out6));

add#(9)U7(.a(out5),.b(out6),.out(out));

endmodule

//加法器

moduleadd(a,b,out);

parametersize=8;

input[size-1:0]a,b;

output[size:0]out;

assignout=a+b;

endmodule

//乘法器

modulemul_addtree(mul_a,mul_b,mul_out);

input[3:0]mul_a,mul_b;//IO端口聲明

output[7:0]mul_out;

wire[3:0]mul_out;//連線類型聲明

wire[3:0]stored0,stored1,stored2,stored3;

wire[3:0]add01,add23;

assignstored3=mul_b[3]?{1'b0,mul_a,3'b0}:8'b0;//邏輯設(shè)計(jì)

assignstored2=mul_b[2]?{2'b0,mul_a,2'b0}:8'b0;

assignstored1=mul_b[1]?{3'b0,mul_a,1'b0}:8'b0;

assignstored0=mul_b[0]?{4'b0,mul_a}:8'b0;

assignadd01=stored1+stored0;

assignadd23=stored3+stored2;

assignmul_out=add01+add23;

endmodule

可以看到,在這個(gè)電路設(shè)計(jì)中,vector、add和mul_addtree三個(gè)模塊共同構(gòu)成了向量點(diǎn)積乘法器。頂層模塊vector采用結(jié)構(gòu)描述方式分別使用了4個(gè)mul_addtree和3個(gè)add模塊,分兩層實(shí)現(xiàn)了電路功能。

6.2.1加法器樹乘法器

加法器樹乘法器的設(shè)計(jì)思想是“移位后加”,并且加法運(yùn)算采用加法器樹的形式。乘法運(yùn)算的過程是,被乘數(shù)與乘數(shù)的每一位相乘并且乘以相應(yīng)的權(quán)值,最后將所得的結(jié)果相加,便得到了最終的乘法結(jié)果。6.2典型電路設(shè)計(jì)加法器樹乘法器在計(jì)算被乘數(shù)與乘數(shù)及與其權(quán)值相乘時(shí)采用“判斷移位”的形式,即通過判斷乘數(shù)位是否為1來決定結(jié)果為0或者進(jìn)行移位。當(dāng)乘數(shù)位為1時(shí)被乘數(shù)根據(jù)該位的權(quán)值將被乘數(shù)移位,權(quán)值為0不移位,權(quán)值為2左移1位,權(quán)值為4左移2位,權(quán)值為8左移3位……;當(dāng)乘數(shù)位為0時(shí)直接輸出0。而加法器樹乘法器的加法運(yùn)算是通過加法器樹來實(shí)現(xiàn)的,如圖6.2-1所示。加法器樹所需要的加法器的數(shù)目是操作數(shù)的位數(shù)減1。

圖6.2-14位的加法器樹乘法器結(jié)構(gòu)例6.2-1圖6.2-1是一個(gè)4位的加法器樹乘法器結(jié)構(gòu),用VerilogHDL設(shè)計(jì)一個(gè)4位加法器樹乘法器。

modulemul_addtree(mul_a,mul_b,mul_out);

input[3:0]mul_a,mul_b; //IO端口聲明

output[7:0]mul_out;

wire[7:0]mul_out; //連線類型聲明

wire[7:0]stored0,stored1,stored2,stored3;

wire[7:0]add01,add23;

assignstored3=mul_b[3]?{1'b0,mul_a,3'b0}:8'b0; //邏輯設(shè)計(jì)

assignstored2=mul_b[2]?{2'b0,mul_a,2'b0}:8'b0;

assignstored1=mul_b[1]?{3'b0,mul_a,1'b0}:8'b0;

assignstored0=mul_b[0]?{4'b0,mul_a}:8'b0;

assignadd01=stored1+stored0;

assignadd23=stored3+stored2;

assignmul_out=add01+add23;

endmodule

//****************************測試代碼********************************

modulemult_addtree_tb;

reg[3:0]mult_a;

reg[3:0]mult_b;

wire[7:0]mult_out;

//模塊例化

mul_addtreeU1(.mul_a(mult_a),.mul_b(mult_b),.mul_out(mult_out));

initial//測試信號

begin

mult_a=0;mult_b=0;

repeat(9)

begin

#20mult_a=mult_a+1;

mult_b=mult_b+1;

end

end

endmodule

圖6.2-2加法器樹乘法器測試結(jié)果圖6.2-3兩級流水線4位加法器樹乘法器結(jié)構(gòu)加法器樹乘法器可以通過流水線提高電路速度。其基本思想是加法器樹中插入寄存器,將加法器樹乘法器設(shè)計(jì)成流水線型。

例6.2-2用VerilogHDL設(shè)計(jì)一個(gè)兩級流水線4位加法器樹乘法器。

兩級流水線4位加法器樹乘法器結(jié)構(gòu)如圖6.2-3所示。

通過在第一級與第二級、第二級與第三級加法器之間插入D觸發(fā)器組,可以實(shí)現(xiàn)兩級流水線設(shè)計(jì),其VerilogHDL代碼如下:

modulemul_addtree_2_stage(clk,clr,mul_a,mul_b,mul_out);

inputclk,clr;

input[3:0]mul_a,mul_b; //IO端口聲明

output[7:0]mul_out;

reg[7:0]add_tmp_1,add_tmp_2,mul_out;

wire[7:0]stored0,stored1,stored2,stored3;

assignstored3=mul_b[3]?{1'b0,mul_a,3'b0}:8'b0; //邏輯設(shè)計(jì)

assignstored2=mul_b[2]?{2'b0,mul_a,2'b0}:8'b0;

assignstored1=mul_b[1]?{3'b0,mul_a,1'b0}:8'b0;

assignstored0=mul_b[0]?{4'b0,mul_a}:8'b0;

always@(posedgeclkornegedgeclr) //時(shí)序控制

begin

if(!clr)

begin

add_tmp_1<=8'b0000_0000;

add_tmp_2<=8'b0000_0000;

mul_out<=8'b0000_0000;

end

else

begin

add_tmp_1<=stored3+stored2;

add_tmp_2<=stored1+stored0;

mul_out<=add_tmp_1+add_tmp_2;

end

end

endmodule

應(yīng)該指出,在這個(gè)VerilogHDL代碼中,使用非阻塞賦值方式可以直接實(shí)現(xiàn)寄存器的插入,相關(guān)內(nèi)容參照3.2.3節(jié)。

//****************************測試代碼****************************//

modulemult_addtree_2_stag_tb;

regclk,clr;

reg[3:0]mult_a,mult_b;

wire[7:0]mult_out;

mul_addtree_2_stage U1(.mul_a(mult_a),.mul_b(mult_b),

.mul_out(mult_out),.clk(clk),.clr(clr));

initial

begin

clk=0;clr=0;mult_a=1;mult_b=1;

#5clr=1;

end

always#10clk=~clk;

initial

begin

repeat(5)

begin

#20mult_a=mult_a+1;mult_b=mult_b+1;

end

end

endmodule

測試結(jié)果如圖6.2-4所示。

圖6.2-4兩級流水線4位加法器樹乘法器的測試結(jié)果6.2.2Wallace樹乘法器

在乘法器的設(shè)計(jì)中,采用樹形乘法器可以減少關(guān)鍵路徑和所需的加法器單元數(shù)目。Wallace樹乘法器就是其中一種。下面以一個(gè)4

×

4位的乘法器為例來介紹Wallace樹乘法器。Wallace樹乘法器原理圖如圖6.2-5所示,其中FA為全加器,HA為半加器。其基本原理是,加法從數(shù)據(jù)最密集的地方開始,不斷地反復(fù)使用全加器、半加器來覆蓋“樹”。這一級全加器是一個(gè)3輸入2輸出的器件,因此全加器又稱為3-2壓縮器。通過全加器將樹的深度不斷縮減,最終縮減為一個(gè)深度為2的樹。最后一級則采用一個(gè)簡單的2輸入加法器組成。

圖6.2-5Wallace樹乘法器原理圖

圖6.2-6Wallace樹乘法器電路結(jié)構(gòu)例6.2-3用VerilogHDL設(shè)計(jì)如圖6.2-6所示的4位Wallace樹乘法器。

modulewallace(x,y,out);

parametersize=4; //參數(shù)定義

input[size-1:0]x,y;

output[2*size-1:0]out; //端口聲明

wire[size*size-1:0]a;

wire[1:0]b0,b1,c0,c1,c2,c3; //連線類型聲明

wire[5:0]add_a,add_b;

wire[6:0]add_out;

wire[2*size-1:0]out;

assign

a={x[3],x[3],x[2],x[2],x[1],x[3],x[1],x[0],x[3],

x[2],x[1],x[0],x[2],x[1],x[0],x[0]}&

{y[3],y[2],y[3],y[2],y[3],y[1],y[2]

,y[3],y[0],y[1],y[1],y[2],y[0],y[0],y[1],y[0]};//部分積

haddU1(.x(a[8]),.y(a[9]),.out(b0)); //2輸入半加器

haddU2(.x(a[11]),.y(a[12]),.out(b1));

haddU3(.x(a[4]),.y(a[5]),.out(c0));

faddU4(.x(a[6]),.y(a[7]),.z(b0[0]),.out(c1)); //3輸入全加器

faddU5(.x(a[13]),.y(a[14]),.z(b0[1]),.out(c2));

faddU6(.x(b1[0]),.y(a[10]),.z(b1[1]),.out(c3));

assignadd_a={c3[1],c2[1],c1[1],c0[1],a[3],a[1]}; //加數(shù)

assignadd_b={a[15],c3[0],c2[0],c1[0],c0[0],a[2]};

assignadd_out=add_a+add_b;

assignout={add_out,a[0]};

endmodule

modulefadd(x,y,z,out);

output[1:0]out;

inputx,y,z;

assignout=x+y+z;

endmodule

modulehadd(x,y,out);

output[1:0]out;

inputx,y;

assignout=x+y;

endmodule

//***************************測試代碼*********************//

modulewallace_tb;

reg[3:0]x,y;

wire[7:0]out;

wallacem(.x(x),.y(y),.out(out)); //模塊例化

initial //測試信號

begin

x=3;y=4;

#20x=2;y=3;

#20x=6;y=8;

end

endmodule

測試結(jié)果如圖6.2-7所示。

圖6.2-7Wallace樹乘法器的測試結(jié)果6.2.3復(fù)數(shù)乘法器

復(fù)數(shù)乘法的算法是:設(shè)復(fù)數(shù),則復(fù)數(shù)乘法結(jié)果為

(6.2-1)

復(fù)數(shù)乘法器的電路結(jié)構(gòu)如圖6.2-8所示。將復(fù)數(shù)x的實(shí)部與復(fù)數(shù)y的實(shí)部相乘,減去x的虛部與y的虛部相乘,得到輸出結(jié)果的實(shí)部。將x的實(shí)部與y的虛部相乘,加上x的虛部與y的實(shí)部相乘,得到輸出結(jié)果的虛部。

圖6.2-8復(fù)數(shù)乘法器的電路結(jié)構(gòu)例6.2-4用VerilogHDL設(shè)計(jì)實(shí)部和虛部均為4位二進(jìn)制數(shù)的復(fù)數(shù)乘法器。

modulecomplex(a,b,c,d,out_real,out_im);

input[3:0]a,b,c,d;

output[8:0]out_real,out_im;

wire[7:0]sub1,sub2,add1,add2;

wallace U1(.x(a),.y(c),.out(sub1));

wallace U2(.x(b),.y(d),.out(sub2));

wallace U3(.x(a),.y(d),.out(add1));

wallace U4(.x(b),.y(c),.out(add2));

assign out_real=sub1-sub2;

assign out_im=add1+add2;

endmodule

//***********************測試模塊*********************//

modulecomplex_tb;

reg[3:0]a,b,c,d;

wire[8:0]out_real;

wire[8:0]out_im;

complexU1(.a(a),.b(b),.c(c),.d(d),.out_real(out_real),.out_im(out_im));

initial

begin

a=2; b=2;c=5;d=4;

#10

a=4;b=3;c=2;d=1;

#10

a=3;b=2;c=3;d=4;

end

endmodule

測試結(jié)果如圖6.2-9所示。

圖6.2-9復(fù)數(shù)乘法器的測試結(jié)果6.2.4FIR濾波器的設(shè)計(jì)

濾波器就是對特定的頻率或者特定頻率以外的頻率進(jìn)行消除的電路,被廣泛用于通信系統(tǒng)和信號處理系統(tǒng)中。從功能角度而言,數(shù)字濾波器對輸入離散信號的數(shù)字代碼進(jìn)行運(yùn)算處理,以達(dá)到濾除頻帶外信號的目的。

有限沖激響應(yīng)(FIR)濾波器就是一種常用的數(shù)字濾波器,采用對已輸入樣值的加權(quán)和來形成它的輸出。其系統(tǒng)函數(shù)為

(6.2-2)其中z-1表示延遲一個(gè)時(shí)鐘周期,z-2表示延遲兩個(gè)時(shí)鐘周期。

對于輸入序列X[n]的FIR濾波器,可用圖6.2-10所示的結(jié)構(gòu)示意圖來表示,其中X[n]是輸入數(shù)據(jù)流。各級的輸入連接和輸出連接被稱為抽頭,系數(shù)(b0,b1,…,bn)被稱為抽頭系數(shù)。一個(gè)M階的FIR濾波器將會(huì)有M

+

1個(gè)抽頭。通過移位寄存器用每個(gè)時(shí)鐘邊沿n(時(shí)間下標(biāo))處的數(shù)據(jù)流采樣值乘以抽頭系數(shù),并將它們加起來形成輸出Y[n]。

圖6.2-10FIR濾波器結(jié)構(gòu)示意圖例6.2-5用VerilogHDL設(shè)計(jì)一個(gè)輸入信號位寬為4bit的8階FIR濾波器。

如圖6.2-10所示,F(xiàn)IR濾波器電路有兩個(gè)主要功能模塊:移位寄存器組模塊shift_register用于存儲(chǔ)串行進(jìn)入濾波器的數(shù)據(jù);乘加計(jì)算模塊caculator用于進(jìn)行FIR計(jì)算(見式(6.2-2))。因此,在頂層模塊中采用結(jié)構(gòu)性的描述方式設(shè)計(jì)。

moduleFIR(Data_out,Data_in,clock,reset);

output[9:0]Data_out;

input[3:0]Data_in;

inputclock,reset;

wire[9:0]Data_out;

wire[3:0]samples_0,samples_1,samples_2,samples_3,samples_4,

samples_5,samples_6,samples_7,samples_8;

shift_registerU1(.Data_in(Data_in),.clock(clock),.reset(reset),

.samples_0(samples_0),.samples_1(samples_1),

.samples_2(samples_2),.samples_3(samples_3),

.samples_4(samples_4),.samples_5(samples_5),

.samples_6(samples_6),.samples_7(samples_7),

.samples_8(samples_8));

caculatorU2(.samples_0(samples_0),.samples_1(samples_1),

.samples_2(samples_2),.samples_3(samples_3),

.samples_4(samples_4),.samples_5(samples_5),

.samples_6(samples_6),.samples_7(samples_7),

.samples_8(samples_8),.Data_out(Data_out));

endmodule

shift_register模塊用于存儲(chǔ)輸入的數(shù)據(jù)流,本例中主要負(fù)責(zé)存儲(chǔ)8個(gè)位寬為4bit的輸入數(shù)據(jù)信號,用于caculator模塊的輸入。

moduleshift_register(Data_in,clock,reset,samples_0,samples_1,samples_2,

samples_3,samples_4,samples_5,samples_6,

samples_7,samples_8);

input[3:0]Data_in;

inputclock,reset;

output[3:0]samples_0,samples_1,samples_2,samples_3,samples_4,

samples_5,samples_6,samples_7,samples_8;

reg[3:0]samples_0,samples_1,samples_2,samples_3,samples_4,

samples_5,samples_6,samples_7,samples_8;

always@(posedgeclockornegedgereset)

begin

if(reset)

begin

samples_0<=4'b0;

samples_1<=4'b0;

samples_2<=4'b0;

samples_3<=4'b0;

samples_4<=4'b0;

samples_5<=4'b0;

samples_6<=4'b0;

samples_7<=4'b0;

samples_8<=4'b0;

end

else

begin

samples_0<=Data_in;

samples_1<=samples_0;

samples_2<=samples_1;

samples_3<=samples_2;

samples_4<=samples_3;

samples_5<=samples_4;

samples_6<=samples_5;

samples_7<=samples_6;

samples_8<=samples_7;

end

end

endmodule

caculator模塊用于進(jìn)行8輸入信號與抽頭系數(shù)的乘法和累加,并產(chǎn)生濾波之后的輸出信號Data_out。應(yīng)該指出的是,F(xiàn)IR濾波器系數(shù)具有對稱性,在本例中,b0

=

b8,b1

=

b7,b2

=

b6,b3

=

b5,因此,可以采用先將輸入信號相加再與抽頭系數(shù)相乘的方式,減少乘法器電路的數(shù)量和芯片面積。

modulecaculator(samples_0,samples_1,samples_2,samples_3,samples_4,samples_5,

samples_6,samples_7,samples_8,Data_out);

input[3:0]samples_0,samples_1,samples_2,samples_3,samples_4,samples_5,

samples_6,samples_7,samples_8;

output[9:0]Data_out;

wire[9:0]Data_out;

wire[3:0]out_tmp_1,out_tmp_2,out_tmp_3,out_tmp_4,out_tmp_5;

wire[7:0]out1,out2,out3,out4,out5;

parameterb0=4'b0010;

parameterb1=4'b0011;

parameterb2=4'b0110;

parameterb3=4'b1010;

parameterb4=4'b1100;

mul_addtreeU1(.mul_a(b0),.mul_b(out_tmp_1),.mul_out(out1));

mul_addtreeU2(.mul_a(b1),.mul_b(out_tmp_2),.mul_out(out2));

mul_addtreeU3(.mul_a(b2),.mul_b(out_tmp_3),.mul_out(out3));

mul_addtreeU4(.mul_a(b3),.mul_b(out_tmp_4),.mul_out(out4));

mul_addtreeU5(.mul_a(b4),.mul_b(samples_4),.mul_out(out5));

assignout_tmp_1=samples_0+samples_8;

assignout_tmp_2=samples_1+samples_7;

assignout_tmp_3=samples_2+samples_6;

assignout_tmp_4=samples_3+samples_5;

assignData_out=out1+out2+out3+out4+out5;

endmodule

乘法器模塊mul_addtree的代碼見例6.2-2。

//***********************測試模塊*********************//

moduleFIR_tb;

regclock,reset;

reg[3:0]Data_in;

wire[9:0]Data_out;

FIR U1(.Data_out(Data_out),.Data_in(Data_in),.clock(clock),.reset(reset));

initial

begin

Data_in=0;clock=0;reset=1;

#10reset=0;

end

always

begin

#5clock<=~clock;

#5Data_in<=Data_in+1;

end

endmodule

測試結(jié)果如圖6.2-11所示。

圖6.2-11FIR濾波器的測試結(jié)果圖6.2-12RAM的內(nèi)部結(jié)構(gòu)示意圖6.2.5片內(nèi)存儲(chǔ)器的設(shè)計(jì)

片內(nèi)存儲(chǔ)器分為RAM和ROM兩大類。本節(jié)將分別介紹RAM和ROM的VerilogHDL描述方式。

1.?RAM的VerilogHDL描述

RAM是隨機(jī)存儲(chǔ)器,存儲(chǔ)單元的內(nèi)容可按需隨意取出或存入。這種存儲(chǔ)器在斷電后將丟失所有數(shù)據(jù),因此一般用來存儲(chǔ)一些短時(shí)間內(nèi)使用的程序和數(shù)據(jù)。其內(nèi)部結(jié)構(gòu)如圖6.2-12所示。根據(jù)地址總線、數(shù)據(jù)總線以及讀寫控制線的數(shù)目,可以將RAM分為單端口RAM和雙端口RAM兩大類。

例6.2-6用VerilogHDL設(shè)計(jì)深度為8、位寬為8bit的單端口RAM。

單端口RAM只有一套地址總線,讀操作和寫操作是分開的。其VerilogHDL程序如下:

moduleram_single(clk,addm,cs_n,we_n,din,dout);

input clk; //時(shí)鐘信號

input[2:0] addm; //地址信號

input cs_n; //片選信號

input we_n; //寫使能信號

input[7:0]din; //輸入數(shù)據(jù)

output[7:0]dout; //輸出數(shù)據(jù)

reg[7:0]dout;

reg[7:0]raml[7:0]; //8*8bit寄存器

always@(posedgeclk)

begin

if(cs_n)

dout<=8'bzzzz_zzzz;

else

if(we_n) //讀數(shù)據(jù)

dout<=raml[addm];

else //寫數(shù)據(jù)

raml[addm]<=din;

end

endmodule

//******************************測試程序*******************************

moduleram_single_tb;

regclk,we_n,cs_n;

reg[2:0]addm;

reg[7:0]din;

wire[7:0]dout;

ram_singleU1(.clk(clk),.addm(addm),.cs_n(cs_n),.we_n(we_n),

.din(din),.dout(dout));

initial

begin

clk=0;addm=0;cs_n=1;we_n=0;din=0;

#5cs_n=0;

#315we_n=1;

end

always#10clk=~clk;

initial

begin

repeat(7)

begin

#40addm=addm+1;

din=din+1;

end

#40

repeat(7)

#40addm=addm-1;

end

endmodule

測試結(jié)果如圖6.2-13所示。

圖6.2-13單端口RAM的測試結(jié)果例6.2-7用VerilogHDL設(shè)計(jì)深度為8、位寬為8bit的雙端口RAM。

雙端口RAM具有兩套地址總線,一套用于讀數(shù)據(jù),另一套用于寫數(shù)據(jù)。二者可以分別進(jìn)行操作。其VerilegHDL程序如下:

moduleram_dual(q,addr_in,addr_out,d,we,rd,clk1,clk2);

output[7:0]q; //輸出數(shù)據(jù)

input[7:0]d; //輸入數(shù)據(jù)

input[2:0]addr_in; //寫數(shù)據(jù)地址信號

input[2:0]addr_out; //輸出數(shù)據(jù)地址信號

inputwe; //寫數(shù)據(jù)控制信號

inputrd; //讀數(shù)據(jù)控制信號

inputclk1; //寫數(shù)據(jù)時(shí)鐘信號

inputclk2; //讀數(shù)據(jù)時(shí)鐘信號

reg[7:0]q;

reg[7:0]mem[7:0]; //8*8bit寄存器

always@(posedgeclk1)

begin

if(we)

mem[addr_in]<=d;

end

always@(posedgeclk2)

begin

if(rd)

q<=mem[addr_out];

end

endmodule

//*******************************測試代碼*****************************

moduleram_dual_tb;

regclk1,clk2,we,rd;

reg[2:0]addr_in;

reg[2:0]addr_out;

reg[7:0]d;

wire[7:0]q;

ram_dualU1(.q(q),.addr_in(addr_in),.addr_out(addr_out),.d(d),.we(we),

.rd(rd),.clk1(clk1),.clk2(clk2));

initial

begin

clk1=0;clk2=0;we=1;rd=0;addr_in=0;addr_out=0;d=0;

#320we=0;

rd=1;

end

always

begin

#10clk1=~clk1;clk2=~clk2;

end

initial

begin

repeat(7)

begin

#40addr_in=addr_in+1;d=d+1;

end

#40

repeat(7)#40addr_out=addr_out+1;

end

endmodule

測試結(jié)果如圖6.2-14所示。

圖6.2-14雙端口RAM的測試結(jié)果

2.?ROM的VerilogHDL描述

ROM即只讀存儲(chǔ)器,是一種只能讀出事先存儲(chǔ)的數(shù)據(jù)的存儲(chǔ)器,其特性是存入的數(shù)據(jù)無法改變。也就是說,這種存儲(chǔ)器只能讀不能寫。由于ROM在斷電之后數(shù)據(jù)不會(huì)丟失,所以通常用在不需經(jīng)常變更資料的電子或電腦系統(tǒng)中,資料并不會(huì)因?yàn)殡娫吹年P(guān)閉而消失。

例6.2-8用VerilogHDL設(shè)計(jì)深度為8、位寬為8bit的ROM。

modulerom(dout,clk,addm,cs_n);

inputclk,cs_n;

input[2:0]addm;

output[7:0]dout;

reg[7:0]dout;

reg[7:0]rom[7:0];

initial

begin

rom[0]=8'b0000_0000;

rom[1]=8'b0000_0001;

rom[2]=8'b0000_0010;

rom[3]=8'b0000_0011;

rom[4]=8'b0000_0100;

rom[5]=8'b0000_0101;

rom[6]=8'b0000_0110;

rom[7]=8'b0000_0111;

end

always@(posedgeclk)

begin

if(cs_n) dout<=8'bzzzz_zzzz;

else dout<=rom[addm];

end

endmodule

//*****************************測試代碼***************************

modulerom_tb;

regclk,cs_n;

reg[2:0]addm;

wire[7:0]dout;

romU1(.dout(dout),.clk(clk),.addm(addm),.cs_n(cs_n));

initial

begin

clk=0;addm=0;cs_n=0;

end

always#10clk=~clk;

initial

begin

repeat(7)

#20addm=addm+1;

end

endmodule

測試結(jié)果如圖6.2-15所示。

圖6.2-15ROM的測試結(jié)果6.2.6FIFO設(shè)計(jì)

FIFO(FirstInFirstOut)是一種先進(jìn)先出的數(shù)據(jù)緩存器,通常用于接口電路的數(shù)據(jù)緩存。與普通存儲(chǔ)器的區(qū)別是,沒有外部讀寫地址線,可以使用兩個(gè)時(shí)鐘分別進(jìn)行寫操作和讀操作。FIFO只能順序?qū)懭霐?shù)據(jù)和順序讀出數(shù)據(jù),其數(shù)據(jù)地址由內(nèi)部讀寫指針自動(dòng)加1完成,不能像普通存儲(chǔ)器那樣可以由地址線決定讀取或?qū)懭肽硞€(gè)指定的地址。

FIFO由存儲(chǔ)器塊和對數(shù)據(jù)進(jìn)出FIFO的通道進(jìn)行管理的控制器構(gòu)成,每次只對一個(gè)寄存器提供存取操作,而不是對整個(gè)寄存器陣列進(jìn)行。FIFO有兩個(gè)地址指針,一個(gè)用于將數(shù)據(jù)寫入下一個(gè)可用的存儲(chǔ)單元,一個(gè)用于讀取下一個(gè)未讀存儲(chǔ)單元的操作。讀寫數(shù)據(jù)必須一次進(jìn)行。其讀寫過程如圖6.2-16所示。

圖6.2-16FIFO的讀寫過程當(dāng)一個(gè)堆棧為空時(shí)(圖6.2-16(a)),讀數(shù)據(jù)指針和寫數(shù)據(jù)指針都指向第一個(gè)存儲(chǔ)單元;當(dāng)寫入一個(gè)數(shù)據(jù)時(shí)(圖6.2-16(b)),寫數(shù)據(jù)指針將指向下一個(gè)存儲(chǔ)單元;經(jīng)過七次寫數(shù)據(jù)操作后(圖6.2-16(c)),寫指針將指向最后一個(gè)存儲(chǔ)單元;當(dāng)經(jīng)過連續(xù)八次寫操作之后,寫指針將回到首單元并且顯示堆棧狀態(tài)為滿(圖6.2-16(d))。數(shù)據(jù)的讀操作和寫操作相似,當(dāng)讀出一個(gè)數(shù)據(jù)時(shí),讀數(shù)據(jù)指針將移向下一個(gè)存儲(chǔ)單元,直到讀出全部的數(shù)據(jù),此時(shí)讀指針回到首單元,堆棧狀態(tài)顯示為空。一個(gè)FIFO的組成一般包括兩部分:地址控制部分和存儲(chǔ)數(shù)據(jù)的RAM部分,如圖6.2-17所示。地址控制部分可以根據(jù)讀寫指令生成RAM地址。RAM用于存儲(chǔ)堆棧數(shù)據(jù),并根據(jù)控制部分生成的地址信號進(jìn)行數(shù)據(jù)的存儲(chǔ)和讀取操作。這里的RAM采用的是前面提到的雙端口RAM。

圖6.2-17FIFO結(jié)構(gòu)圖例6.2-9用VerilogHDL設(shè)計(jì)深度為8、位寬為8bit的FIFO。

//頂層模塊

moduleFIFO_buffer(clk,rst,write_to_stack,read_from_stack,Data_in,Data_out);

inputclk,rst;

inputwrite_to_stack,read_from_stack;

input[7:0]Data_in;

output[7:0]Data_out;

wire[7:0]Data_out;

wirestack_full,stack_empty;

wire[2:0]addr_in,addr_out;

FIFO_controlU1(.stack_full(stack_full),.stack_empty(stack_empty),

.write_to_stack(write_to_stack),.write_ptr(addr_in),

.read_ptr(addr_out),.read_from_stack(read_from_stack),

.clk(clk),.rst(rst));

ram_dualU2(.q(Data_out),.addr_in(addr_in),.addr_out(addr_out),

.d(Data_in),.we(write_to_stack),.rd(read_from_stack),

.clk1(clk),.clk2(clk));

endmodule

//控制模塊

moduleFIFO_control(write_ptr,read_ptr,stack_full,stack_empty,write_to_stack,

read_from_stack,clk,rst);

parameterstack_width=8;

parameterstack_height=8;

parameterstack_ptr_width=3;

outputstack_full; //堆棧滿標(biāo)志

outputstack_empty; //堆??諛?biāo)志

output[stack_ptr_width-1:0]read_ptr; //讀數(shù)據(jù)地址

output[stack_ptr_width-1:0]write_ptr; //寫數(shù)據(jù)地址

inputwrite_to_stack; //將數(shù)據(jù)寫入堆棧

inputread_from_stack; //從堆棧讀出數(shù)據(jù)

inputclk;

inputrst;

reg[stack_ptr_width-1:0]read_ptr;

reg[stack_ptr_width-1:0]write_ptr;

reg[stack_ptr_width:0]ptr_gap;

reg[stack_width-1:0]Data_out;

reg[stack_width-1:0]stack[stack_height-1:0];

//堆棧狀態(tài)信號

assignstack_full=(ptr_gap==stack_height);

assignstack_empty=(ptr_gap==0);

always@(posedgeclkorposedgerst)

begin

if(rst)

begin

Data_out<=0;

read_ptr<=0;

write_ptr<=0;

ptr_gap<=0;

end

elseif(write_to_stack&&(!stack_full)&&(!read_from_stack))

begin

write_ptr<=write_ptr+1;

ptr_gap<=ptr_gap+1;

end

elseif(!write_to_stack&&(!stack_empty)&&(read_from_stack))

begin

read_ptr<=read_ptr+1;

ptr_gap<=ptr_gap-1;

end

elseif(write_to_stack&&stack_empty&&read_from_stack)

begin

write_ptr<=write_ptr+1;

ptr_gap<=ptr_gap+1;

end

elseif(write_to_stack&&stack_full&&read_from_stack)

begin

read_ptr<=read_ptr+1;

ptr_gap<=ptr_gap-1;

end

elseif(write_to_stack&&read_from_stack

&&(!stack_full)&&(!stack_empty))

begin

read_ptr<=read_ptr+1;

write_ptr<=write_ptr+1;

end

end

endmodule

RAM模塊參考例6.2-7。

//*****************************測試代碼***************************

moduleFIFO_tb;

regclk,rst;

reg[7:0]Data_in;

regwrite_to_stack,read_from_stack;

wire[7:0]Data_out;

FIFO_bufferU1(.clk(clk),.rst(rst),.write_to_stack(write_to_stack),

.read_from_stack(read_from_stack),.Data_in(Data_in),

.Data_out(Data_out));

initial

begin

clk=0;rst=1;Data_in=0;write_to_stack=1;read_from_stack=0;

#5rst=0;

#155write_to_stack=0;

read_from_stack=1;

end

always#10clk=~clk;

initial

begin

repeat(7)

#20Data_in=Data_in+1;

end

endmodule圖6.2-18FIFO的測試結(jié)果6.2.7鍵盤掃描和編碼器

鍵盤掃描和編碼器用于在擁有鍵盤的數(shù)字系統(tǒng)中手工輸入數(shù)據(jù),通過檢測按鍵是否按下來產(chǎn)生一個(gè)唯一對應(yīng)此按鍵的掃描碼。

例6.2-10用VerilogHDL設(shè)計(jì)一個(gè)十六進(jìn)制鍵盤電路的鍵盤掃描和編碼器。

圖6.2-19是十六進(jìn)制鍵盤電路的鍵盤掃描和編碼器的一種設(shè)計(jì)方案。

圖6.2-19十六進(jìn)制鍵盤電路的鍵盤掃描和編碼器鍵盤的每一行都會(huì)通過一個(gè)下拉電阻連接到地,而行和列之間有一個(gè)以按鍵為開關(guān)的連接,當(dāng)按下按鍵時(shí)行和列之間就建立了連接。如果列線的值為1,則由按鍵連接到的那個(gè)列的行值也將會(huì)被拉升為1,反之行線將會(huì)被下拉至0。通過鍵盤掃描碼發(fā)生器單元來控制列線,使列線上的電壓有規(guī)律而有效地檢測行線的電壓值,進(jìn)而來確定按下按鍵的位置。鍵盤掃描碼發(fā)生器必須具備檢測識別按鍵,并產(chǎn)生一個(gè)與按鍵唯一對應(yīng)掃描碼輸出的功能。為此可以設(shè)計(jì)一個(gè)時(shí)序狀態(tài)機(jī),通過不同狀態(tài)之間的轉(zhuǎn)換來實(shí)現(xiàn)信號的檢測識別以及對應(yīng)掃描碼的輸出。首先,令所有的列線同時(shí)為1來檢測行線的值,直到發(fā)現(xiàn)一條行線的值被上拉為1,此時(shí)說明有按鍵被按下,但是仍然不能確定按鍵的位置;然后,通過依次將列線的值拉高來檢測各個(gè)行線的值,直到檢測到一條行線的值為1為止??刂菩盘枲顟B(tài)機(jī)轉(zhuǎn)移圖如圖6.2-20所示。

圖6.2-20十六進(jìn)制鍵盤電路的鍵盤掃描和編碼器的控制信號狀態(tài)轉(zhuǎn)移圖此時(shí)行線和列線的交叉處就是按鍵的位置。根據(jù)已確定的按鍵的位置輸出其對應(yīng)的編碼信息。其鍵盤編碼表如表6.2-1所示。表6.2-1十六進(jìn)制鍵盤電路的編碼器碼表為了使測試更接近于真實(shí)的物理環(huán)境,測試平臺中必須包括模擬按鍵狀態(tài)的信號發(fā)生器,能確認(rèn)按鍵對應(yīng)行線的模塊row_signal和被測試模塊hex_keypad_grayhill_072。模擬按鍵狀態(tài)的信號發(fā)生器可以嵌入在測試平臺中,通過不斷地給key信號賦值,模擬產(chǎn)生不同的按鍵信號。row_signal模塊用于檢測按鍵的有效性并確定按鍵所處的行。而synchronizer模塊通過檢測各個(gè)行線值的或來確定是否有按鍵按下,當(dāng)此模塊的輸出發(fā)生變化時(shí),被測模塊hex_keypad_grayhill_072將會(huì)確定按鍵的位置并輸出相應(yīng)的代碼。其VerilogHDL程序代碼如下:

//頂層模塊

modulekeypad(clock,reset,row,code,valid,col);

inputclock,reset;

input[3:0]row;

output[3:0]code;

outputvalid;

output[3:0]col;

wires_row;

hex_keypad_grayhillU1(.code(code),.col(col),.valid(valid),

.row(row),.s_row(s_row),.clock(clock),

.reset(reset));

synchronizerU2(.s_row(s_row),.row(row),.clock(clock),.reset(reset));

endmodule

//編碼模塊

modulehex_keypad_grayhill(code,col,valid,row,s_row,clock,reset);

output[3:0] code;

output valid;

output[3:0] col;

input[3:0] row;

input s_row;

input clock,reset;

reg[3:0] col;

reg[3:0] code;

reg[5:0] state,next_state;

parameters_0=6'b000001,s_1=6'b000010,s_2=6'b000100;

parameters_3=6'b001000,s_4=6'b010000,s_5=6'b100000;

assignvalid=((state==s_1)||(state==s_2)||(state==s_3)||(state==s_4))

&&row;

always@(roworcol)

case({row,col})

8'b0001_0001:code=0;//0

8'b0001_0010:code=1;//1

8'b0001_0100:code=2;//2

8'b0001_1000:code=3;//3

8'b0010_0001:code=4;//4

8'b0010_0010

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論