FPGA培训资料-Verilog基础与电路设计
---
title: "FPGA培训资料-Verilog基础与电路设计"
source: "/日常学习资料/FPGA培训资料/培训讲义/2.1.verilog基础与电路设计.pdf"
original_path: "/日常学习资料/FPGA培训资料/培训讲义/2.1.verilog基础与电路设计.pdf"
author: "FPGA培训资料"
date: "2012-07"
size: "3.73 MB"
pages: 93
status: done
method: PDF文本提取
---核心内容
Altera FPGA培训中关于Verilog HDL的基础语法、可综合设计风格和设计实例的完整教程。
Verilog概述
基本定义
- 硬件描述语言(HDL):用于描述数字电路
- 层次化描述能力:支持从系统级到门级的多级抽象
- 历史:1984年研发,1995年成为IEEE 1364标准
设计层次
| 层次 | 说明 | 适用场景 |
|---|---|---|
| 系统级 | 行为级描述,不涉及具体实现 | 系统仿真、接口开发 |
| 行为级 | 描述功能行为 | 算法验证 |
| RTL级 | 寄存器传输级,描述数据流和寄存器 | ASIC/FPGA设计 |
| 门级 | 门级原语和连线 | 时序仿真 |
设计流程
代码编写 → 仿真(功能/时序) → 综合 → 验证 → 下载
↓ ↓ ↓ ↓ ↓
RTL描述 检查逻辑错误 转化为 确认工作 下载到FPGA
网表
Verilog vs VHDL
- Verilog:C语言风格,语法简洁,工业界主流
- VHDL:Pascal风格,语法严格,军工航天常用
- 趋势:Verilog/SystemVerilog逐渐成为主流
设计人员角色
| 角色 | 职责 |
|---|---|
| ASIC/FPGA工程师 | 编写可综合代码 |
| 高抽象级系统工程师 | 系统仿真、接口开发 |
| 硬件测试工程师 | 编写测试环境 |
| 单元建模工程师 | 建模仿真和设计单元 |
Verilog基础语法
标识符规则
- 有效开头:字母(a-z, A-Z)或下划线(_)
- 后续字符:字母、数字、$、_
- 最大长度:1023字符
- 大小写敏感:sel ≠ SEL
- 示例:
- 有效:shift_reg_a、busa_index、_bus3
- 无效:34net(数字开头)、ab_net(含)
常量定义
格式:<size>'<base><value>
| 示例 | 解释 |
|---|---|
| 12 | 32位十进制数 |
| 8’b1100_0001 | 8位二进制数 |
| 64’hff01 | 64位十六进制数 |
| 3’b1010_1101 | 高位舍去,相当于3’b101 |
| 32’bz01x | 高位用z补齐 |
| 6.3 | 十进制小数 |
| 4.1E3 | 科学计数法4100 |
数值进制
- b:二进制
- o:八进制
- d:十进制(缺省)
- h:十六进制
运算符
位运算符
&按位与|按位或~按位非^按位异或~^/^~按位同或
算术运算符
+加、-减、*乘、/除、%模
移位运算符
>>逻辑右移<<逻辑左移
关系运算符
><>=<=
相等运算符
==逻辑相等(x/z返回x)!=逻辑不等===严格等于(x/z也参与比较)!==严格不等
三元运算符
cond_expr ? true_expr : false_expr
数据模型
Verilog采用四值逻辑系统:0、1、x(不定)、z(高阻)
数据类型
Net类型(线网)
表示物理连接,需要持续驱动:
| 类型 | 功能 |
|---|---|
| wire, tri | 标准内部连接线 |
| supply1, supply0 | 电源、地 |
| wor, trior | 多驱动源线或 |
| wand, triand | 多驱动源线与 |
| trireg | 能保存电荷的net |
| tri1, tri0 | 无驱动时上拉、下拉 |
Register类型(寄存器)
保持值直到被赋新值:
| 类型 | 功能 |
|---|---|
| reg | 最常用的寄存器类型 |
| integer | 32位有符号整数 |
| real | 双精度浮点变量 |
| time, realtime | 时间变量 |
参数(parameter)
parameter WIDTH = 8;
parameter DELAY = #2;- 局部有效,只在当前模块中
- 常用于定义宽度、延时等常量
存储器数组
reg [MSB:LSB] mem_name[first_addr:last_addr];- 只能通过索引寻址,不支持多维数组
- 常用于描述ROM、RAM
模块结构
module <module_name>(<port_list>);
input <port_list>;
output <port_list>;
inout <port_list>;
// 模块描述
endmodule示例:2选1多路选择器
module MUX2_1 (out, a, b, sel);
output out;
input a, b, sel;
assign out = sel ? b : a;
endmodule示例:半加器
module half_adder (sum, carry, a, b);
output sum, carry;
input a, b;
xor (sum, a, b);
and (carry, a, b);
endmodule赋值语句
连续赋值(assign)
assign #del <id> = <expr>;- 用于组合逻辑
- LHS必须是net型变量
过程赋值
用于always/initial块中:
| 类型 | 语法 | 用途 |
|---|---|---|
| 阻塞赋值 | = | 组合逻辑 |
| 非阻塞赋值 | <= | 时序逻辑 |
阻塞 vs 非阻塞
阻塞赋值(=):
- 右边求值后立即赋值给左边
- 同一块内语句顺序执行
- 用于组合逻辑
非阻塞赋值(<=):
- 考察时刻对所有非阻塞语句求值
- 在考察时刻之后统一赋值
- 用于时序逻辑
重要规则
- 组合逻辑尽量用阻塞赋值
- 时序逻辑必须用非阻塞赋值
- 同一always块不要混用两种赋值
- 不同时序和组合逻辑写到不同always块
- 不要在多个always块中对同一变量赋值
设计实例
移位寄存器
module SHIFTREG (CLK, RST, IN, D);
input CLK, RST;
input [7:0] IN;
output [7:0] D;
always@(posedge CLK or posedge RST) begin
if(RST == 1)
D <= IN;
else
D <= {D[0], D[7:1]};
end
endmodule- 使用非阻塞赋值描述时序逻辑
- 注意赋值顺序:低位先移入
组合逻辑设计
- 使用阻塞赋值
- 能有效减少锁存现象
可综合代码规范
推荐做法
- 时序逻辑用非阻塞赋值
- 组合逻辑用阻塞赋值
- 分离时序和组合逻辑到不同always块
- 避免在多always块中对同一变量赋值
- 使用显式的复位逻辑
避免的做法
- 混合使用阻塞和非阻塞赋值
- 使用不可综合的系统任务($display等)
- 依赖隐式锁存
- 使用条件不充分的多路选择