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>

示例解释
1232位十进制数
8’b1100_00018位二进制数
64’hff0164位十六进制数
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最常用的寄存器类型
integer32位有符号整数
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 非阻塞

阻塞赋值(=):

  • 右边求值后立即赋值给左边
  • 同一块内语句顺序执行
  • 用于组合逻辑

非阻塞赋值(<=):

  • 考察时刻对所有非阻塞语句求值
  • 在考察时刻之后统一赋值
  • 用于时序逻辑

重要规则

  1. 组合逻辑尽量用阻塞赋值
  2. 时序逻辑必须用非阻塞赋值
  3. 同一always块不要混用两种赋值
  4. 不同时序和组合逻辑写到不同always块
  5. 不要在多个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
  • 使用非阻塞赋值描述时序逻辑
  • 注意赋值顺序:低位先移入

组合逻辑设计

  • 使用阻塞赋值
  • 能有效减少锁存现象

可综合代码规范

推荐做法

  1. 时序逻辑用非阻塞赋值
  2. 组合逻辑用阻塞赋值
  3. 分离时序和组合逻辑到不同always块
  4. 避免在多always块中对同一变量赋值
  5. 使用显式的复位逻辑

避免的做法

  1. 混合使用阻塞和非阻塞赋值
  2. 使用不可综合的系统任务($display等)
  3. 依赖隐式锁存
  4. 使用条件不充分的多路选择

关联笔记