一、电路设计#
一、逻辑门#
- 与门
- 或门
- 非门
- 异或门
- 同或门
二、正逻辑和负逻辑#
- 正逻辑中高电压是1,低电压是0
- 负逻辑中高电压是0,高电压是1
二、Verilog语言#
1.基础语法#
(1)数值表示#
逻辑数值#
- 0:低电平,逻辑0
- 1:高电平,裸机1
- x或者X:状态未知
- z或者Z:高阻,上拉为1,下拉为0。
整数数值#
整数数值前面可以指明位宽,可以声明进制。
4'b1011 //表示4bit的二进制数101132'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
- 实数:real
- 时间:time,调用系统函数
$time获得当前的仿真时间
变量并不代表电路中的信号,只是用来记录一些值。
数组#
可以声明任意维数的数组,数组中的每一个元素必须是一个标量或者向量。
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_precisiontime_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#
- 用于组合逻辑
- 用于wire类型的信号
- 赋值是连续的,只要输入信号发生改变输出信号就立刻跟着改变
- 一般用于逻辑运算或连接不同模块的信号
assign a=b;always#
- 用于时序逻辑
- 赋值通常是给reg类型的
- 只有在条件满足时,才会触发
always @(posedge clk) begin reg_a = 0; reg_b = 1;end//在clk的上升沿触发阻塞赋值和非阻塞赋值
- 阻塞赋值 = ,从前往后依次赋值
- 非阻塞赋值 <= ,所有的赋值语句并行进行