找回密码
 注册
关于网站域名变更的通知
查看: 197|回复: 1
打印 上一主题 下一主题

VHDL学习理解 

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-5-14 16:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
VHDL学习理解

2 @9 h+ U7 [' ]2 f, t) F6 A3 D0 `4 l9 x7 i1 E$ V
一. 关于端口
0 b: f0 F9 w: h1 g7 ^+ `8 n/ _VHDL共定义了5种类型的端口,分别是In, Out,Inout, Buffer及Linkage,实际设计时只会用到前四种。In和Out 端口的使用相对简单。这里,我们主要讲述关于buffer和inout使用时的注意事项。
6 A% w+ L$ c# H0 O  N  a与Out 端口比,Buffer端口具有回读功能,也即内部反馈,但在设计时最好不要使用buffer,因为buffer类型的端口不能连接到其他类型的端口上,无法把包含该类型端口的设计作为子模块元件例化,不利于大型设计和程序的可读性。若设计时需要实现某个输出的回读功能,可以通过增加中间信号作为缓冲,由该信号完成回读功能。
$ j1 y+ N5 D5 D& F! Q3 q2 H( N双向端口Inout是四种端口类型中最为特殊的一种,最难以学习和掌握,为此专门提供一个简单程序进行阐述,部分程序如下:! t( t9 d$ T4 @& ^* r6 @% H
... …: r& Q; q) c5 x* @, |% p
① DataB<=Din when CE=’1’ and Rd=’0’ else9 [8 d% Y' f, v! B# j
② (others=>’Z’);
6 ]: A$ x# Z( }$ A5 ~+ W& A③ Dout<=DataB when CE=’1’ and Rd=’1’ else
8 F$ W( M, ]# w- N$ s; L④ ( others=>’1’ );# T$ G# M2 ^; ^0 o# P; s! x
… …6 j0 B& J3 O6 E3 _: c; q

) a& b& j2 @; ?程序中DataB为双向端口,编程时应注意的是,当DataB作为输出且空闲时,必须将其设为高阻态挂起,即有类似第②行的语句,否则实现后会造成端口死锁。而当DataB作为有效输入时, DataB输出必须处于高阻态,对于该例子中即,当 CE=’1’ and Rd=’1’时,输出DataB应处于高阻态。1 B; R: c' Z, L

9 U. b) R- F' ?5 l7 m
" Q6 c! l5 f  a+ G. n7 M# y二.信号和变量
) x  l6 L" V& W3 a+ H, {4 d常数、信号和变量是VHDL中最主要的对象,分别代表一定的物理意义。常数对应于数字电路中的电源或地;信号对应某条硬件连线;变量通常指临时数据的局部存储。信号和变量功能相近,用法上却有很大不同。5 T& l" N+ F2 W' W7 ^

( x: ]3 D/ l3 A/ ]% d3 X
8 ~  F3 V. `& a  k! |! P表1 信号与变量主要区别
: u- P. f2 D2 ~' r信号 变量
) a  q7 z/ j- x: s2 G赋值延迟 至少有△延时 无,立即变化6 q: W4 p6 u$ u
相关信息 有,可以形成波形 无,只有当前值
1 a& K9 Z. i9 N8 y  x7 b0 Q进程敏感 是 否. @' x+ W" X6 J0 F: I3 U2 U
全局性 具有全局性,可存在于多个进程中 只能在某个进程或子程序中有效
, e& I& V+ @5 G: x* F6 g) c相互赋值关系 信号不能给变量赋值 变量可以给信号赋值
9 v" W9 a& K/ o) P% F: w% U对于变量赋值操作无延迟,初学者认为这个特性对VHDL设计非常有利,但这只是理论上的。基于以下几点原因,我们建议,编程时还是应以信号为主,尽量减少变量的使用。
3 a, J5 u! m7 ~7 K' I8 `/ S
  S! F. _6 e. y5 }$ ~' M(1)变量赋值无延时是针对进程运行而言的,只是一个理想值,对于变量的操作往往被综合成为组合逻辑的形式,而硬件上的组合逻辑必然存在输入到输出延时。当进程内关于变量的操作越多,其组合逻辑就会变得越大越复杂。假设在一个进程内,有关于变量的3个 级连操作,其输出延时分别为5ns,6ns,7ns,则其最快的时钟只能达到18ns。相反,采用信号编程,在时钟控制下,往往综合成触发器的形式,特别是对于FPGA芯片而言,具有丰富的触发器结构,易形成流水作业,其时钟频率只受控于延时最大的那一级,而不会与变量一样层层累积。假设某个设计为3级流水作业,其每一级延时分别为10ns,11ns,12ns,则其最快时钟可达12ns。因此,采用信号反而更能提高设计的速度。, Z5 d9 w  @" y/ U

0 Y; \' D* s. }- C" b(2)由于变量不具备信息的相关性,只有当前值,因此也无法在仿真时观察其波形和状态改变情况,无法对设计的运行情况有效验证,而测试验证工作量往往会占到整个设计70%~80%的工作量,采用信号则不会存在这类问题。
4 r7 z/ F: D" \. j" t2 w
/ G5 D9 g& D2 t(3)变量有效范围只能局限在单个进程或子程序中,要想将其值带出与其余进程、子模块之间相互作用,必须借助信号,这在一定程度上会造成代码不够简洁,可读性下降等缺点。
& @7 b2 g/ d* `0 F& |4 b' B' X当然,变量也具有其特殊的优点,特别是用来描述一些复杂的算法,如图像处理,多维数组变换等。
4 i1 n' A0 F  x  A7 ~# A' R0 t( B& O% q

" j- j) p3 C/ ?/ N三.位(矢量)与逻辑(矢量)
$ J- b# ^- T+ d# g4 f+ z/ e$ vbit 或其矢量形式bit_vector只有’0’和’1’两种状态,数字电路中也只有’0’和’1’两种逻辑,因此会给初学者一个误区,认为采用位(矢量)则足够设计之用,而不必像std_logic那样出现’X’,’U’,’W’各种状态,增加编程难度。但实际情况却并非如此,以一个最简单D型触发器设计为例
4 M: v* ~: ~1 _. Z! L* K… …
! n0 c! h# {) _2 Q① process(clk)0 ], S( @/ w6 T
② begin% U3 D8 ~; m  l# Z3 v7 `
③ if clk’event and clk=’1’ then
4 I; U4 l4 N, P9 `" v- I: l+ D8 v④ Q<=D;# s8 F' c) Q+ r- @* Q4 a
⑤ end if;' \( W2 q1 @1 q. H6 ?1 ]9 W0 O
⑥ end process;
0 w6 G- ?( R2 U1 ?5 p% M… …3 @) |4 V8 x+ w7 b, i
实际中clk对数据端D的输入有一定的时间限制,即在clk上升沿附近(建立时间和保持时间之内),D必须保持稳定,否则Q输出会出现亚稳态,如下图所示。
1 D7 a' k: O% ^2 p: `' E& q% X5 I7 e
图1 建立时间和保持时间  r3 B& v. `6 C7 N3 B7 y& k' y3 i% R
当clk和D时序关系不满足时,由于bit只有’0’或’1’,系统只能随机的从’0’和’1’中给Q输出,这样的结果显然是不可信的;而采用std_logic类型,则时序仿真时会输出为一个’X’,提醒用户建立保持时间存在问题,应重新安排D和clk之间时序关系。
& Y* E" C& K4 \- C; @2 D3 Z此外,对于双向总线设计(前面已提及)、 FPGA/cpld上电配置等问题,如果没有’Z’,’X’等状态,根本无法进行设计和有效验证。/ L+ M5 ?  f7 z/ n3 ?4 i1 h- e$ _, b

/ \# @7 Z4 k6 I+ {- L  `( c/ U& ]( O4 C: I* ~! c4 Q
四.关于进程7 B, c$ A8 g/ z. C- N
进程(Process)是VHDL中最为重要的部分,大部分设计都会用到Process结构,因此掌握Process的使用显得尤为重要。以下是初学和使用Process经常会出错的例子。0 U9 v# f* |5 u5 c

8 x8 w# D, {; }& t6 |1. 多余时钟的引入
3 B8 q; q. x% y8 ~4 B; ?$ x1 [在设计时往往会遇到这种情况,需要对外部某个输入信号进行判断,当其出现上跳或下跳沿时,执行相应的操作,而该信号不像正常时钟那样具有固定占空比和周期,而是很随机,需要程序设计判断其上跳沿出现与否。这时,很容易写出如下程序:6 w" n! c. u7 Z4 X9 A( C6 n
① process(Ctl_a) -- Ctl_a即为该输入信号% r" p  m/ l. _
② begin
; N) U4 A3 G7 q( p2 k& j8 p) }③ if Ctl_a’event and Ctl_a=’1’ then) y" W( G4 Q' J$ |3 P! e
④ … … ; --执行相应操作
9 ^2 }& o3 H& ~0 u8 X; _⑤ end if ;; t" h1 \7 h0 `
⑥ end process;
. P" q$ r7 x% x" o" c; {: ]由于出现第③行这类语句,综合工具自动默认Ctl_a为时钟,某些FPGA更会强行将该输入约束到时钟引脚上。而设计者的初衷只是想将其作为下位机的状态输入以进行判断。上面的程序容易造成多时钟现象,增加设计的难度。解决的办法可以如下,将Ctl_a增加一级状态Ctl_areg寄存,通过对Ctl_a和 Ctl_areg状态判断上跳与否,改正程序如下:$ N' h7 e* H* p# L0 v: [+ C
① process(clk)
8 z: }  t. n  T② begin$ ?* ~" |" l" Z, Q
③ if clk’event and clk=’1’ then' i) W4 M! o7 D3 M6 S6 p& |; `
④ Ctl_areg<=Ctl_a;--产生相邻状态
+ W, c9 p5 `  \⑤ if Ctl_areg=’0’ and Ctl_a=’1’ then--上跳判断* M# _  s# ]2 x3 J4 T
⑥ … … ; --执行相应操作) S: g3 }8 `! J/ z& B$ b
⑦ end if;
; \; }* a3 V8 }, n4 F⑧ end if;& y1 Z3 O, }" V1 r$ P7 M1 n
⑨ end process;# J4 ?/ n7 y4 ^9 W9 v/ N: M' ~
程序中第④行用以产生两个相邻状态,第⑤行对前后状态进行判断是否有上跳现象发生。其中,需注意的是clk的时钟频率应明显快于Ctl_a信号的变化频率,以保证正确采样。
1 X9 O5 U% s4 O7 j6 H  G# I% R5 U  i8 I3 {8 I/ T6 g
2. 输出多驱动
4 z, A8 V  M2 b$ Y; ~- `5 U; Y. C误用Process经常会引起输出多驱动源的发生,即在两个以上的进程内对同一信号赋值操作。以下程序就出现了这类情况:& m$ o! Z/ S! ^
⑴ Proc_a: process(clk)
8 K$ n" Y7 {5 q+ t- l⑵ begin
  f; p2 X9 W3 |+ m. Z! r; _⑶ if clk’event and clk=’1’ then8 G6 F# D! D3 P8 v" u
⑷ Dout<=Din_A;$ \1 U' n$ v5 x# z; V1 _
⑸ end if5 w' i- k2 W4 t2 w. T( k
⑹ end process;;7 _/ S! @7 o8 }
) t9 o$ `2 V& U3 W: O2 t1 @
⑻ Proc_b:process(sel_en)
) X5 S% k. n" a⑼ begin6 V8 y5 e8 v9 h/ b1 m
⑽ if sel_en=’1’ then5 c% E+ T0 c9 R. v8 @
⑾ Dout<=Din_B;
  l, d; R- d+ K0 m+ h) c8 ?⑿ end if;
$ V' Y: V7 v) ^/ _9 U- k' s⒀ end process;0 {) @: L9 b  }+ N& c: S
进程Proc_a和Proc_b中都出现了对Dout的赋值语句,设计者原本的想法是,只要合理控制好clk和sel_en输入,使其不发生冲突,即clk 上升沿时sel_en不为’1’;sel_en为’1’时,不出现clk的上升沿,这样Proc_a,Proc_b两个进程就不会发生冲突。但综合时,综合工具会将所有可能情况全部罗列进去,包括第⑶行和第⑽行同时成立的情况,此时对于Dout就有Din_A和Din_B两个输入驱动,Dout不知接收哪一个,因此该程序无法综合,改正的方法是只要将两个进程合并成一个即可。& f9 B! e- R4 }$ P6 D  q
由于进程在VHDL中的重要性,对此专门做了一个总结如下:
) z& w4 W7 q* t$ a3 Q( b(1)一个进程中不允许出现两个时钟沿触发,(Xilinx公司CoolRunner系列CPLD支持单个时双钟的双触发沿除外)
; L7 F4 h; r+ @5 S: E7 E" c(2)对同一信号赋值的语句应出现在单个进程内,不要在时钟沿之后加上else语句,如
8 P( M0 L4 m# p* }( B, rif clk’event and clk=’1’ then - else … 的结构,现有综合工具支持不了这种特殊的触发器结构
: m- @" \: ]5 ](3)当出现多层IF语句嵌套时,最好采用CASE语句替代,一是减少多层嵌套带来的延时,二来可以增强程序的可读性9 u( }, a+ }' I! H2 p& F% Z
(4)顺序语句如IF语句、CASE语句、LOOP语句、变量赋值语句等必须出现在进程、函数或子程序内部,而不能单独出现在进程之外
3 D7 L3 y! D) y2 f- g(5)进程内部是顺序执行的,进程之间是并行运行的;VHDL中的所有并行语句都可以理解为特殊的进程,只是不以Process结构出现,其输入信号和判断信号就是隐含的敏感表
& N* Q( _& V( G& N  r* `6 Q5 q( W7 Z$ A/ n2 o8 l+ N$ D; P

' U; m! j2 B4 u# T0 p五.关于VHDL学习中的几点说明# j2 {; z& N" d  G1 `+ K! o7 w
与软件语言相比,VHDL最重要的特点就在于它的并行运行特性,当设计好的电路上电后,器件内部所有信号将同时并发工作,而不会以软件方式按照程序顺序执行,即使在进程内部也是趋向并行工作的。例如以下程序:
/ F" j/ }) v: A3 v4 n: L① process(clk)
$ i& S) ^  i+ I2 @. h, U② begin- E7 y" O6 a% ^; u- [3 A
③ if clk’event and clk=’1’ then
7 V# g% K% Q, c4 n$ T9 l" y- t④ <= ;
% Y9 f& }! q$ U& b; N* a⑤ <= ;
  B% ~" V: H# Q⑥ end if;;, E! v1 d. \/ z; F/ p3 p9 S
⑦ end process;- ~' ~& \$ ]( h; @% v
综合的结果两个独立的D型触发器,虽然进程内部应按顺序执行,但是硬件实现后,只要采样到时钟上升沿, 和 状态会同时翻转,而不会先执行的变化,然后才会去执行的转变。因此,VHDL学习过程中,应加强硬件概念的理解,没有硬件概念或是硬件概念不强,在设计时,往往会将VHDL设计以软件编程的方式来处理,而得出一些不可思议的结果。
; o2 C7 P2 k2 w( I作为一门硬件描述语言,VHDL几乎可以用来描述现有的大型系统数字电路、算法以及其它设计。但是,限于目前综合工具的水平,VHDL中的许多语法还不能支持,例如:$ g; `) l" ^7 \$ K- S0 I/ Z, z2 R
dout<=din after 5 ns; ! }- c5 V7 i8 Q; p
综合时就无法达到如此精度,因此这条语句主要用来编写测试激励,而很少出现在设计实体中。类似的情况还有很多,目前VHDL设计使用的也只是整个标准中的一部分,这也正是VHDL的“可综合子集”性质,它一定程度上限制了VHDL的广泛应用,但是随着综合技术的发展,这种情况会逐渐得以改善,VHDL也将在各个领域中发挥出愈来愈重要的作用。# Q: T, U  _8 n+ E! N
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-2 21:19 , Processed in 0.125000 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表