#FPGA#Verilog入门

参考教程:
        Verilog教程-夏宇闻
因为Verilog和C语言很像,所以这个入门只是记录一下Verilog的特殊点等,具体可以去看上面的参考教程

数据类型及常量、变量

  • 数据类型
    • 表述数字电路中数据存储和传送单元
    • 共19种数据类型
      • 4种最基本:integer,parameter,reg,wire
      • 其他:large,medium,scalared,small,time,tri,tri0,tri1,triand,trior,trireg,vectored,ward,wor
  • 常量
    • 整数型常量
      • 有二进制、十进制、十六进制、八进制
      • <位宽>'<进制><数字>
      • 缺省位宽,则位宽由机器系统决定;缺省进制,则为十进制
    • x和z值
      • x表示不定值,z表示高阻值
      • 具有扩展性(8'b1x=8'b0000_001x)
      • ?是z的另一种表示符号,建议在case语句中使用?表示高阻态
    • 负数
    • parameter常量(符号常量)
      • 用parameter来定义一个标识符,代表一个常量——称为符号常量
      • parameter 参数名1=表达式,参数名2=表达式,……
      • 用来定义延迟时间变量宽度
      • 参数是本地的,其定义只在本模块内有效
      • 在模块或实例引用时,可通过参数传递改变在被引用模块或实例中已定义的参数
        • defparamdefparam 例化模块名.参数名1=常数表达式,例化模块名.参数名2=常数表达式,……;
        • #被引用模块名# (参数1,参数2……) 例化模块名 (端口列表);
  • 变量
    • 数据类型有19种,常用的有三种
    • 网络型nets
      • 输出始终随输入变化而变化的变量
      • 不能存储值
      • 最常用:wire ,常用来表示以assign语句赋值的组合逻辑信号
    • 寄存器型register
      • 对应具有状态保持作用的电路元件(如触发器、寄存器等),常用来表示过程块语句(如initial,always,task,function)内的指定信号
      • 需要明确赋值,并在被重新赋值前一直保持原值
      • 必须通过过程赋值语句赋值,不能通过assign语句
      • reg
        • 常代表触发器,但不一定就是触发器(也可以是组合逻辑信号)
        • reg[n-1:0] 数据名1,数据名2,……,数据名m;reg[n:1] 数据名1,数据名2,……,数据名m;
      • integer:32位带符号整数型变量
      • real:64位带符号实数型变量
      • time:无符号时间变量
    • 数组memory
      • 由若干个相同宽度的reg型向量构成的数组
      • 可描述RAM、ROM和reg文件

运算符及表达式

  • 算术运算符
    在这里插入图片描述
  • 逻辑运算符
    在这里插入图片描述
  • 关系运算符
    在这里插入图片描述
  • 等式运算符
    在这里插入图片描述
  • 缩减运算符
    在这里插入图片描述
  • 条件运算符
    在这里插入图片描述
  • 位运算符
    在这里插入图片描述
  • 移位运算符
    在这里插入图片描述
  • 位拼接运算符
    在这里插入图片描述
  • 运算符优先级
    在这里插入图片描述

结构说明语句

  • initial说明语句——只执行一次
    • 在仿真的初始状态对各变量进行初始化
    • 在测试文件中生成激励波形作为电路仿真信号
    initial
    	begin
    		语句1;
    		语句2;
    		……
    		语句n;
    	end
    
  • always说明语句——不断重复执行,直至仿真结束
    • 被赋值的只能是register型变量
    • 每个always块在仿真一开始便执行
    • always <时序控制><语句>
    • 必须与一定的时序控制结合在一起在有用,否则,易形成仿真死锁
    • 当always块有多个敏感信号时,一定要采用if-else if语句,而不能采用并列的if语句,否则,易造成一个寄存器有多个时钟驱动
    • 通常采用异步清零
  • task说明语句——可在程序模块中一处或多处调用
    • 用户定义任务
    • 对一些信号进行一些运算并输出多个结果
    • 定义和调用必须在一个module模块内
    • 可以调用其他任务和函数
    任务定义:
    	task <任务名>;
    		端口及数据类型声明语句;
    		其他语句;
    	endtask
    
    任务调用:
    	<任务名> (端口1,端口2,……);
    
  • function说明语句——可在程序模块中一处或多处调用
    • 用户定义函数
    • 通过返回一个用于某表达式的值,来响应输入信号。适用于对不同变了采取同一运算操作
    • 可以在其他模块调用
    • 其定义不能包含任何时间控制语句
    • 不能调用任务
    • 定义时至少有一个输入参量,且不能有任何输出或输入/输出双向变量
    • 函数定义中必须有一条赋值语句,给函数中一个内部寄存器赋以函数的结果值,该内部寄存器与函数同名
    函数定义
    	function <返回值位宽或类型说明> 函数名;
    		端口声明;
    		局部变量定义;
    		其他语句;
    	endfuction
    	
    函数调用
    	<函数名>(<表达式> <表达式>)
    

在这里插入图片描述

编译预处理语句

  • define
  • include
  • timescale
    • 定义跟在该命令后模块时间单位和时间精度
    • timescale <时间单位>/<时间精度>
    • 时间精度值不能大于时间单位值,且必须都是整数

基本结构

  • Verilog程序由模块构成,模块可以进行层次嵌套
  • 每个Verilog源文件只能有一个顶层模块,其他为子模块
  • 逻辑功能定义
    • 在Verilog中有三种方法可以描述电路的逻辑功能
    • 1.用assign赋值语句
      • assign x=(b&~c);
      • 常用于描述组合逻辑
    • 2.用元件例化(instantiate)
      • and myand3(f,a,b,c);
      • 元件例化即是调用Verilog提供那个的元件
      • 包括元件例化和模块元件例化
      • 每个实例元件名字必须唯一
      • 例化元件名也可以省略
    • 3.always块语句
      • 结构说明语句
      • 常用于描述时序逻辑 ,也可以描述组合逻辑
      always @(posedge clk)//每当时钟上升沿到来时执行一遍块内语句
      	begin
      		if(load)
      			out=data;//同步预置数据
      		else
      			out=data+1+cin;//加1计数
      	end
      
  • 其大概模板如下:
module <顶层模块名>(<输入输出端口列表>)
	output 输出端口列表;
	input 输入端口列表;
//(1)使用assign语句定义逻辑功能
	wire 结果信号名;
	assign <结果信号名>=表达式;
//(2)使用always块定义逻辑功能
	always@(<敏感信号表达式>)
		begin
			//过程复制语句
			//if语句
			//case语句
			//while,repeat,for循环语句
			//task,function调用
		end
//(3)元件例化
	<module_name><instance_name>(<port_list>);//模块元件例化
	<gate_type_keyword><instance_name>(<port_list>)//门元件例化
endmodule

关键字

在这里插入图片描述
在这里插入图片描述

Verilog的描述

  • 系统级:用高级语言结构(如case语句)实现的设计模块外部性能的模型
  • 算法级:用高级语言结构实现的设计算法模型(写出逻辑表达式)
  • RTL级:描述数据在寄存器之间流动和如何处理这些数据
  • 门级:描述逻辑门以及逻辑门之间连接的模型
  • 开关级:描述器件中三极管和存储节点及其之间连接的模型

门级描述

  • 结构描述,最直观
  • 关键字有26个,常用的有:not,and,nand,or,nor,xor,xnor,buf,(各种三态门)bufif1,bufif0,notif1,notif0
  • 调用语法:门类型关键字 <例化的门名称>(<端口列表>);

设计技巧

  • 一个变量不能在多个always块中被赋值
  • always块语句中,当敏感信号为两个以上的时钟边沿触发信号时,应注意不要使用多个if语句,以免因逻辑关系不清晰而导致编译错误(if-else)
  • 当输出信号为总线信号是,一定要在I/O说明中指出其位宽,否则在生成逻辑信号时,输出信号被误认为是单个信号
  • 当要用到计数器时,一定要根据计数最大值事先计算好所需的位宽
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值