小插曲4——Verilog HDL语言基础学习

起因

之前的小插曲1、2、3都是讲的FPGA项目经验,这次回归基础,讲一讲FPGA的编程语言,我用的时Verilog HDL。我将从定义开始讲解Verilog 语言。

Verilog HDL语言

总体结构

(1),端口定义

module 模块名(端口1,端口2,端口3……)
例如:
module test(a,b,c)
表示该模块一共有3个端口

(2),输入输出口定义

输入端口:input [n:1]端口1,端口2,端口3……端口n
输出端口:output [n:1]端口1,端口2,端口3……端口n

其中[n:1]表示端口的位宽为n,也可以写成[n-1:0]。如果没有写位宽,则默认为1,例如
input a;
output b;
a,b默认为1位

(3),内部信号声明

例如wire a\reg c;

(4),逻辑功能实现

 用assign、always语句描述,其中

 assign用于给wire型变量赋值

always用于给reg型变量赋值

(5)模块例化

<模块名字> <例化后的模块名字>(端口对应);

endmoudle

概念图如下:

词法

数值表达式

Verilog的数值并不是直接写1,2,3。因为编译器默认1,2,3为十进制数,而大部分用到的都是二进制和十六进制,所以必须将数值加以区分:格式为<位宽>‘<基数><数值>。

位宽:表示数值一共有几位;

基数:表示是什么进制,b(二进制)、d(十进制)、h(十六进制)、o(八进制)

数值:表示大小,范围根据基数来定:其中x为不定态,?/z为高阻态(不用管)

基数为b:可选0.1.x.z
基数为o:可选2.3.4.5.6.7
基数为d:可选1~9
基数为h:8.9.a.b.c.d.e.f

数据类型

1.parameter:parameter定义一个标识符代表一个常量,例如:

parameter data=1,address=8'b111111111;

2.线网——wire型数据

        相当于定义了一个接口,用于连线。输入输出信号默认定义为wire型,但要对其赋值,只能用assign语句。

定义举例:wire[32:1] emx1,emx2,emx3;
表示emx1,emx2,emx3均有32位
         wire[8:0]a;表示a为9位变量

3.寄存器——reg型数据

也相当于一个接口,一般用于寄存器的输出

reg w1 w2;表示定义w1和w2均是1位变量

运算符

算术运算符

+、-、*、/、%表示加减乘除余,和C语言中一样

关系运算符

>=、<=、<、>表示大于等于、小于等于、小于、大于。如果为真,则返回1,如果为假,则返回0。

逻辑运算符

&&、||、!表示与或非。如果为真,则返回1,如果为假,则返回0。

位运算符

&、|、~表示按位的与或非,比如两个数1111,0000。对它们两个进行一位一位的与或非。

等式运算符

==:两个等于是对两个数进行按位比较,若有对应位不相同,则返回0。若两个数的对应位均为不定态x,则直接判错。

===:若两个数中的对应位均为x,不判错。其余用法和“==”相同。

缩减运算符

缩减运算符是单目运算符,只是在位运算符的基础上做了些更改,位运算符是两个值一位一位的运算。而缩减运算符是自身的第一位与第二位运算,结果再与第三位运算,接着再与第四位运算,以此类推。

若A=4'b1001
&A=0//只有当A的每一位都为1时才为1
|A=1//只有当A的每一位都为0时才为0
并接运算符

表示将某些信号的某几位组合在一起

output [5:0]a;
input[3:0]b;
assign ab={a,[1,b[1:0]}//表示将a的6位和b的低两位拼接在一起
a为高位,b[0]为最低位

描述语句

assign
assign sum=add1+add2

assign语句不可以重复赋值

assign sum=a-b;
assign sum=a+b;//会导致程序报错
分支语句

if-else

if()
begin
……
end
else
    begin
    ……
    end

case

case(敏感信号)
敏感信号的值:情况;
敏感信号的值:情况;
敏感信号的值:情况;
敏感信号的值:情况;
敏感信号的值:情况;
default:情况;
endcase

测试仿真——testbench代码编写

如果我们身边没有FPGA的实物,但我们又想看一下实验效果,这时就可以利用Modesim进行软件仿真,仿真的代码称为——testbench代码。代码总体结构如下:

1.时间尺度指令

`timescale 1ns/100ps

2.模块名字

module 模块名字(一般是程序代码+_top);

在testbench中不需要定义输入input和输出output端口,因为仿真代码仅仅是用来给程序设置电平信号的。

3.信号的声明和定义

在程序中如果定义的是输出reg,则在这里定义成wire;

在程序中如果定义的是输出wire,则在这里定义成reg.

这就像是32中的TX-RX、RX-TX

4.初始化

在仿真代码里面如果要模拟时钟信号、输入信号,则就在初始化里面定义

Initual begin
#5 A=1;//5个时间单位后执行A为高电平指令
#5 A=0;//5个时间单位后,执行A为低电平指令
……
end

5.定时赋值

手动设置时钟的翻转,通常是用always来实现

always  #5 clk=~clk;
//每隔5个时间单位就翻转一次时钟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值