Skip to content

FPGA入门

· 7 min

一、电路设计#

一、逻辑门#

二、正逻辑和负逻辑#

二、Verilog语言#

1.基础语法#

(1)数值表示#

逻辑数值#

整数数值#

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

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

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

实数数值#

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

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

字符串#

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

(2)数据类型#

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

线网Wire#

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

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

寄存器Reg#

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

reg flag;

向量#

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

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

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

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

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

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

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

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

寄存器型变量#

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

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

数组#

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

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

存储器#

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

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

参数#

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**编译指令将时间单位和实际时间相关联。

`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#

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

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

(4)电路逻辑描述#

assign#

assign a=b;

always#

always @(posedge clk) begin
reg_a = 0;
reg_b = 1;
end
//在clk的上升沿触发

阻塞赋值和非阻塞赋值