FPGA入门

HarderHeng Lv5

一、电路设计

一、逻辑门

  • 与门
  • 或门
  • 非门
  • 异或门
  • 同或门

二、正逻辑和负逻辑

  • 正逻辑中高电压是1,低电压是0
  • 负逻辑中高电压是0,高电压是1

二、Verilog语言

1.基础语法

(1)数值表示

逻辑数值

  • 0:低电平,逻辑0
  • 1:高电平,裸机1
  • x或者X:状态未知
  • z或者Z:高阻,上拉为1,下拉为0。

整数数值

整数数值前面可以指明位宽,可以声明进制

1
2
4'b1011 //表示4bit的二进制数1011
32'h1234_abcd //表示32bit的16进制数1234_abcd,加下划线可以提高可读性。

如果是负数,则在整个数字最前面加一个负号。

实数数值

实数数值可以用两种方法表示,十进制科学计数法

1
2
123.123 //十进制表示法
123123e-3 //科学计数法

字符串

字符串中不能够包含回车符号,不能换行书写。一个字符串被认为是一个单字节的序列。

(2)数据类型

最常用的数据类型是线网Wire寄存器Reg

线网Wire

表示硬件单元之间的物理连接,其值由连接的器件的输出端连续驱动。如果没有驱动单元连接到wire型变量,缺省值一般为”Z”。

1
2
3
wire interrupt;
wire flag;
wire gnd = 1b'0;

寄存器Reg

寄存器用来表示存储单元,会一直保持原有的数值直到被某一个输入给改写。

1
reg flag;

向量

在线网和寄存器的位宽大于1的时候,可以被声明成向量的形式。

1
2
3
wire [7:0] data;
reg [3:0] alu;
reg [7:6] counter

声明成向量之后,我们可以对其中的某几位进行选择使用。

Verilog还支持指定bit位后固定位宽的向量域选择访问

1
2
3
A = data[31-:8];
A = data[31:24];
A = data[24+:8];

上述的三种表达式是等价的,都表示data的24位到31位。

对数据进行组合形成新的向量时,需要使用大括号。

1
2
wire [31:0] temp;
temp = {byte1[0:7], byte2[8:31]};

寄存器型变量

整数,实数,时间等数据类型属于寄存器类型。

  • 整数:integer
  • 实数:real
  • 时间:time,调用系统函数$time获得当前的仿真时间

变量并不代表电路中的信号,只是用来记录一些值。

数组

可以声明任意维数的数组,数组中的每一个元素必须是一个标量或者向量。

1
2
integer int[7:0];
reg [3:0] counter[7:0][3:0];

存储器

存储器变量就是一种寄存器数组,可以用来描述RAM或者ROM的行为。

1
reg [7:0] RAM[0:1023]; //1kb的存储器

参数

1
parameter data_width = 10'd32;

参数用来表示常量,只能被赋值一次。

局部参数用localparam来声明,作用和用法和parameter相同,区别在于它不能够被赋值。

(3)编译指令

`define ,`undef

**`define**用于文本替换,和C语言中的#define类似,一旦被编译在整个编译过程中都会有效。

**`undef**用于取消之前的`define。

`ifdef,`ifndef,`elsif,`else,`endif

都是条件编译指令,和C语言中的条件编译基本一致。

`include

**`include**可以在编译时将一个Verilog文件包含在另一个文件中,类似于C语言中的#include

`timescale

在Verilog模型中,时延有具体的单位时间表述,用**`timescale**编译指令将时间单位和实际时间相关联。

1
`timescale time_unit / time_precision

time_unit是时间单位,time_precision是时间精度,时间精度不能超过时间单位的大小。

`timescale**会一直生效直到遇到另一个**`timescale指令或者**`resetall**指令。

多个模块带有**`timescale**时,会将所有的时延精度替换为最小的那个时延精度。

`default_nettype

设置默认的变量类型。如果没有给一个变量定义类型,则默认可以是wire、reg、none

设置为none的时候,不允许出现未定义类型的变量,可以规范代码编写。

`resetall

将所有编译指令重新设置为默认值。**`resetall**可以使得缺省连线类型为线网类型。

`resetall**加到模块最后,可以将当前的**`timscale取消,防止传递到下一个模块。

`unconnected_drive,`nounconnected_drive

在这两个编译指令中间的,任何未连接的输入端口,都会被默认设置为正偏电路状态或者反偏电路状态。

1
2
3
4
5
6
7
8
9
`unconnected_drive pull1
. . .
/ *在这两个程序指令间的所有未连接的输入端口为正偏电路状态(连接到高电平) * /
`nounconnected_drive

`unconnected_drive pull0
. . .
/ *在这两个程序指令间的所有未连接的输入端口为反偏电路状态(连接到低电平) * /
`nounconnected_drive

(4)电路逻辑描述

assign

  • 用于组合逻辑
  • 用于wire类型的信号
  • 赋值是连续的,只要输入信号发生改变输出信号就立刻跟着改变
  • 一般用于逻辑运算或连接不同模块的信号
1
assign a=b;

always

  • 用于时序逻辑
  • 赋值通常是给reg类型的
  • 只有在条件满足时,才会触发
1
2
3
4
5
always @(posedge clk) begin
reg_a = 0;
reg_b = 1;
end
//在clk的上升沿触发

阻塞赋值和非阻塞赋值

  • 阻塞赋值 = ,从前往后依次赋值
  • 非阻塞赋值 <= ,所有的赋值语句并行进行
  • Title: FPGA入门
  • Author: HarderHeng
  • Created at : 2024-09-04 14:35:35
  • Updated at : 2025-01-28 17:17:23
  • Link: https://harderheng.life/2024/09/04/FPGA入门/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments