|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
转——凔海笔记之FPGA(四):Verilog HDL语法简单述
! f2 ?2 q) W: U/ J! G2 a) J! C6 A
在百度百科中,是这样介绍Verilog HDL的,它是一种硬件描述语言(HDL:Hardware Description Language),以文本形式来描述数字系统硬件的结构和行为的语言,用它可以表示逻辑电路图、逻辑表达式,还可以表示数字逻辑系统所完成的逻辑功能。 Verilog HDL和VHDL是世界上最流行的两种硬件描述语言,都是在20世纪80年代中期开发出来的。记得在刚接触FPGA时,还不知道有一种语言叫做VHDL,只是傻傻的跟着特权同学去入门,还好选对了语言入对了门,感谢吴厚航老师。- P# g e2 O" D
古人云:“工欲善其事,必先利其器”。对于我们来说,若要拿下FPGA,必先克下Verilog。但若苦学语法而不用,也会因利器而误事。所以,咱先知道点就好啦,说多了,也不敢,毕竟菜鸟我不会/(ㄒoㄒ)/~~
% K. x! i' [5 T' p8 V0 r, V1、模块声明:module……endmodule
/ p; e# B$ X t7 u+ l. c, q) hmodule:模块。endmodule:模块结束。显然,这之间要写的是一个模块的内容,也就是Description模块功能。module后面要跟着这个模块的名称,它是模块的标签,格式是这样的:
! S6 j/ p4 N' C# L9 o# r! gmodule 模块名(口1,口2,口3,口4, ………);括号里面的内容就是输入或输出信号的端口声明。一般一个.V文件里面放一个模块。Why?
& I4 v ~1 Q8 c+ n$ p" x* kThis is coding style!!! 2、端口声明:input、output、inout。0 Q; V- r/ m: L5 v" ?6 i
input :输入。output:输出。inout:输入输出。如果把模块看成一个黑匣子,那么端口声明就是与外界连接的引线。所以在写模块内容时候,先要定义输入什么,输出什么。我们所做的就是对输入信号的处理及对输出信号的表述。
0 g- J& R6 F* a3、信号类型:wire、reg。+ G1 `3 n6 \- O1 m0 H/ N: `8 t
wire:线。reg: register,寄存器。网上有这么一句话,“reg相当于存储单元,wire相当于物理连线”,如果理解了这句话,我想也就理解了这俩个信号类型。wire表示直通,即输入有变化,输出马上无条件地反映(如与、非门的简单连接)。reg表示一定要有触发,输出才会反映输入的状态。但我还是没理解(⊙﹏⊙)b,就先这样吧,这个需要去悟。声明一下哈,信号类型不止这俩个,其他的碰到了再说吧,(*^__^*) 嘻嘻……。
9 J& ?& T) b7 L1 J在书写的时候,
" ?% W6 d. J% B8 v6 x) D1 Pwire c; //定义一个一位wire型数据. r% f2 d* ? \% u G! d
reg c; //定义一个一位名为a的reg型数据
. Z$ W; `% _0 ]$ Swire [7:0] b; //定义一个八位的wire数据+ `6 W* T7 k! a
reg [7:0] b; //定义一个八位的reg数据
/ }: [5 ^2 y8 j# i7 A' i其中。[7:0]表示位宽,只要是整数就好,当然分号左边的数要大于右边的。
/ R- h* ~$ e0 t9 O; a' F6 B
5 j/ d& Y4 i% p( [! R" u9 _; D4、参数定义:parameter
' c2 ?! \6 l( C# r! @% pparameter:参数,百度有这样翻译:“参数,传送到功能或程序并影响其操作的值”。说实话,我对这个翻译爱得很深沉,(✿◡‿◡)。值得一提的是,parameter的作用域仅限于该文件,而与之相对的define确因编译器不同会产生不同的效果,所以,在一般情况下,用parameter吧,如果用define还是在该文件的结尾加上一个undef。
5 q6 c0 e) s" e
9 w. Q7 O1 s) p P4 t/ N5、常量。$ |9 S4 I5 `1 a3 `/ a! ^5 \ q
学过C语言都知道,常量表示方法有很多种,二进制B、八进制O、十进制D、十六进制H。对于Verilog语言,同样有这几种表示方法,其书写格式可以为<位宽><进制><数字>,4’b1101即为用二进制表示位宽为4的数1101;可以为<进制><数字>这样缺省位宽,由机器系统决定,说实话,我是受不了这样的写法;也可以为<数字>这种表示方法,缺省进制默认十进制。其实无论用那种表示方法,都是为了能够很好地描述所写模块,软件都会给翻译成二进制表示,毕竟机器只有高低电平。
) t8 j" P0 N: D+ R* t
" H2 i; E H3 A8 G6、连续赋值:
4 d' X: y& n7 O/ y Dassign。我认为它就是连接内部小模块之间或是模块与外界联系的线的标志。嗯,就这样! F: t2 i* N$ d
) o& I; D( P" Q- B P0 U3 l4 p
7、always模块:
2 V2 y- ~$ J* q- Qalways@(敏感事件列表) 用于描述时序逻辑
# X: M- X& v8 [敏感事件上升沿 posedge,下降沿 negedge,或电平
% ]. w7 u; W" V* K- ?: w5 F敏感事件列表中可以包含多个敏感事件,但不可以同时包括电平敏感事件和边沿敏感事件,也不可以同时包括同一个信号的上升沿和下降沿,这两个事件可以合并为一个电平敏感事件。
# F4 r9 J- P2 U' }( Z' E在新的verilog2001中“,”和“or”都可以用来分割敏感事件了,可以用“*”代表所有输入信号,这可以防止遗漏。- L; E& [7 w% A/ h0 b, o8 ~7 C! _
合法的写法:& c' a- V6 X ~$ R( |- Y
always@ *
6 G* f' J& J2 \$ R5 U; n5 oalways@ (posedge clk1,negedge clk2)
- |+ n' ? J" _& aalways@ (a or b)
V! v: a- |9 ^# P* \' \8 R6 d( E) N
8、begin……end ~- `" Y6 F+ A' [) M a b% s a
这个吧,就把它当做C语言里面的{}吧) d4 M+ X* i# D/ R* v+ u
; ?' g5 b9 j+ `" q4 z1 o
9、赋值符号:=和<=
2 C0 y; @4 |" b# q0 J6 k 这个被称为阻塞赋值和非阻塞赋值,这个可是很有说头的,不过,咱就先知道" g: \5 `+ i" t/ R9 f
a=a+1;
) K3 Y1 j7 ^2 S3 a0 d' s4 Kb=b+1;
* E* Q) R0 w5 y% D* c& v# mc=c+1;, T L I# s, F( I3 A% ~8 P% c
这都是顺序执行的,和C语言一样。但
/ @; \6 X; v1 p) i R: Q8 ~a<=a+1;2 y- n; |* s. {; y9 ?
b<=b+1;8 l/ @% N) r* m
c<=c+1;
* T, q3 N% f5 C. y是并行的,是同时工作的,很神奇呀,为啥??以后再谈~7 q- s1 M5 ^% @; f
不过我们在always@(*)块语句内的赋值符号使用的是“=”,而always@(posedge XXX)的块语句内的赋值符号使用的是 “<=”
, G3 [9 S9 c$ F/ \
. I3 }2 S; G0 o; ^" g, E Q4 f10、运算符及表达式% ?3 t/ {* j+ P/ d7 D7 Q: P
6 c" l/ R& _# h注:摘自夏宇文老师的书) W1 q9 ^" j: [
|
|