博文目錄
-
- 寫在前面
- 正文
- 按順序排列的端口連接配接
- 按名稱排列的端口連接配接
- 未連接配接/懸空端口處理
- 關于子產品端口的說明
- 參考資料
- 交個朋友
此系列相關博文:
Verilog初級教程(6)Verilog子產品與端口
Verilog初級教程(5)Verilog中的多元數組和存儲器
Verilog初級教程(4)Verilog中的标量與向量
Verilog初級教程(3)Verilog 資料類型
Verilog初級教程(2)Verilog HDL的初級文法
Verilog初級教程(1)認識 Verilog HDL
晶片設計抽象層及其設計風格
Verilog以及VHDL所倡導的的代碼準則
FPGA/ASIC初學者應該學習Verilog還是VHDL?
- 個人微信公衆号: FPGA LAB
- 個人部落格首頁
- 注:學習交流使用!
Verilog例化方式分為兩種,一種是按端口定義時的順序例化,一種是按端口名來例化。
下面将帶來這些内容的叙述以及對比,還有如何處理空置的端口等。
按順序排列的端口連接配接是例化的第一種方式,并不推薦,但是必須知道,因為還是有一些代碼使用這種例化方式。
如下,如果我設計了一個子產品:
module mydesign ( input x, y, z, // x is at position 1, y at 2, x at 3 and
output o); // o is at position 4
endmodule
那麼按端口順序例化的話,如下所示:
module tb_top;
wire [1:0] a;
wire b, c;
mydesign d0 (a[0], b, a[1], c); // a[0] is at position 1 so it is automatically connected to x
// b is at position 2 so it is automatically connected to y
// a[1] is at position 3 so it is connected to z
// c is at position 4, and hence connection is with o
endmodule
還是按上面那個例子,我定了一個子產品:
module mydesign ( input x, y, z, // x is at position 1, y at 2, x at 3 and
output o); // o is at position 4
endmodule
如果按端口名字例化,如下:
module tb_top;
wire [1:0] a;
wire b, c;
mydesign d0(
.x(a[0]),
.y(b),
.z(a[1]),
.o(c)
);
endmodule
我們推薦使用按名字進行例化的方式,因為這種方式不考慮順序,不容易出錯。
一般自動生成例化模闆的軟體或插件,也幾乎全是生成這種例化模闆的。如果生成按順序例化的模闆,那也就注定黃了。
這些都不是重點,重點是下一個話題,我們在做實際項目中也會常常看看有未連接配接的端口,我們如何認為呢?或者如何處理呢?
未連接配接到例化子產品中的端口按高阻态處理。如下:
還是拿上面設計的子產品為例:
module mydesign ( input x, y, z, // x is at position 1, y at 2, x at 3 and
output o); // o is at position 4
endmodule
我們對這個子產品進行例化使用:
module design_top(
input [1:0] a,
output c
);
mydesign d0 ( // x is an input and not connected, hence a[0] will be Z
.y (a[1]),
.z (a[1]),
.o ()); // o has valid value in mydesign but since
// it is not connected to "c" in design_top, c will be Z
endmodule
可以看到端口x,就連寫都沒寫,是以,可以認為是一個未連接配接的懸空端口,是一個高阻态;
端口o,雖然寫了,但是也沒連接配接到頂層子產品中的任意一個端口上,是以頂層的端口c也是一個高阻态。
下面舉一個移位寄存器的例子,看看有些端口未連接配接,生成的硬體原理圖是什麼樣的。
先從一個觸發器看起:
// Module called "dff" has 3 inputs and 1 output port
module dff ( input d,
input clk,
input rstn,
output reg q);
// Contents of the module
always @ (posedge clk) begin
if (!rstn)
q <= 0;
else
q <= d;
end
endmodule
通過例化觸發器形成移位寄存器,移位寄存器如果端口都連接配接了:
module shift_reg ( input d,
input clk,
input rstn,
output q);
wire [2:0] q_net;
dff u0 (.d(d), .clk(clk), .rstn(rstn), .q(q_net[0]));
dff u1 (.d(q_net[0]), .clk(clk), .rstn(rstn), .q(q_net[1]));
dff u2 (.d(q_net[1]), .clk(clk), .rstn(rstn), .q(q_net[2]));
dff u3 (.d(q_net[2]), .clk(clk), .rstn(rstn), .q(q));
endmodule
RTL原理圖:
如果有一些端口未連接配接:
module shift_reg ( input d,
input clk,
input rstn,
output q);
wire [2:0] q_net;
dff u0 (.d(d), .clk(clk), .rstn(rstn), .q(q_net[0]));
dff u1 (.d(q_net[0]), .clk(clk), .rstn(rstn), .q()); // Output q is left floating
dff u2 (.d(q_net[1]), .clk(clk), .rstn(rstn), .q()); // Output q is left floating
dff u3 (.d(q_net[2]), .clk(clk), .rstn(rstn), .q(q));
endmodule
RTL原理圖為:
在仿真中,由于端口懸空了,是以,輸出也是高阻态z。
所有的端口聲明都隐含地聲明為wire,是以在這種情況下端口方向就足夠了。然而需要存儲值的輸出端口應該聲明為 reg 資料類型,并且可以在程式塊中使用,比如 always 和 initial only。
輸入或inout類型的端口不能聲明為reg,因為它們是由外部連續驅動的,不應該存儲值,而是盡快反映外部信号的變化。連接配接兩個不同向量大小的端口是完全合法的,但以向量大小較小的端口為準,而另一個寬度較大的端口的剩餘位将被忽略。