基础概念
- Verilog:一种硬件描述语言,用程序设计语言来描述数字电路功能
- 先有电路结构再描述
- 一个简单的hello world描述
module hello(); initial begin $display("hello world"); end endmodule
- verilog总体分为两类
- 可综合
- 综合tool可以把语言描述转换为基本的数字底层cell的描述
- 不可综合
- 综合tool不能转换为底层电路
- 可综合
- verilog设计的物理实现
- 数字ic芯片
- FPGA实现
- 数字电路设计方法学
- bottom-up:从底层cell开始,逐步进行上层搭建功能
- top-down:从顶层开发向下逐步发展设计
- 底层设计需要考虑并行性
标识符和关键字及基础数据类型
- 标识符—用于定义code中的各种名字,比如信号、module、define、parameter
- 主要构成
- 字符数字下划线
- 首字母不可以是数字
- 标识符是区分大小写的
- 关注基于含义的定义命名
- 主要构成
- 关键字—有特定含义不可当作标识符
- module/reg/wire/input/output/assign/begin-end/for/tri0/tri1等
- 注释和C语言一致
- 物理数据类型
- 线性数据:用于连续赋值语句(assign)描述组合逻辑或module间的信号连接线
- wire:线性,可综合
- tri0/tri1:带下拉/上拉电阻的线性,没有驱动会默认0/1,不可综合
- 寄存器类型:用于过程赋值语句(always, initial)描述组合逻辑或时序逻辑
- initial:只执行一次//不可综合
- always:循环执行//可综合
- reg/real/integer:寄存器数据类型
- 线性数据:用于连续赋值语句(assign)描述组合逻辑或module间的信号连接线
- 总结:
- wire只能描述组合逻辑或者线而reg可以描述组合逻辑或时序逻辑
- 除wire/tri外的其他数据类型,基本都属于寄存器,只能用于过程赋值语句
常量和变量
- 一维标量类型(常量)
- 整数型—16’d100/16’h64/16’b0110_0100
- 实数型(可综合不可用)
- 字符型(每个字符按照8bitasii码的整型存储)—“verilog"//56个bits
- 一维标量类型(变量)
- 整数型
wire [3:0] da, db;//unsigned wire [9:0] so;//signed wire [15:0] co; assign co = "ab";//16'h6162 assign da = db + 4'd1;
- 实数型—目前不可综合
- 多维标量类型(变量)
wire [3:0] array_0 [0:7];//8个4bit数组成的数组 reg [7:0] array_1[0:15][0:255]//多维数组
运算符
- 逻辑运算符
- 按bit位逻辑操作:&/|/^/~
wire [3:0] a, b ,c; wire [3:0] d0; wire d; assign a = 4'b0001; assign b = 4'b0101; assign d0 = a & b; assign d = |a;//1'b1: d = a[0] | a[1] | a[2] | a[3]
- 按整体逻辑操作:&&/||/!/==/!=
- 不论多少位,直接转换为0和1,然后仅仅用这一位进行运算
- 三目运算符
wire [31:0] a0, a1; wire sel; wire [31:0] out; assign out = (sel) ? a0 : a1;//实现多路选择器
- bit位选择[]/拼接{}
wire [4:0] a0, a1; wire [2:0] a; assign a = {a0[1:0],a1[0]};//线的排序,不需要什么面积
- 算术运算符:+/-/*/%等
- 可以灵活控制每一个变量的位宽
- 对于加法而言,比如两个3位宽相加则结果应该为4位宽
- 对于减法而言,由于不知道谁大谁小因此要加上一个符号位,比如两个3位宽相减则结果要用4位宽表示
- 总之为了结果不溢出,需要认真计算bit数
- 条件语句
- if-else—可以实现mux也可以实现触发器
- 注意单个if-else和多个if-else的电路区别
带有优先级
- case/casez/casex—并行结构—级数少
//四选一选择器的实现
input wire [1:0] din;
output reg [7:0] dout;
always @(*) begin
case(din)
2'b00: dout = 8'h01;
2'b01: dout = 8'h02;
2'b10: dout = 8'h03;
2'b11: dout = 8'h04;
endcase
end