FPGA学习笔记day4
这节课学习联合仿真
怎么理解联合仿真?好像就是把仿真软件和开发环境联系到一起去
首先在quartus里面找到tools,option

然后在这里找一下modelsim的安装路径


然后去quartus的assignments里面选择一下settings,在这里设置一下

然后还有下面的这个simulation,作用:在把tb文件写好之后,需要在这里添加tb文件

可以把1ps改成1ns
然后在下面点击testbench,然后点new,添加tb文件。以前写tb文件都是需要正儿八经的自己敲,这里有一个工具可以生成一个模板:

点完了之后,下面会提示你这个:

意思就是他成功的在你的par下面创建了一个simulation文件夹

打开可以看到里面有个后缀名.vt的文件

打开看一下

里面有很多没有用的注释,去掉即可

然后在相应位置添加几行代码就行了

这个模板生成的文件,module的名字会加一个vlg_tst,不要忘了,刚才有一个添加tb文件的步骤,new什么的,在那里添加的名字是这个module的名字,而不是tb文件的名字

然后点ok

就可以了,有的时候仿真不通过主要存在两个可能性
一个是文件名没整对
一个是本身quartus编译就没通过
一个是quartus程序里面的时序对仿真系统来说太慢了,比如流水灯,一秒钟变一次状态。但是仿真里面都是以ns为单位的。所以观察不到变化。改改程序就完事了。
速学verilog
又开始讲fpga,过一遍吧

HDL:hardware description language硬件描述语言
常见的有verilogHDL和VHDL
verilog历史:

verilog与C语言的区别:

学一下基本语法:
1、基础知识:

2、数字进制格式:

需要注意一点,这个我不知道,就是这个位宽实际上指的是二进制数的位宽。参见csdn的一个文章的解释:


3、标识符
用于定义模块名、端口名、信号名,可以是任意一组字母、数字、$、下划线,第一个字符必须是字母或者下划线。标识符区分大小写。
建议:命名信号的时候最好让他有一定的含义
4、数据类型
寄存器数据类新给,线网数据类型、参数数据类型
reg。wire。parameter
reg:表示一个抽象的数据存储单元,通过赋值语句可以改变寄存器存储的值,reg数据类型的初始值默认为不定值X
reg类型数据只能在always和initial语句中被赋值。
若always里面带有时钟信号,则该寄存器变量对应为触发器
若always里面没有时钟信号,则该寄存器变量对应位硬件连线
wire:表示结构实体之间的物理连线。这种的变量不能存储值,他的值是由驱动它的原件决定的。
驱动线网类型变量的元器件有门、连续赋值语句、assign等
如果没有驱动原件连接到线网类型的变量上,则该变量就是高阻的,值为z
线网数据类型包括wire和tri型,wire较为常用
parameter:就是个常量,有点像C里面的define,我们可以一次定义多个参数,参数与参数之间需要用逗号隔开,每个参数定义的右边必须是一个常数表达式。

参数型数据类型常用于定义状态机的状态,数据位宽、延迟大小。采用标识符来代表一个常量,可以提高可读性。
5、运算符
1算数运算符:

模除其实就是求余数
2关系运算符

3逻辑运算符

4条件操作符

eg:result=(a>=b)?a:b
功能等同于always中的if-else语句。a是判断条件,bc是执行语句
5位运算

6移位运算


7拼接运算符

举例子:

优先级:

6、verilog注释
和C一样
//和/*
7、verilog关键字
常用的:

8、verilog程序框架
基本设计单元是模块(C的基本单元是函数)一个模块由两个部分组成,一部分描述接口,一部分描述逻辑功能
每个verilog程序包括4个主要部分:
端口定义,IO说明,内部信号声明,功能定义

端口定义:就是block后面,括号里面那些。
IO说明:input、output
功能定义:
assign是给线网数据类型的变量赋值的一种方法。之前说了wire这个东西不能直接存储变量,是需要其他东西驱动的。

功能定义部分有三种方法:
1、assign语句
2、always语句
3、例化实例元件

这个例化其实昨天写tb文件的时候领教过了,还有一种新的方式:


以这个为例.sys_clk(sys_clk)
这个.+变量(变量)的含义就是括号外面那个变量名,是被调用的子模块中的变量名。括号里面那个变量,就是要赋值给这个“被调用的子模块中的变量名”的值。
然后来学结构语句、赋值语句、条件语句
1、结构语句
initial和always语句
initial语句在模块中只执行一次,常用于测试文件的编写(tb),用来产生仿真测试信号,或者用于对存储器变量赋初值
always语句一直在不断地重复活动,但是只有和一定的时间控制结合在一起才有用。这里的时间控制可以是沿触发,也可以是电平触发。可以是单个信号,也可以是多个信号。多个信号中间要用关键字or连接。
2、赋值语句
阻塞赋值:b=a
非阻塞赋值:b<=a

也就是说这里给出来的值是a=b=c=0
就是说这里的赋值过程是一个一个按照顺序来的
非阻塞则是并行执行的


3、条件语句
if语句

条件语句必须再过程块中使用,也就是initial和always语句。
而且上述的表达式好像并不需要针对同一个对象。比方说右边那个,表达式1可能说的是A的事,但是表达式2可以说B的事。
注意:

case语句(就类似switch)

casez:比较时不考虑表达式中的高阻值
casex:比较时不考虑高阻值和不定值
最后学状态机
状态机概念,状态机模型,状态机设计
应用场景:

状态机state machine
有限状态机(Finite state machine)在有限个状态之间按照一定规律转换的时序电路
状态机模型:
mealy状态机

这个其实就是数电里面学的那个东西。就是时序逻辑电路。状态转换图。

这个摩尔和米利其实也学过,在数电书里面讲过,我去找找——数电书262页

状态机设计:

step1:状态空间定义
两部分工作,第一部分:把各个状态用不同的二进制数编码。第二部分:定义两个reg变量:现态和次态。需要注意的是,这两个部分的位宽需要对应上。

step2:状态跳转:

在时序逻辑中必须使用非阻塞赋值
step3:下个状态判断(组合逻辑)

组合逻辑要用阻塞赋值
latch是一个锁存器,会使得最后输出的毛刺较多,影响时序分析。所以最好if和else要配对。case和default(还有endcase)配对
step4:各个状态的动作(组合逻辑)

组合逻辑,用阻塞赋值
看个例子


always @ (*) begin含义

状态机的最后可以再加一个输出寄存器(时序逻辑)
作用:

完事
晚上做做第一个实验