verilog基础教程

verilog基础教程

欢迎访问作者博客sakuraの绘梨衣

1 数值表示

1. 逻辑电平

0:逻辑0或假

1:逻辑1或真

x或X:未知

z或Z:高阻

2. 数字

  1. 十进制:8’d1(负数:-8’d1)
  2. 二进制:8’b0(8’b0000_0000)
  3. 八进制:6’o0
  4. 十六进制:8’h0(8’h00)

3. 字符串

每个字符用单字节ASCII码表示

reg [5*8-1:0] str;
initial begin
    str = "hello";
end

2 数据类型

1. wire(线网)

  1. 定义:表示硬件单元之间的物理连线,由其连接的器件输出端连续驱动
  2. 赋值:不能过程赋值(initial,always),只能连续赋值(assign),即需要驱动
  3. 连接:用于模块间的连接,input必须是wire类型
wire clk;

2. reg(寄存器)

  1. 定义:表示存储单元
  2. 赋值:不需要驱动,可在任何时候可以赋值
reg addr

3. 向量

字面意思,如下定义8bit寄存器

reg [7:0] addr

4. parameter

相当于常量

parameter SIZE 2'd10

3 操作符

优先级由高到低为

操作符操作符号
单目运算+ - ! ~
乘、除、取模* / %
加减+ -
移位<< >>
关系< <= > >=
等价== != === !===
归约& ~&
^ ~^
| ~|
逻辑&&
||
条件?:

特殊操作符:{}

拼接操作符,可以拼接多个操作数为一个向量

data = {2'b01, 1'b0, 3'b101}
// data = 6'b010101

4 编译指令

  1. `define:类似C语言的#define,定义一个宏
  2. `undef:取消一个宏
  3. `include:类似C语言的#include,引入一个.v文件
  4. `timescale:定义时延、仿真的单位和精度
  5. `resetall:如其名,重置所有编译指令为缺省值

5 连续赋值

用于组合逻辑设计

对wire类型变量进行赋值,一旦设定了一个连续赋值后,每当等号右边的任何一个值发生变化,赋值将自动重新赋值,即wire每时每刻都等于右边的表达式结果

如下,Z一直等于X&Y

wire X, Y, Z
assign Z = X & Y

6 时延

可以用#+时延秒数实现时延

assign #10 Z = X & Y
// 当X或Y发生变化后会时延10秒才会赋值给Z

7 过程结构

1. initial

只执行一次,一帮用于给reg赋初值

reg clk;
reg [3:0] data;

initial begin
	clk = 0;
	data = 4'b0001;
end

2. always

重复执行,只要触发了设定的条件就执行一次

reg clk;

initial begin
	clk = 0;
end

// 表示每隔1秒clk就取反
always #1 begin
	clk = ~clk;
end

reg clk;
reg rst;

initial begin
	clk = 0;
	rst = 0;
end

// 表示每隔1秒clk就取反
always #1 begin
	clk = ~clk;
end

// 表示每当clk处于上升沿就让rst取反
always @(posedge clk) begin
	rst = ~rst;
end

注意

  1. initial不能与always嵌套嵌套
  2. 每个过程结构快都是并行执行,即initial与always是同时开始的
  3. 每个过程结构块内是顺序执行

8 过程赋值

1. 过程赋值与连续赋值

  1. 过程赋值:在initial或always块里的赋值,可以描述组合逻辑或时序逻辑,对象一般为寄存器
  2. 连续赋值:一般是assign关键字标志的赋值,用于描述组合逻辑,对象一般是wire

2. 阻塞赋值与非阻塞赋值

  1. 阻塞赋值:用=赋值,顺序执行,会阻塞
  2. 非阻塞赋值:用<=赋值,并行执行,不会阻塞

3. 避免竞争

如下例子,由于两个always块同时执行,使用阻塞赋值会导致两个对寄存器的操作竞争,使用非阻塞赋值则可以实现交换两个寄存器的值

// 竞争
always @(posedge clk) begin
    a = b ;
end
 
always @(posedge clk) begin
    b = a;
end

// 不竞争,结果是交换两个寄存器的值
always @(posedge clk) begin
    a <= b ;
end
 
always @(posedge clk) begin
    b <= a;
end

9 时序控制

1. 时延控制

用时延#10实现时延控制

2. 事件控制

事件一般是指某个reg或者wire发生变化,事件控制用@或wait触发

  1. 边沿触发事件控制:

一般事件:

  • 关键字 posedge 指信号发生边沿正向跳变
  • negedge 指信号发生负向边沿跳变
  • 未指明跳变方向时,则 2 种情况的边沿变化都会触发
  • 如果有多个,任何一个都可以触发
  • *可以表示语句块中所有变量
always @(posedge clk) begin
	data = 1'b0;
end

always @(negedge clk) begin
	data = 1'b1;
end

always @(clk) begin
	data = 1'b0;
end

// 等价于上一个
always @(posedge clk, negedge clk) begin
	data = 1'b0;
end

// 当语句块中任何变量变化时都触发,A、B、C任一变化都触发
always @(*) begin
	Z = A | (B & C);
end

命名事件:命名事件用event关键字,用->触发,用法不好解释,看例子

event reset;
always @(posedge clk) begin
        -> reset;
end

//触发,重置data
always @(reset) begin
    data = 1'b0;
end

  1. 电平敏感事件控制:用wait等待某一个信号为真
initial begin
	// 等待start_signal
	wait (start_signal);
	data = 1'b0;
end

10 语句块

1. 顺序块

用begin与end标识,顺序块中语句顺序执行,但用非阻塞赋值可以实现并行执行

2. 并行块

用fork和join标识,即使语句是阻塞赋值,也会强制并行执行

3. 块命名

module test();

	reg data;

	// 命名为init
    initial begin: init
        data = 0'b0;
    end
    
    // 访问
    test.init.data = 0'b1;
    // 禁用该块
    disable init;

endmodule

11 条件语句

if,else

reg select;
reg clk;
reg data;

if (clk) begin

	if (select) begin
		data = 1'b0;
	end
	else begin
		data = 1'b1;
	end

end

12 多路分支

case

always @(*) begin
	case(select)
		2'b00:	begin
					data = a;
				end
		2'b01:	begin
					data = b;
				end
		2'b10:	begin
					data = c;
				end
		default:begin
					data = d;
				end
	endcase
end

13 循环

注意,循环只能在initial与always块中使用

1. while

initial begin
	counter = 2'd0;
	while (counter <= 10) begin
		#10;
		counter = counter + 1'd1;
	end
end

2. for

// 整形变量i,之前没说
integer i;

initial begin
    counter = 2'd0 ;
    for (i = 0; i <= 10; i = i+1) begin
        #10;
        counter = counter + 1'd1;
    end
end

3. repeat

固定次数

initial begin
    counter = 2'd0;
    repeat (10) begin  //重复10次
        #10;
        counter = counter + 1'd1 ;
    end
end

4. forever

永久执行,可以用来做一个时钟

initial begin
    clk = 0;
    forever begin
        clk = ~clk;
        #5;
    end
end

// 其实等价于
always #5 begin
	clk = ~clk;
end

14 模块

  1. 有点像class,但含义不同
  2. 用input表示模块输入,input只能是wire类型,用output表示模块输出,output可以是reg或wire

一个全加器模块

module full_adder_1bit(
    input wire A,
    input wire B,
    input wire Cin,
    output wire F,
    output wire Cout
);

    assign F = A^B^Cin;
	assign Cout = (A&B) | ((A^B)&Cin);

endmodule

15 模块例化

  1. 有点像class对象实例化,但含义不同
  2. 对接input的可以是wire或reg,对接output的只能是wire
  3. genvar是一个特殊的变量类型,专门用于generate语句中的循环控制。genvar只能在编译时赋值,并且只能在generate语句中使用
  4. generate用来重复生成实例(注意,不能用for循环直接生成实例,需要用generate包起来)

一个32位加法器模块,用上述全加器实例化实现,注意一下接口写法

module full_adder_32bit(
    input wire [31:0] A,
    input wire [31:0] B,
    input wire Cin,
    output wire [31:0] F,
    output wire Cout
);

    wire [31:0] Cout_tmp;
    full_adder_1bit u_full_adder_1bit(
        .A      (A[0]),
        .B      (B[0]),
        .Cin    (Cin),
        .F      (F[0]),
        .Cout   (Cout_tmp[0])
    );

    genvar i;
    generate
        for (i = 1; i <= 31 ; i = i+1) begin
            full_adder_1bit u_full_adder_1bit(
                .A      (A[i]),
                .B      (B[i]),
                .Cin    (Cout_tmp[i-1]),
                .F      (F[i]),
                .Cout   (Cout_tmp[i])
            );
        end
    endgenerate

    assign Cout = Cout_tmp[31];

endmodule

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
目 录 译者序 前言 第1章 简介 1 1.1 什么是Verilog HDL? 1 1.2 历史 1 1.3 主要能力 1 第2章 HDL指南 4 2.1 模块 4 2.2 时延 5 2.3 数据流描述方式 5 2.4 行为描述方式 6 2.5 结构化描述形式 8 2.6 混合设计描述方式 9 2.7 设计模拟 10 第3章 Verilog语言要素 14 3.1 标识符 14 3.2 注释 14 3.3 格式 14 3.4 系统任务和函数 15 3.5 编译指令 15 3.5.1 `define和`undef 15 3.5.2 `ifdef、`else 和`endif 16 3.5.3 `default_nettype 16 3.5.4 `include 16 3.5.5 `resetall 16 3.5.6 `timescale 16 3.5.7 `unconnected_drive和 `nounconnected_drive 18 3.5.8 `celldefine 和 `endcelldefine 18 3.6 值集合 18 3.6.1 整型数 18 3.6.2 实数 19 3.6.3 字符串 20 3.7 数据类型 20 3.7.1 线网类型 20 3.7.2 未说明的线网 23 3.7.3 向量和标量线网 23 3.7.4 寄存器类型 23 3.8 参数 26 第4章 表达式 28 4.1 操作数 28 4.1.1 常数 28 4.1.2 参数 29 4.1.3 线网 29 4.1.4 寄存器 29 4.1.5 位选择 29 4.1.6 部分选择 29 4.1.7 存储器单元 30 4.1.8 函数调用 30 4.2 操作符 30 4.2.1 算术操作符 31 4.2.2 关系操作符 33 4.2.3 相等关系操作符 33 4.2.4 逻辑操作符 34 4.2.5 按位操作符 35 4.2.6 归约操作符 36 4.2.7 移位操作符 36 4.2.8 条件操作符 37 4.2.9 连接和复制操作 37 4.3 表达式种类 38 第5章 门电平模型化 39 5.1 内置基本门 39 5.2 多输入门 39 5.3 多输出门 41 5.4 三态门 41 5.5 上拉、下拉电阻 42 5.6 MOS开关 42 5.7 双向开关 44 5.8 门时延 44 5.9 实例数组 45 5.10 隐式线网 45 5.11 简单示例 46 5.12 2-4解码器举例 46 5.13 主从触发器举例 47 5.14 奇偶电路 47 第6章 用户定义的原语 49 6.1 UDP的定义 49 6.2 组合电路UDP 49 6.3 时序电路UDP 50 6.3.1 初始化状态寄存器 50 6.3.2 电平触发的时序电路UDP 50 6.3.3 边沿触发的时序电路UDP 51 6.3.4 边沿触发和电平触发的混合行为 51 6.4 另一实例 52 6.5 表项汇总 52 第7章 数据流模型化 54 7.1 连续赋值语句 54 7.2 举例 55 7.3 线网说明赋值 55 7.4 时延 55 7.5 线网时延 57 7.6 举例 57 7.6.1 主从触发器 57 7.6.2 数值比较器 58 第8章 行为建模 59 8.1 过程结构 59 8.1.1 initial 语句 59 8.1.2 always语句 61 8.1.3 两类语句在模块中的使用 62 8.2 时序控制 63 8.2.1 时延控制 63 8.2.2 事件控制 64 8.3 语句块 65 8.3.1 顺序语句块 66 8.3.2 并行语句块 67 8.4 过程性赋值 68 8.4.1 语句内部时延 69 8.4.2 阻塞性过程赋值 70 8.4.3 非阻塞性过程赋值 71 8.4.4 连续赋值与过程赋值的比较 72 8.5 if 语句 73 8.6 case语句 74 8.7 循环语句 76 8.7.1 forever 循环语句 76 8.7.2 repeat 循环语句 76 8.7.3 while 循环语句 77 8.7.4 for 循环语句 77 8.8 过程性连续赋值 78 8.8.1 赋值—重新赋值 78 8.8.2 force与release 79 8.9 握手协议实例 80 第9章 结构建模 83 9.1 模块 83 9.2 端口 83 9.3 模块实例语句 83 9.3.1 悬空端口 84 9.3.2 不同的端口长度 85 9.3.3 模块参数值 85 9.4 外部端口 87 9.5 举例 89 第10章 其他论题 91 10.1 任务 91 10.1.1 任务定义 91 10.1.2 任务调用 92 10.2 函数 93 10.2.1 函数说明部分 93 10.2.2 函数调用 94 10.3 系统任务和系统函数 95 10.3.1 显示任务 95 10.3.2 文件输入/输出任务 97 10.3.3 时间标度任务 99 10.3.4 模拟控制任务 99 10.3.5 定时校验任务 100 10.3.6 模拟时间函数 101 10.3.7 变换函数 102 10.3.8 概率分布函数 102 10.4 禁止语句 103 10.5 命名事件 104 10.6 结构描述方式和行为描述方式的 混合使用 106 10.7 层次路径名 107 10.8 共享任务和函数 108 10.9 值变转储文件 110 10.9.1 举例 111 10.9.2 VCD文件格式 112 10.10 指定程序块 113 10.11 强度 114 10.11.1 驱动强度 114 10.11.2 电荷强度 115 10.12 竞争状态 116 第11章 验证 118 11.1 编写测试验证程序 118 11.2 波形产生 118 11.2.1 值序列 118 11.2.2 重复模式 119 11.3 测试验证程序实例 123 11.3.1 解码器 123 11.3.2 触发器 124 11.4 从文本文件中读取向量 126 11.5 向文本文件中写入向量 127 11.6 其他实例 128 11.6.1 时钟分频器 128 11.6.2 阶乘设计 130 11.6.3 时序检测器 132 第12章 建模实例 136 12.1 简单元件建模 136 12.2 建模的不同方式 138 12.3 时延建模 139 12.4 条件操作建模 141 12.5 同步时序逻辑建模 142 12.6 通用移位寄存器 145 12.7 状态机建模 145 12.8 交互状态机 147 12.9 Moore有限状态机建模 150 12.10 Mealy型有限状态机建模 151 12.11 简化的21点程序 153 附录 语法参考 157 参考文献 172

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值