title: “ [FPGA] FPGA基础入门教程 - 004 - 第三章 Veilog快速入门” date: 2019-05-15 11:00:00 categories:
- FPGA tags:
- FPGA
- 教程
- Verilog keywords: FPGA, 入门, 教程, Verilog —
第三章 Verilog快速入门
概览
现在信息爆炸的时代,关于verilog的语法书籍、教程多如牛毛,但是作为FPGA的初学者,在这些让人眼花缭乱的教程中简直无所适从,根本不知道该看哪个好。就本人这些年来看的一些verilog语法书来看,其实只需要选择一个最基础的书籍即可,这本书可以是中文,也可以是因为,但是语言最好要通俗易懂,内容不能太过冗长。再配一个IEEE的verilog标准,当做工具书,这样就足以了。 我在这里不打算将verilog从头开始讲,而是打算对一个通用的设计,在其中用到的最多的语法列出来,讲一讲模块间的架构,让读者能够很快的对FPGA的代码设计有一个宏观的映像,这个时间一两天足以。至于具体的语法,可以查看我前面提到的两类教材。
常用设计结构
Module
verilog的文件后缀是.v
,在一个通用设计中,所有的代码都是放在模块中的,一个模块一个.v文件,特殊情况或者写法这里不予讨论。模块的语法如下:
1 |
|
子模块声明&例化
在模块中,可以根据需要,如功能划分等,将一部分代码放入子模块中,子模块还可以包含自己的子模块。通常设计中,子模块的嵌套层数不应该过多,一个模块中的代码量也不宜过多。在上面的代码中,应该有三个.v文件。
模块端口/输入输出
在上述代码中标有//port list
的地方,会添加模块的输入输出端口。所谓输入输出,其实就是一个模块对内或者对外的接口,其有三个方向:input
,output
,inout
,分别是模块本身的输入、输出以及双向。所谓双向,就是说这个端口可以根据需要,既可以接收外部输入,也可以往外部输出信号,这两个状态需要二选一。输入输出的语法如下:
1 |
|
输入输出有4个部分,包括方向:input/output/inout,类型:wire/reg,位宽 none/n:0,以及输出输入名称。其中类型wire代表这个输入输出的是一个线连接过来,而reg代表它是一个寄存器连接过来。位宽部分不写,代表位宽是1,一个n位宽的寄存器,其定义应该为[n-1:0]。在每个输入输出用,
隔开,最后一个端口不包含,
。
声明
在使用一个变量前,我们都需要先声明其类型、位宽。其基本语法为:
1 |
|
就像前面所述,wire为线网类型,可以作为一个线连接两个接口,也可以连接组合逻辑门(与或非门等等)。reg类型的变量是连接到寄存器的输出。
组合逻辑和时序逻辑
组合逻辑就是不依靠时钟来进行采样的逻辑,属于电平敏感逻辑。记住一点,组合逻辑的赋值用=
,这叫阻塞赋值,时序逻辑属于利用时钟进行采样的寄存器逻辑,用<=
进行赋值。
组合逻辑赋值
组合逻辑使用assign(连续赋值)进行赋值。 例如,下面是一个二输入加法器的例子:
1 |
|
也可以直接给一个信号赋值固定值:
1 |
|
组合逻辑可以用always @(敏感信号表)
或者always @(*)
,推荐使用后者
1 |
|
时序逻辑
1 |
|
在上述例子中,寄存器的采样边沿和复位电平的有效电平可以自由组合,但是一般推荐是上升沿。对于xilinx来说,推荐高电平复位,对于altera来说,推荐低电平复位。到底是同步复位,还是异步(同步复位需要保证时钟能采到复位信号才能复位,异步复位则是复位信号的优先级比时钟采样高),则根据实际情况来选择。前提是能用同步复位的地方就用同步复位,如果同步复位不能保证复位逻辑和期望的一样,则使用异步复位。
操作符
本章节可以参考语法书
if…else if…else语句
if语句需要再always块中,无论是always @(*)
或者always @(posedge clk...)
,条件语句只需要记住基本语法即可 :
1 |
|
if是可以控制优先级语句。
case…endcase语句
当要并行判断某些逻辑时,使用case语句,case依旧需要放置于always块内:
1 |
|
- if中可以有case,case中也可以有if
- 通常认为if有优先级,case没有优先级,你也可以这么认为,但是并不绝对,有兴趣可以深入研究一下
子模块
就前面所述,模块中可以有很多子模块,下面就看下子模块怎么使用
子模块的例化
在一个module内的位置可以添加子模块,子模块添加格式如下:
1 |
|
实例
在下一章节中,我们将使用一个简单的例子来看看怎么使用Verilog代码进行设计的,它的一个完整的结构、设计思路等都将在其中进行详细说明。