TA的每日心情 | 开心 2019-11-20 15:00 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
Verilog中INOUT端口的使用方法
3 D, C0 W9 }, w* [7 ?9 D" k. r+ k" v" V( B
# C. f3 v @! j, B% v+ X6 u+ W
见许多问这个问题的,总结一下,希望能对大家有点用处,如果有不对的地方,欢迎指出. 9 a$ K" x9 F) C( `+ C
芯片外部引脚很多都使用inout类型的,为的是节省管腿。一般信号线用做总线等双向数据传输的时候就要用到。0 Q" z# B) K8 w5 k9 c0 y
9 [ j' N& [4 h0 G
先送上一个表格吧,正好今天在一本书上看到了。这个表格表示 的是在同等驱动强度下,两个驱动源驱动的wire型和tri型 变量的真值表。8 V: |' P" M$ M! C
6 _5 a* s+ E! U; b3 T; d( e![]()
7 R9 c* [. q' U* B4 m" ^; J# D H g: J4 R% j+ v2 d0 c0 N1 O# e
2 ]4 G4 a: G7 S. w# l7 j 发现问题了吧!如果某时刻inout口有输入,此时你又正好要拿这个inout口 做输出那么冲突是在所难免的,会出现什么样的结果可以参考上面的表。另外看这个表,你就应该明白双向口该怎么处理了吧。
* J5 \; A: h2 i3 ~2 M ]$ q& z
. @& l% {# t* S: S( n: E ^INOUT类型了。就是一个端口同时做输入和输出。 inout在具体实现上一般用三态门来实现。三态门的第三个状态就是高阻'Z'。 当inout端口不输出时,将三态门置高阻。这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料., \3 U* N0 M! w6 ?5 r2 T* \
1 使用inout类型数据,可以用如下写法:$ ^9 x# L$ w% O" v
inout data_inout;
) F+ b% G* w% l% Q0 B* R# Binput data_in;# y+ a6 `% K" L) J/ j% ?
reg data_reg;//data_inout的映象寄存器
( K/ R$ s7 l4 \4 a: Areg link_data;: ?- u3 Y; q" A* K8 W' n4 m+ X# n- Q
assign data_inout=link_data?data_reg:1’bz;//link_data控制三态门
* g& j; ]2 C0 M4 t0 K6 ?- W3 g//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.
+ Z& a/ e* N( s( l3 w$ p5 m- x2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.
% p7 Q0 i2 m3 Q1 [ 当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1’bz;其中的link ,data_in_t是reg类型变量,在测试模块中赋值.
( ^* I$ V; D% _1 M; {' ~* o" H3 \: B( N 另外,可以设置一个输出端口观察data_inout用作输出的情况:
( r* U. k/ h' F- s2 r. i Wire data_out;
+ _4 i- I q& X$ {' t Assign data_out_t=(!link)?data_inout:1’bz;+ `9 Y! l+ o, B# E! c( H
+ c- A* }$ m0 v# t. e
else,in RTL! _: Y3 |! ~/ [4 _$ k( T* D# R/ K
inout use in top module(PAD)' A- ^8 D/ Y- | u. ?$ K
dont use inout(tri) in sub module
% c( Z8 Y5 s0 C! K8 U( }+ e也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port实现,到顶层的时候再用三态实现。理由是:在非顶层模块用双向口的话,该双向口必然有它的上层跟它相连。既然是双向口,则上层至少有一个输入口和一个输出口联到该双向口上,则发生两个内部输出单元连接到一起的情况出现,这样在综合时往往会出错。 0 w+ h, k* A+ R r
1 Y7 g5 ~1 X. z# a
举例说明
) u7 r- X% p4 K$ f0 ^& ?输入口din定义:input[7:0]din;当双向端口5 F$ D# X$ Q T& k$ R1 N
dinout作为输出口时,我们从din端口输入数据到! F5 B) g2 q; H% T; o. ^
模块中,让数据从dinout口出来。/ s* }* Y! N7 K
输出口dout定义 utput[7:0]dout;当双向# M. u! ]' u+ R" J* B R. y
端口dinout作为输入口时,我们让数据从dinout口2 l1 g) J' j1 J$ O( E5 ^: A
输入,从输出口dout输出。6 k& c9 j0 Y2 |/ g
双向端口dinout定义:inout[7:0]dinout;# p5 m% G" r9 i9 x+ |1 _! W# U, W
三态门选通信号z:inputz;- z9 u6 o2 d0 A5 R+ R- u; R6 k3 A) {, C
当z=1时,把三态门置为高阻态,这时dinout! W& s9 M- s; T! M* \& h0 _
作为输入口用;当z=0时,开通三态门,这时dinout
; E6 L3 Z( v) ?7 y6 B) H, y7 r作为输出口用。
0 l6 l9 E/ R r6 C& H7 A4 w8 h$ E三态门控制语句为:7 e4 B) s* B% \ m
assigndinout=(!z)?din_reg:8'bz;
2 h$ v$ Q3 d. @* f7 Y6 ~7 `总的完整程序如下:7 z& g+ B& d% l* [+ r5 b. b
moduledinout(din,z,clk,dout,dinout);' A; I) t) S/ g4 W
input [7:0]din;
) ?2 G' q, Q1 k: k! g8 [input z;3 f; a& M1 k" I0 y0 a
input clk; n: W, \; _% F9 C4 i
output [7:0]dout;7 g& [) M2 E: T) {. I0 T
inout [7:0]dinout;
1 y$ x8 a4 Y5 Z7 Greg [7:0]dout;- f# A: Q" T# d1 d
reg [7:0]din_reg;
0 g% a# ]5 ?! ]. Z; Sassigndinout=(!z)?din_reg:8'bz;
4 |" s- f/ R8 R P# J7 {always @(posedgeclk)) e! T, J7 y3 M! @
begin% i. T1 @5 C" @9 n( E3 t
if(!z)
d3 r" L$ q& @! cdin_reg=din;
Y* ]; S+ i2 telse
" s' K0 t2 \5 g Kdout=dinout;1 y' A% `( F, j; E4 Z! r
end$ w( I; C- \( U9 i7 X: L P |
Endmodule
& c+ ?0 K! @: ?, K- o# Z |
|