第一部分 Verilog HDL 语言 10.1 综述 一. 什么是硬件描述语言? 硬件描述语言是一种用文本形式来描述和 设计电路的语言 是硬件设计人员和电子设计 自动化 (EDA EDA) 工具之间的界面 P.2

Similar documents
z x / +/- < >< >< >< >< > 3 b10x b10x 0~9,a~f,A~F, 0~9,a~f,A~F, x,x,z,z,?,_ x,x,z,z,?,_ h H 0~9,_ 0~9,_ d D 0~7,x,X,z,Z

2. initial always initial always 0 always initial always fork module initial always 2 module clk_gen_demo(clock1,clock2); output clock1,clock2; reg cl

Huawei Technologies Co

untitled

前言

ebook122-3

第一章.doc

PowerPoint Presentation

9 什 么 是 竞 争 与 冒 险 现 象? 怎 样 判 断? 如 何 消 除?( 汉 王 笔 试 ) 在 组 合 逻 辑 中, 由 于 门 的 输 入 信 号 通 路 中 经 过 了 不 同 的 延 时, 导 致 到 达 该 门 的 时 间 不 一 致 叫 竞 争 产 生 毛 刺 叫 冒 险 如

Microsoft Word - FPGA的学习流程.doc

<4D F736F F F696E74202D20D7BFD4BDB9A4B3CCCAA6D6AE454441BCBCCAF5BCB0D3A6D3C3B5DA33BDB22E BBCE6C8DDC4A3CABD5D>

图 片 展 示 : 资 源 简 介 : FPGA Altera CycloneII EP2C5T144C8 (4608 个 LE) 2 路 有 源 晶 振 (50M,25M) AS & JTAG 标 准 接 口 VGA 接 口 UART 接 口 蜂 鸣 器 8bit 并 行 DAC 8 路 按 键

ebook122-11

PowerPoint Presentation

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

PowerPoint Presentation

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

Microsoft PowerPoint - EDA-理论3 [兼容模式]

⊙内容:常用逻辑电路设计

<4D F736F F D20B5DAC8FDCBC4D5C2D7F7D2B5B4F0B0B82E646F63>

数字逻辑设计2013

a b c d e f g C2 C1 2

附件1:

chap07.key

程式人雜誌

101

VHDL Timer Exercise

1 1

untitled

untitled

C/C++语言 - C/C++数据

untitled

Microsoft PowerPoint - chap11.ppt

第3节 VHDL语言的常用语法

穨R _report.PDF

CC213

untitled

Ps22Pdf

《C语言程序设计》教材习题参考答案

Microsoft PowerPoint - 07 派生数据类型

目录

系统架构 - 模块划分 功能 状态机 H265 主要的模块 : 1. 顶层模块 H265ENC_top 包括 sys_ctrl,enc_core 及 fetch 三个模块 2. sys_ctrl 就是一个状态机, 控制 fetch 和 enc_core 中各子模块的工作 3. enc_core 编码

untitled

untitled

STEP-MAX10 V2软件手册

PowerPoint 演示文稿

12 Differential Low-Power 6x6 12 bit multiply 1

FPGAs in Next Generation Wireless Networks WPChinese

C/C++ - 字符输入输出和字符确认

(Load Project) (Save Project) (OffLine Mode) (Help) Intel Hex Motor

2 A

第七章 中断

VN-Cover

<4D F736F F D205A572D2D A1AAA1AAD4ACE7F42D43D3EFD1D4CAB5D1B5BDCCB3CC2E646F6378>

《C语言程序设计》第2版教材习题参考答案

51 C 51 isp 10 C PCB C C C C KEIL

B 6 A A N A S A +V B B B +V 2

第一章三角函数 1.3 三角函数的诱导公式 A 组 ( ) 一 选择题 : 共 6 小题 1 ( 易诱导公式 ) 若 A B C 分别为 ABC 的内角, 则下列关系中正确的是 A. sin( A B) sin C C. tan( A B) tan C 2 ( 中诱导公式 ) ( ) B. cos(

邏輯分析儀的概念與原理-展示版

计算机组成原理

逢甲大學


C/C++程序设计 - 字符串与格式化输入/输出

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

操作指导手册


Transcription:

第十章 Verilog HDL 语言初步 第一部分 Verilog HDL 语言 第二部分 VerilogHDL 程序设计 第三部分 MAX+plus II 与 Verilog HDL 2007-12-7 P.1

第一部分 Verilog HDL 语言 10.1 综述 一. 什么是硬件描述语言? 硬件描述语言是一种用文本形式来描述和 设计电路的语言 是硬件设计人员和电子设计 自动化 (EDA EDA) 工具之间的界面 2007-12-7 P.2

功能 : 1) 编写设计文件 ; 2) 建立电子系统行为级的仿真模型 ; 3) 自动综合以生成符合要求且在电路结构上可以实现的数字逻辑网表 (Netlist Netlist); 4) 写入到 CPLD 和 FPGA 器件中 2007-12-7 P.3

常见术语 1.VLSI(Very Very Large Scale Integration) 超大规模集成电路 集成电路从 60 年代开始, 经历了小规模 SSI 中规模 MSI 大规模 LSI 到目前的超大规模集成 VLSI, 单个芯片上可以制作几百万个晶体管的一个完整的数字系统或数模混合的电子系统 它的迅速发展已经改变了电子技术的面貌, 并且对一系列科学技术, 甚至人们的日常生活都产生了强烈的影响 2007-12-7 P.4

2. EDA (Electronic Design Automatic ) EDA 技术是指以计算机为工作平台, 把应用电子技术 计算机技术 智能化技术等融合在一个电子 CAD 通用软件包中, 根据硬件描述语言 HDL 完成的设计文件, 自动完成逻辑 化简 分割 综合 优化 布局布线及仿真, 直至完成对于特定目标芯片的适配编译 逻辑映射和编程下载等工作 EDA 主要辅助进行三个方面的设计工作 : IC 设计 电子电路设计 PCB 设计 ( 印刷电路板 ) 2007-12-7 P.5

3.FPGA(Field Field Programmable Gate Array) 现场可编程门阵列 4.CPLD (Complex Programmable Logic Device) 复杂可编程逻辑器件 2007-12-7 P.6

部分 FPGA 厂家 Altera http://www.altera.com/ 九十年代以后发展很快, 是最大可编程逻辑器件供应商之一 主要产品有 : FELX6K/10K, MAX3000/7000, APEX20K,ACEX1K ACEX1K 普遍认为其开发工具 MaxplusII 是较成功的 PLD 开发平台 新近推出的新一代完全集成设计环境 Quartus 提供了对 APEX20K 系列芯片的最好支持, 弥补了 MaxplusII 某些功能的不足 2007-12-7 P.7

Lattice http://www.latticesemi.com/ Lattice 是 ISP 技术的发明者,ISP 技术极大的促进了 PLD 产品的发展, 与 ALTERA 和 XILINX 相比, 其开发工具比 ALTERA 和 XILINX 略逊一筹 中小规模 PLD 比较有特色, 而且参考书较多, 不过其大规模 PLD 的竞争力还不够强 (Lattice 没有基于查找表技术的大规模 FPGA) 1999 年推出可编程模拟器件 99 年收购 Vantis( 原 AMD 子公司 ), 成为第三大可编程逻辑器件供应商 主要产品有 isplsi2000/5000/8000, MACH4/5 2007-12-7 P.8

Xilinx http://www.xilinx.com/ FPGA 的发明者, 老牌 PLD 公司, 是最大可编程逻辑器件供应商之一 产品种类较全, 主要有 :XC9500/4000 XC9500/4000, Coolrunner(XPLA3),Spartan, Vertex 开发软件为 :Foundition3.1i 通常来说, 在欧洲用 Xilinx 的人多, 在日本和亚太地区用 ALTERA 的人多, 在美国则是平分秋色 全球 PLD/FPGA 产品 60% 以上是由 Altera 和 Xilinx 提供的 可以讲 Altera 和 Xilinx 共同决定了 PLD 技术的发展方向 2007-12-7 P.9

Actel http://www.actel.com/ 反熔丝 ( 一次性烧写 )PLD 的领导者, 由于反熔丝 PLD 抗辐射, 耐高低温, 功耗低, 速度快, 所以在军品和宇航级上有较大优势 ALTERA 和 XILINX 则一般不涉足军品和宇航级市场 2007-12-7 P.10

Verilog HDL 语言最初是于 1983 年由 Gateway Design Automation 公司为其模拟器产品开发的 硬件建模语言 那时它只是一种专用语言 由 于其模拟 仿真器产品的广泛使用,Verilog HDL 作为一种便于使用且实用的语言逐渐为众 多设计者所接受 并于 1990 年被推向公众领域 1995 年 Verilog 语言成为 IEEE 标准, 称为 IEEE Std 1364-1995 1995 完整的标准在 Verilog 硬件描 述语言参考手册中有详细描述 2007-12-7 P.11

二. 为什么要用 HDL? 1 电路设计的规模越来越大, 复杂度越来越高 2 电子领域的竞争越来越激烈 3 调试电路速度快 不必修改电路原理图原型, 只需要对 HDL 进行修改 4 易于理解, 易于维护 5 有许多易于掌握的仿真 综合和布局布线工具 2007-12-7 P.12

三. Verilog HDL 和 VHDL 的比较 共同的特点 : 1. Verilog HDL 和 HDL 都是用于逻辑设计的硬件描述语言, 并且都已成为 IEEE 标准 ; 2. 能形式化地抽象表示电路的行为和结构 ; 3. 支持逻辑设计中层次与范围的描述 ; 4. 可借用高级语言的精巧结构来简化电路行为的描述 ; 5. 具有电路仿真与验证机制以保证设计的正确性 ; 6. 硬件描述与实现工艺无关, 便于文档管理, 易于理解和设计重用 2007-12-7 P.13

不同点 : 1. VHDL 是美国军方组织开发的, 而 Verilog HDL 则是从一个普通的民间公司的私有财产转化而来 ; 2. Verilog HDL 是一种非常容易掌握的硬件描述语言, 只要有 C 语言的编程基础, 通过二十学时的学习, 再加上一段实际操作, 一般可在二至三个月内掌握这种设计技术 ; 而 VHDL 需要有 Ada 编程基础, 一般认为至少需要半年以上的专业培训, 才能掌握 VHDL 的基本设计技术 3. 一般认为 Verilog HDL 在系统级抽象方面比 VHDL 略差一些, 而在门级开关电路描述方面比 VHDL 强得多 2007-12-7 P.14

美国 : 高层次数字系统设计领域 Verilog 和 VHDL 的应用比率是 80% 和 20%; 日本和我国台湾省与美国相同 ; 欧洲 :VHDL 发展得比较好 在中国大陆 : 据了解, 国内大多数集成电路设计公司都采用 Verilog Verilog 是专门为复杂数字系统的设计仿真而开发的, 本身就非常适合复杂数字逻辑电路和系统的仿真和综合 由于 Verilog 在其门级描述的底层, 也就是在晶体管开关的描述方面比 VHDL 有强得多的功能, 所以即使是 VHDL 的设计环境, 在底层实质上也是由 Verilog HDL 描述的器件库所支持的 2007-12-7 P.15

Verilog HDL 与其他 HDL 比较 Verilog 告诉我你想要电路做什么, 我给你提供能实现这个功能的硬件电路 VHDL 和 Verilog HDL 类似 ABEL AHDL 告诉我你想要什么样的电路, 我给你提供这样的电路 2007-12-7 P.16

Verilog HDL 与 C 语言的比较 Verilog HDL 是在 C 语言基础上发展起来的, 保留了 C 语言的结构特点 C 语言由函数组成, Verilog HDL 由模块 (module) 组成 C 语言通过函数名及其端口变量实现调用, Verilog HDL 通过模块名及其端口变量实现调用 C 语言有主函数 main( ), Verilog HDL 的各模块均等价, 但必有一个顶层模块, 包含芯片系统与外界的所有 I/O 信号 C 语言顺序执行, Verilog HDL 的各模块均并发执行 2007-12-7 P.17

Bottom Up 和 Top down 的设计方法 1. Bottom Up 的设计方法 4. 完成整个系统测试与性能分析 3. 由各个功能模块连成一个完整系统 REGISTER ALU PC RAM 2. 由逻辑单元组成各个独立的功能模块 1. 由基本门构成各个组合与时序逻辑 2007-12-7 P.18 & 1

传统的电路系统设计方法的步骤 : 1. 采用自下而上的设计方法 - 从状态图的简化, 写出最 简逻辑表达式 ; 2. 采用通用逻辑元器件 - 通常采用 74 系列和 CMOS4000 系列的产品进行设计 ; 3. 在系统硬件设计的后期进行调试和仿真 ; 只有在部分或全部硬件电路连接完毕, 才可以进行电路调试, 一旦考虑不周到, 系统设计存在较大缺陷, 则要重新设计, 使设计周期延长 4. 设计结果是一张电路图 ; 当设计调试完毕后, 形成电原理图, 该图包括元器件型号和信号之间的互连关系等等 2007-12-7 P.19

优点 : 1. 设计人员对于用这种方法进行设计比较熟悉 ; 2. 实现各个子块电路所需的时间短 缺点 : 1. 一般来讲, 对系统的整体功能把握不足 ; 2. 实现整个系统的功能所需的时间长, 因为必须先 将各个小模块完成, 使用这种方法对设计人员之 间相互进行协作有比较高的要求 2007-12-7 P.20

2. Top down 的设计方法 1. 系统层 : 顶层模块, 行为级描述, 功能模拟和性能评估 2. 各个功能模块划分, 设计和验证 3. 各个功能模块系统级联合验证 4. 工艺库映射 REGISTER & ALU CPU PC RAM 1 2007-12-7 P.21

Top down 的设计方法的特点 : 从系统层开始设计和优化, 保证了设计结果的正确性 适合复杂的 大规模电路的设计 缩短设计周期 依赖于先进的 EDA 设计工具和环境, 费用昂贵 需要精确的工艺库支持 2007-12-7 P.22

四. 设计过程 Verilog 仿真器 行为仿真 功能仿真 时序仿真 文本编辑器图形编辑器 生成 Verilog HDL 源程序 逻辑综合优化 FPGA/CPLD 布线 / 适配器 硬件测试 2007-12-7 P.23 FPGA/CPLD 编程 下载

典型的综合流程 HDL Library Timing Analysis HDL Model Synthesis Compiler Netlist Technology Library Place/Route Text Output Waveform Simulation Test Vectors 2007-12-7 P.24

2007-12-7 P.25 典型的仿真流程 HDL HDL HDL Library Library Library Simulation Simulation Simulation Compiler Compiler Compiler HDL HDL HDL Model Model Model HDL HDL HDL TestBench TestBench TestBench Simulation Simulation Simulation Model Model Model Test Test Test Vectors Vectors Vectors HDL HDL HDL Simulation Simulation Simulation Text Output Text Output Text Output Waveform Waveform Waveform

10.2 Verilog HDL 设计初步 10.2 内容简介 Verilog HDL 与 C 语言的比较 Verilog 模块的基本结构 逻辑功能的定义 2007-12-7 P.26

一. Verilog HDL 与 C 语言的比较 2007-12-7 P.27 C 语言 function if-then-else for while case break define printf int Verilog 语言 module, function if-then-else for while case break define printf int

Verilog HDL 与 C 语言运算符的比较 C 语言 Verilog 功能 C 语言 Verilog 功能 + + 加 >= >= 大于等于 - - 减 <= <= 小于等于 * * 乘 == == 等于 / / 除!=!= 不等于 % % 取模 ~ ~ 取反!! 逻辑非 & & 按位与 && && 逻辑与 按位或 逻辑或 ^ ^ 按位异或 > > 大于 << << 左移 < 2007-12-7 P.28 < 小于 >> >> 右移

二. Verilog 模块的基本结构 由关键词 module 和 endmodule 定义 模块声明 module 模块名 ( 端口列表 ) 端口定义 数据类型说明 结束行 endmodule 逻辑功能定义 2007-12-7 P.29

1. 模块声明 module 关键词 模块名 模块唯一的标识符 端口列表 是由输入 输出和双向端口的端 2007-12-7 P.30 口表达式按一定的次序组成的一 个列表, 它用来指明模块所具有 的端口, 这些端口用来与其它模 块进行连接

2. 端口定义 又称 端口声明语句, 用来进行端口方向的说 明 Verilog 语言中有如下三种端口声明语句 : 1)input input 对应的端口是输入端口 2 )output output 对应的端口是输出端口 3 )inout inout 对应的端口是双向端口 module output input inout 2007-12-7 P.31

3. 数据类型说明 用来指定模块内用到的数据对象的类型 wire 连线型 wire A,B,C,D;// 定义信号 A~D 为 wire 型 reg 寄存器型 reg [3:0] out;// 定义信号 out 的数据类型为 4 位 reg 型 2007-12-7 P.32 缺省数据类型为 wire 型

4. 逻辑功能定义 模块中最核心部分, 有三种方法可在模块中 产生逻辑 1) 用 assign assign 持续赋值语句定义 例 : assign a = b & c; 2) 调用元件 ( 元件例化 ) 类似于在电路图输入方式下调入图形符号完成设计 2007-12-7 P.33

例 : 调用模块的例子 module MUX2-1 (out,a,b,sel sel); 2007-12-7 P.34 output out; input a,b,sel sel; not (sel_,sel) sel); and (a1,a,sel _); and ( b1,b,sel) sel); or (out,a1 a1,b1) b1); endmodule

2007-12-7 P.35

3) 用 always always 过程块赋值 例 : always @ (posedge clk) begin end if(reset) out=0; else out=out+1; 2007-12-7 P.36

要点总结 : 1. 在 Verilog 模块中, 所有的过程块 ( 如 initial always) 连续赋值语句 实例引用都是并行的 ; 2. 它们表示的是一种通过变量名互相连接的关系 ; 3. 在同一模块中这三者出现的先后顺序没有关系 ; 4. 只有连续赋值语句 assign 和实例引用语句可以独立于过程块而存在于模块的功能定义部分 2007-12-7 P.37

10.3 Verilog HDL 语言要素 10.3 内容简介 词法 数据类型 寄存器和存储器 运算符 2007-12-7 P.38

一. 词法 1. 空白符 ( 间隔符 ) 包括 : 空格 (\b) tab(\t)( 制表符 ) 换行符 (\n) 及换页符 空白符使代码错落有致 阅读方便 综合 时, 空白符被忽略 但是在字符串中空白和 制表符会被认为是有意义的字符 2007-12-7 P.39

Verilog 程序可以不分行 : initial begin ina=3 =3 b001;inb inb=3 =3 b011; end 也可以加入空白符采用多行编写 : initial begin end 2007-12-7 P.40 ina=3 =3 b001; inb=3 =3 b011;

2. 注释 有两种注释形式 : 单行注释 : 以 // 开始到本行结束 多行注释 : 以 /* 开始到 */ 结束 /* 举例说明 */ module addbit(a,b,ci,sum,co); // 输入端口 input a; input b;. 2007-12-7 P.41

3. 数字与字符串 Verilog HDL 有下面 4 种基本逻辑状态 : 0 低电平 逻辑 0 或 假 1 高电平 逻辑 1 或 真 X 未知状态 Z 高阻态 2007-12-7 P.42 X Z 不分大小写 常数按照其数值类型可以划分为整 数和实数两种

1) 整数有 4 种进制表示形式 : 二进制整数 (b 或 B) 十进制整数 (d 或 D) 十六进制整数 (h 或 H) 八进制整数 (o 或 O) 2007-12-7 P.43

数字表达方式有以下 3 种 : < 位宽 > < 进制 > < 数字 > < 进制 > < 数字 > < 数字 > 举例 : 8 b11000101 // 位宽为 8 位的二进制数 8 hd5 // 位宽为 8 位的十六进制数 5 o27 // 位宽为 5 位的八进制数 2007-12-7 P.44

4 B1X_01 //4 位二进制数 1X01 5 HX //5 位十六进制数 XXXXX 4 hz //4 位十六进制数 zzzz 8 h 2 A // 位宽与字符间允许有空格 -8 D5 // 代表 5 的补数 2007-12-7 P.45 X 可以用来定义十六进制数的 4 位二进制 状态, 八进制数的 3 位, 二进制数的 1 位 Z 的表示方法同 X 类似

数值常量中的下划线 _ 是为了增加可读 性, 可以忽略 如 8`b1100_0110 表示 8 位二进制 数 数值常量中的? 表示高阻状态 例 :2 B1 B1? 表示 2 位的二进制数其中的一位是高 阻状态 2007-12-7 P.46

如果没有定义一个整数型的长度, 数的 长度为相应值中定义的位数 下面是两个例子 : o721 //9 位八进制数 haf //8 位十六进制数 如果定义的长度比为常量指定的长度长, 通常在左边填 0 补位 但是如果数最左边一位 为 x 或 z, 就相应地用 x 或 z 在左边补位 例如 : 10 b10 左边添 0 占位, 0000000010 10 bx0x1 左边添 x 占位,xxxxxxx0x1 2007-12-7 P.47

如果定义的位宽比实际的位数小, 那么最 左边的位相应地被截断 : 3 b1001_0011 // 与 3 b011 相等 5 h0fff // 与 5 h1f 相等 2007-12-7 P.48

2) 实数 有两种表示方法 : 十进制表示方法 2.0 5.67 2. // 非法 : 小数点两侧必须有数字 科学计数法 43_5.1e2 //43510.0( 下划线忽略 ) 9.6E2 //960.0 5E-4 //0.0005 2007-12-7 P.49

下面的几个例子是无效的格式 :.25 3. 7.E3.8e-2 实数可以转化为整数, 根据四舍五入的原则, 而不是截断原则, 当将实数赋给一个整数时, 这种转化会自行发生, 例如 : 在转化成整数时, 实数 25.5 和 25.8 都变成 26, 而 25.2 则变成 25 2007-12-7 P.50

3) 字符串 字符串是双引号内的字符序列, 不能分成 多行书写 若字符串用做 Verilog HDL 表达式 或赋值语句中的操作数, 则字符串被看作 8 位 似的 ASCII 值序列, 每一个字符对应 8 位 ASCII 值 2007-12-7 P.51

例 1: 字符串变量声明 reg [8*12: 1] stringvar; initial begin end stringvar= hello world! ; 2007-12-7 P.52

转意符 : 特殊字符表示 \n \t \\ \* \ddd %% 意义 换行符 Tab 键 符号 \ 符号 * 3 位八进制表示的 ASCII 值 符号 % 2007-12-7 P.53

4. 标识符 Verilog HDL 中的标识符可以是任意一 组字母 数字以及符号 $ 和 _ ( 下划线 ) 的组合, 但是标识符的第一个字符必须是字 母或下划线 标识符是区分大小写的 合法标识符 : count COUNT 2007-12-7 P.54 _A1_d2 R56_68

非法标识符 : 30 count // 标识符不允许以数字开头 out * // 标识符中不允许包含 * 逃逸标识符以反斜杠 \ 开始, 以空格结 束 这种命名可以包含任何可印刷的 ASCII 字符 反斜杠和空格不属于名称的一部分 Outgate=\ Outgate 2007-12-7 P.55

5. 关键字 Verilog HDL 内部已经使用的词称为关键 字或保留字 这些关键字用户不能随便使用 在编写程序时, 变量的定义不要与这些关键词 冲突 所有的关键字都是小写 2007-12-7 P.56

二. 数据类型 Verilog HDL 中共有 19 种数据类型 数据类 型是用来表示数字电路硬件中的数据储存和传 送元件的 这里主要介绍 4 种最基本的数据类型 1. 连线型 (Net Type) 线 net type 相当于硬件电路中的各种物理连 2007-12-7 P.57

特点 : 输出的值紧跟输入值的变化而变化 2007-12-7 P.58 Net Type 的变量不能存储值, 而且必须受 到驱动器的驱动 两种驱动方式 : 1) 在结构描述中将它连接到一个逻辑门或模块 的输出端 2) 用持续赋值语句 assign 对其进行赋值 当没有驱动源对其驱动时, 它将保持高阻态

2007-12-7 P.59 为了能够精确地反映硬件电路中各种可 能的物理信号连接特性, Verilog HDL 提供了 多种连线型数据 常用的有 wire 型和 tri 型 这 两种变量都用于连接器件单元, 它们具有相同 的语法格式和功能 wire 型变量 : 通常用来表示单个门驱动或连续 赋值语句驱动的连线型数据 tri 型变量 : 通常用来表示多驱动器驱动的连线 型数据

wire 型变量的格式 : wire [n-1:0] 数据名 1, 数据名 2,, 数据名 n; wire wire 型数据确认符 ; [n-1:0] 代表该数据的位宽 缺省状态, 位 2007-12-7 P.60 宽默认值为 1 数据名 若一次定义多个数据, 数据名之间 用逗号隔开 声明语句的最后用分号表示语句的结束

例 1. 定义数据总线宽 8 位, 地址总线宽 20 位 wire[7:0] databus; wire[19:0] addrbus; 或 : wire[8:1] databus; wire[20:1] addrbus; // databus 宽 8 位 // addrbus 宽 20 位 wire a; // 定义了一个 1 位的 wire 型数据 2007-12-7 P.61

例 2. 多位 wire 型数据可按下面方法使用 wire[7:0] in, out; // 定义两个 8 位 wire 型向量 assign out=in; 例 3. 可只使用多位数据中的几位, 但要注意 2007-12-7 P.62 位宽 wire[7:0] out; wire[3:0] in; assign out[5:2]=in 2]=in;

说明 : 1) wire 型变量常用来表示以 assign 语句赋值 的组合逻辑信号 2) 输入 / 输出信号缺省时自动定义为 wire 型 3) 对综合器而言, wire 型信号的每一位可以 取 0,1,X 或 Z 中的任意值 2007-12-7 P.63

2. 寄存器型 (Register Type) 寄存器是数据存储单元的抽象 寄存器型 数据对应的是具有状态保持作用的硬件电路, 如触发器 锁存器等 寄存器型数据和连线型数据的区别 : 寄存器型数据保持最后一次的赋值 而 连线型数据需有持续的驱动 2007-12-7 P.64

reg 常用的寄存器型变量 reg 型数据的格式 : reg [n-1:0] 数据名 1, 数据名 2, 数据名 n; 例 1. reg a,b; // 定义了两个 reg 型变量 reg [7:0] qout; // 定义 qout 为 8 位宽的 reg 型变量 2007-12-7 P.65

说明 : 1) reg 型数据常用来表示 always always 模块内的指 定信号, 常代表触发器 在 always always 模块内被 赋值的每一个信号都必须定义成 reg 型 2) 对于 reg 型数据, 其赋值语句的作用就如同 改变一组触发器的存储单元的值 3) 若 reg 型数据未初始化 ( 即缺省 ), 则初始 值为不定状态 2007-12-7 P.66

3. 参数型 (parameter parameter) 在 Verilog HDL 中, 用 parameter 来定义 常量, 即用它来定义变量的位宽及延时等 格式 : parameter 参数名 1= 表达式 1, 参数名 2= 表达式 2, ; parameter 常用来定义延迟时间和变量宽度 2007-12-7 P.67

例 : parameter e=2,f=9 f=9;// 定义两个常数参数 parameter r=5.7; // 定义 r 为一个实型参数 parameter a_delay=(r+f r+f)/2 /2; // 用常数表达式赋值 2007-12-7 P.68

三. 寄存器和存储器 1. 寄存器 用 reg 类型变量可构成寄存器和存储器 reg [7:0] mybyte; A= mybyte[6];// 将 mybyte 的第 6 位赋值给 A B= mybyte[5:2] 2];// 将 mybyte 的第 5,4,3,2 位赋值给 B 2007-12-7 P.69

例 : reg [7:0] a,b; reg [3:0] c; reg d; d=a[7]&b[7]; // 位选择 c=a[7:4]+b[3:0]; // 域选择 寄存器可以取任意长度 寄存器中的值通常被解释为无符号数 2007-12-7 P.70

2. 存储器 Verilog HDL 通过对 reg 型变量建立数组来 对存储器建模, 可以描述 RAM 型存储器 ROM 存储器和 reg 文件数组中的每一个单元通 过一个数组索引进行寻址 在 Verilog 语言中没 有多维数组存在,memory 型数据是通过扩展 reg 型数据的地址范围来生成的 2007-12-7 P.71

格式 : reg [n-1:0] 存储器名 [m-1:0]; 或 reg [n-1:0] 存储器名 [m:1]; reg [n-1:0] : 定义了存储器中每一个存储单元的 2007-12-7 P.72 大小 [m-1:0]: 定义了该存储器中有多少个这样的寄 存器

例 1. 定义一个存储器,1024 个字节, 每个字节 8 位 reg [7:0] mymem[1023:0]; 例 2. 存储器与寄存器的区别 reg [n-1:0] rega; // 一个 n 位的寄存器 reg mema[n-1:0]; //n 个一位寄存器组成的存 reg [0:3] Amem[0:63]; 2007-12-7 P.73 储器组

说明 : 1) 数组的维数不能大于 2 2) 存储器属于寄存器数组类型 连线数据类型没有相应的存储器类型 3) 单个寄存器说明既能够用于说明寄存器类型, 也可以用于说明存储器类型 2007-12-7 P.74

例 : parameter ADDR_SIZE = 16, WORD_SIZE = 8; reg [1: WORD_SIZE] RamPar [ ADDR_SIZE- 1 : 0],DataReg DataReg; RamPar 存储器, 是 16 个 8 位寄存器数组 ; DataReg 8 位寄存器 2007-12-7 P.75

4) 在赋值语句中需要注意如下区别 : 存储器赋值不能在一条赋值语句中完成, 但是寄存器可以 因此在存储器被赋值时, 需要定义一个索引 下例说明它们之间的不同 reg [1:5] Dig;... Dig = 5'b11011; 上述赋值是正确的, //Dig 为 5 位寄存器 2007-12-7 P.76

下列赋值不正确 : reg BOg[1:5]; //Bog 为 5 个 1 位寄存器的存储器 Bog = 5'b11011; 2007-12-7 P.77 有一种存储器赋值的方法是分别对存储 器中的每个字赋值 例如 : reg [0:3] Xrom [1:4]; Xrom[1] = 4'hA; Xrom[2] = 4'h8; Xrom[3] = 4'hF; Xrom[4] = 4'h2;

四. 运算符 2007-12-7 P.78 Verilog 语言参考了 c 语言中大多数运算 符的语义和句法 但 Verilog 中没有增 1(i++) 和减 1 (i ) 运算符 1. 算术运算符 +( 一元加和二元加 ) -( 一元减和二元减 ) *( 乘 ) /( 除 ) %( 取模 )

说明 : 1) 两个整数相除, 结果值要略去小数部分, 只取整数部分 ; 2) 取模运算时, 结果的符号位采用模运算式里第一个操作数的符号位 ; 模运算表达式 10 % 4 12 % 3-11 % 5 结果 2 0-1 说明余数为 2 整数余数为 2007-12-7 P.79

3) 在进行算术运算操作时, 如果某个操作数 有不确定的值 X 或 Z, 那么整个结果为 X 例 : 'b10x1 + 'b01111 结果为不确定数 'bxxxxx 4) 无符号数和有符号数 * 若操作数为寄存器型或连线型, 或基数格 式表示形式的整数则为无符号数 ; * 若为整型或实型, 则可以是有符号数 2007-12-7 P.80

例 : reg [0:5] Bar; integer Tab;... Bar = -4 d12 d12;// 寄存器变量 Bar 的十进制数为 52, 向量值为 110100 Tab = -4 d12 d12;// 整数 Tab 的十进制数为 -12, 位 形式为 110100 2007-12-7 P.81

5) 算术操作结果的长度 算术表达式结果的长度由最长的操作数决 定 在赋值语句下, 算术操作结果的长度由操 作符左端目标长度决定 reg [0:3] Arc, Bar, Crt; reg [0:5] Frx;... Arc = Bar + Crt; Frx = Bar + Crt; 2007-12-7 P.82

例 : 算术运算符应用的一个例子 module arithmetic (a,b,out1 out1,out2 out2, out3, input [2:0] a,b; output [3:0] out1 ; output [4:0] out3 ; 2007-12-7 P.83 out4,out5) out5) output [2:0] out2, out4,out5 out5 ; reg [3:0] ; reg [4:0] out3 ; reg [2:0] out2, out4,out5 out5 ;

always @ (a or b) begin out1=a+b ; out2=a-b ; out3=a*b ; out4=a/b ; out5=a%b ; end endmodule 2007-12-7 P.84

2. 逻辑运算符逻辑运算符有 3 种 : && ( 逻辑与 ) ( 逻辑或 )!( 逻辑非 ) 说明 : 1) && 和 为二目运算符, 要求有两个操作数 例 (a>b a>b) && (b>c b>c), (a<b a<b) (b<c b<c), 2007-12-7 P.85 a && b a b

2)! 是单目运算符, 只要求一个操作数 例 :!(a>b a>b),! a 3) 在一个逻辑表达式中, 如果包含多个逻辑 运算符, 如 :!a&&b (x>y)&&c 按以下优先次序 :! && 逻辑运算符中, && 和 的优先级别低于 关系运算符,! 高于算术运算符 2007-12-7 P.86

3. 位运算 在 Verilog 语言中有 7 种位逻辑运算符 : ~ 按位取反 ; 按位或 ; & 按位与 ; ^ 按位异或 ; ^~ 或 ~^ 按位异或非 ; ~& 按位与非 ; ~ 按位或非 ; 2007-12-7 P.87

例 : 若 A=5`b11001;B=5`b10101 B=5`b10101, 则 : 说明 : ~A=5`b00110 A&B= 5`b10001 A B= 5`b11101 A^B= 5`b01100 1) 按位运算符中, 除了 ~ 为单目运算符外, 其 余均为双目运算符 2007-12-7 P.88

2) 对于双目运算符, 如果操作数长度不相等, 长度较小的操作数在最左侧添 0 补位 3) 无论单目按位运算符还是双目按位运算符, 经过按位运算后, 原来的操作数有几位, 所得结果仍为几位 4) 不要将逻辑运算符和按位运算符相混淆 2007-12-7 P.89

4. 关系运算符 Verilog 关系运算符有 : >( 大于 ) <( 小于 ) >= >=( 大于等于 ) <= <=( 小于等于 ) 2007-12-7 P.90

例 : 关系运算符应用的一个例子 module relation (a,b,out1 out1,out2 out2,out3 out3,out4) out4) input [2:0] a,b; output out1,out2 out2,out3 out3,out4 out4 ; reg out1,out2 out2,out3 out3,out4 out4 ; always @ (a or b) begin 2007-12-7 P.91 out1=a<b ; out2=a<=b ; out3=a>b ;

if (a>=b) else end out4=1 out4=0 endmodule 2007-12-7 P.92

说明 : 1) 在进行关系运算时, 若声明的关系为 假, 则返回值是 0 ; 若声明的关系为 真, 则返回值是 1 ; 2) 若某个操作数的值不定, 则关系是模糊的, 返回值是不定值 3) 所有关系运算符有着相同的优先级别 关系运算符的优先级别低于算术运算符 2007-12-7 P.93

5. 等式运算符 等式运算符有 4 种 = = =( 等于 )!=!=( 不等于 ) = = = =( 全等 )!= =( 非全等 ) 两目运算符, 要求有两个操作数, 得到的结果是 1 位的逻辑值 声明的关系为真, 结果为 1; 声明的关系为假, 结果为 0; 2007-12-7 P.94

== == 与 === === 的区别 : 相等运算符真值表 全等运算符真值表 == 0 1 x z === 0 1 x z 0 1 0 x x 0 1 0 0 0 1 0 1 x x 1 0 1 0 0 x x x x x x 0 0 1 0 z x x x x z 0 0 0 1 2007-12-7 P.95

6. 缩位运算符 ( 归约运算符 ) 单目运算符, 也有与 或 非运算 包括下面几种 : & 与 ~& 与非 或 ~ 或非 ^ 异或 ^~,~^ ~^ 同或 2007-12-7 P.96

其与 或 非运算规则类似于位运算符的运算规则, 但其运算过程不同 位运算 : 对操作数的相应位进行与 或 非运算, 操作数是几位数, 则运算结果是几位 缩位运算 : 对单个操作数进行与 或 非递推运算, 最后的运算结果是 1 位的二进制数 2007-12-7 P.97

具体运算过程 : 第一步 : 先将操作数的第 1 位与第 2 位进行与 或 非运算 ; 第二步 : 将运算结果与第 3 位进行与 或 非运算, 依次类推, 直至最后一位 例 :reg[3:0] a; b=&a; 若 :A=5`b11001 则 :&A=0 &A=0; A=1; 2007-12-7 P.98

7. 移位运算符 >> 左移 << 右移 使用方法 : a>>n 或 a<<n a 代表要进行移位的操作数 ; n 代表要移几位 这两种移位运算都用 0 来填补移出的空位 2007-12-7 P.99

module shift; reg[3:0] start,result result; 2007-12-7 P.100 initial bigin end endmodule start=1; result= (start<<2 start<<2);

8. 条件运算符?: 条件运算符, 有三个操作数, 与 C 格式 : 语言相同 信号 = 条件? 表达式 1: 表达式 2; 当条件成立时, 信号取表达式 1 的值, 反 之取表达式 2 的值 2007-12-7 P.101

module add_or_sub(a,b,op,result); parameter ADD=1`b0; input [7:0] a,b; input op; output [7:0] result; assign result=(op== ADD)?a+b:a-b; endmodule 2007-12-7 P.102

9. 位拼接运算 { } 这是一个特殊的运算符, 这一运算符可以 将两个或更多个信号的某些位并接起来进行运 算操作 其使用方法是把某些信号的某些位详 细地列出来, 中间用逗号分开, 最后用大括号 括起来表示一个整体信号 格式 : { 信号 1 的某几位, 信号 2 的某几位,, 信号 n 的某几位 } 2007-12-7 P.103

例 :wire [7:0] Dbus; wire [11:0] Abus; assign Dbus [7:4] = {Dbus [0], Dbus [1], Dbus[2], Dbus[3]};// 以反转的顺序将低端 4 位赋 给高端 4 位 assign Dbus = {Dbus [3:0], Dbus [7:4]}; // 高 4 位与低 4 位交换 2007-12-7 P.104

由于非定长常数的长度未知, 不允许连接 非定长常数 例如, 下列式子非法 : {Dbus,5} // 不允许连接操作非定长常数 2007-12-7 P.105

运算符优先级排序 :! ~ * / % + - << >> < <= > >= ==!= ===!== & ^ ^~ &&?: 2007-12-7 P.106 高优先级别 低优先级别

10.4 Verilog HDL 行为语句 内容简介 过程语句 块语句 赋值语句 条件语句 循环语句 编译向导语句 2007-12-7 P.107

Verilog HDL 是由模块组成的 行为描述方式 过程块 连续赋值语句 模块 结构描述方式 模块实例语句 基本原语实例语句 数据流描述方式 2007-12-7 P.108

一. 过程语句 过程块 2007-12-7 P.109 过程语句 语句块 initial always 过程性赋值语句 高级程序语句 过程赋值语句 过程连续赋值语句 条件分支语句 循环控制语句

1. always 过程语句 格式 : always @( 敏感信号表达式 ) begin // 过程赋值 //if-else,case case,casex casex,casez casez 选择语句 //while,repeat repeat,for 循环 //task,function 调用 end 可选项 过程块 2007-12-7 P.110

1) 敏感信号 只要表达式中某个信号发生变化, 就会引发块内语句的 执行 @ (a) // 当信号 a 的值发生变化时 @ (a or b) // 当信号 a 或 b 的值发生变化时 @ (posedge clock) // 当 clock 上升沿到来时 @ (negedge clock) // 当 clock 下降沿到来时 @ (posedge clk or negedge reset) // 当 clk 的上升沿或 reset 的下降沿到来时 2007-12-7 P.111

module mux4_1(out,in0 in0,in1 in1,in2 in2,in3 in3, sel); output out; input in0,in1 in1,in2 in2,in3 in3 ; input [1:0] sel; reg out; always @ (in0 or in1 or in2 or in3) case (sel) 2007-12-7 P.112 2`b00:out=in0 ; 2`b01:out=in1 ;

2`b10:out=in2 ; 2`b11:out=in3 ; default :out=2`bx ; endcase endmodule 敏感信号分类 边沿敏感型 电平敏感型 wait 语句 2007-12-7 P.113

2) posedge 与 negedge 关键字 例 1: 同步置数 同步清零的计数器 module count(out,data data,load load,reset reset,clk) clk); output[7:0] out; input [7:0] data ; input load, clk, reset; reg [7:0] out; always @ (posedge clk) //clk 上升沿触发 begin 2007-12-7 P.114

if (!reset) out=8`h00 ;// else if (load) else end endmodule out=data ;// out=out+1 ;// // 同步清零, 低有效 // 同步预置 // 记数 例 2: 时钟信号为 clk,clear clear 为异步清零信号 always @ (posedge clk or posedge clear) always @ (posedge clk or negedge clear) 2007-12-7 P.115

错误的描述 : always @ (posedge clk or negedge clear) begin if (clear) // 应改为 if (!clear) out=0; else out=in; end 2007-12-7 P.116

3) 用 always 过程块实现组合逻辑功能 敏感信号表达式内不能包含 posedge 与 negedge 关键字 组合逻辑的所有输入信号都要作为 信号名 出现在敏感信号表达式中 2007-12-7 P.117

例 : module three_and(f,a,b,c) c); output f; input a,b,c ; reg f; always @ (a or b) // 应改为 @ (a or b or c) 2007-12-7 P.118 begin end endmodule f=a&b&c;

4) 用 always 过程块实现时序逻辑功能 敏感信号表达式内可以有 posedge 与 negedge 关键字, 也可以只有信号名 ; 不要求所有输入信号都出现在敏感信号列表 的 信号名 中 2007-12-7 P.119

例 : 时钟下降沿触发的 D 触发器 module D_FF(Q,D,CLK); output Q; input D,CLK; reg Q; always @(posedge CLK) begin Q = D; end endmodule 2007-12-7 P.120

说明 : 1) always 过程语句后面可以是一个敏感事件列表, 该敏感事件列表的作用是用来激活 always 过程语句的执行 ; 2) 如果 always 过程块中的敏感事件列表缺省, 则认为触发条件始终被满足, always 过程块将无条件地循环执行下去, 直到遇到 $finish 或 $stop 系统任务为止 ; 3) 进行仿真时, always 过程块是从模拟 0 开始执行的, 且 always 语句在仿真过程中是不断重复执行的 ; 2007-12-7 P.121

4) 敏感事件列表由一个或多个 事件表达式 构成, 事件表达式说明了启动块内语句执行时的触发条件, 当存在多个事件表达式时要用关键词 or 将多个触发条件组合起来 Verilog 规定 : 只要这些事件表达式所代表的多个触发条件中有一个成立, 就启动块内语句的执行 5) 切勿将变量引入敏感信号列表 6)always 过程块和 initial 过程块都不能嵌套使用 2007-12-7 P.122

例 : 不恰当使用 always 语句而产生仿真死锁的情况 always begin end clk=~clk; always begin #50 clk=~clk; end 2007-12-7 P.123

2. initial 过程块 格式 : initial begin 语句 1; 语句 2; 过程块 语句 n; end 2007-12-7 P.124

说明 : 1) initial 语句后面没有 敏感信号列表 ; 2) initial 过程块中的语句是从模拟 0 开始执 2007-12-7 P.125 行, 它在仿真过程中只执行一次, 在执行 完后, 该 initial 过程块就被挂起, 不再执 行 ; 3) initial 过程块的使用主要是面向功能模拟 的, 通常不具综合性

例 1: 用 initial 过程语句对测试变量 A B C 赋值 `timescale 1ns/1ns module test; reg A,B,C; initial begin A=0;B=1 B=1;C=0 C=0; #50 A=1;B=0 B=0; 2007-12-7 P.126

#50 A= 0;C=1 C=1; #50 B=1; #50 B=0;C=0 C=0; #50 $finish; end endmodule 2007-12-7 P.127

例 2:initial 过程块用于对变量和存储器进行初始化 module register_initialize(memory); inout areg; inout memory; parameter size=1024,bytesize bytesize=8 ; reg [bytesize-1:0] memory [size-1:0] 0]; 2007-12-7 P.128

initial begin:seq-blk-a integer: index ; for(index=0 (index=0;index<size index<size;index=index+1) index=index+1) memory[index]=0; areg=0; end endmodule 2007-12-7 P.129

3. 两类语句在模块中的使用 module tese reg sa,sb sb,ze; initial begin sa=0; sb=0; #5 sb=1 #5 sa=1; #5 sb=0; end always @ (sa or sb) ze=sa^sb; endmodule 2007-12-7 P.130

二. 块语句 2007-12-7 P.131 在 Verilog HDL 中有两类语句块 : 1. 串行块 (begin-end begin-end) 格式 : begin:< 块名 > 块内局部变量说明 ; 时间控制 1 行为语句 1; 时间控制 n 行为语句 n; end

说明 : 1) 块内的语句按顺序方式执行 ; 2) 每条语句中的时延值与其前一条语句执行的仿真时间有关 ; 3) 一旦顺序语句块执行结束, 跟随顺序语句块过程的下一条语句继续执行 2007-12-7 P.132

例 : 用 begin-end 串行块产生信号波形 `timescale 10ns/1ns module wave1; reg wave ; parameter cycle=10 ; initial begin 2007-12-7 P.133 wave=0 ; #(cycle/2) wave=1 ; #(cycle/2) wave=0 ;

#(cycle/2) wave=1 ; #(cycle/2) wave=0 ; #(cycle/2) wave=1 ; #(cycle/2) $finish ; end initial $monitor($time,,, wave=%b wave=%b, wave); endmodule 2007-12-7 P.134

2. 并行块 (fork-join) 格式 : fork:< 块名 > 块内局部变量说明 ; 时间控制 1 行为语句 1; 时间控制 n 行为语句 n; join 2007-12-7 P.135

说明 : 1) 块内语句是同时执行的, 即程序流程控制 2007-12-7 P.136 一进入到该并行块, 块内语句则开始同时 并行执行 2) 块内每条语句的延迟时间是相对于程序流 程控制进入到块内的仿真时间的 3) 延迟时间用来给赋值语句提供执行时序 4) 当按时间时序排序在最后的语句执行完后, 程序流程控制跳出该程序块

例 : 用 fork-join 并行块产生信号波形 `timescale 10ns/1ns module wave2; reg wave ; parameter cycle=5 ; initial fork wave=0 ; #(cycle) wave=1 ; #(2*cycle) wave=0 ; 2007-12-7 P.137

#(3*cycle) wave=1 ; #(4*cycle) wave=0 ; #(5*cycle) wave=1 ; #(6*cycle) $finish ; join initial $monitor($time,,, wave=%b wave=%b, wave); endmodule 2007-12-7 P.138

自学内容 : 1 系统任务与系统函数 ; 2 编译指令 ; 3 用户自定义元件(UDP UDP); 4 测试与仿真 2007-12-7 P.139

三. 赋值语句 1. 持续赋值语句 ( 不能出现在过程块中 ) 持续赋值语句只能对连线型变量 wire 进 行赋值, 不能对寄存器型变量进行赋值 格式 : 连线型变量类型 [ 连线型变量位宽 ] 连线型变量名 assign #( 延时量 ) 连线型变量名 = 赋值表达式 可选项 2007-12-7 P.140

延时量 的基本格式 : #(delay1 delay1, delay2, delay3) delay1 上升延时 ; delay2 下降延时 ; delay3 关断延时 ( 转移到高阻态 ) 如果 延时量 这项缺省, 默认为 0 延时 2007-12-7 P.141

例 : module and_cont_assignment(z,x,y); input [3:0] x,y; output [3:0]z; wire [3:0]z,x,y; assign #(1.5,1.0 1.0,2.0) z=x&y; endmodule 2007-12-7 P.142

1) 标量连线型 wire a,b; assign a=b; 2) 向量连线型 wire[ 7:0] a,b; assign a=b; 3) 向量连线型变量中的某一位 wire[ 7:0] a,b; assign a[3]=b[3]; 2007-12-7 P.143

4) 向量连线型变量中的某几位 wire [ 7:0] a,b; assign a[3:2]=b[3 2]=b[3:2]; 2]; 5) 上面几种类型的任意拼接运算 wire a, c; wire[ 2:1] b; assign {a,c}=b; 2007-12-7 P.144

说明 : 1) 持续赋值用来描述组合逻辑 2) 持续赋值语句驱动连线型变量, 输入操作 数的值一发生变化, 就重新计算并更新它 所驱动的变量 3) 连线型变量没有数据保持能力 4) 若一个连线型变量没有得到任何连续驱动, 则它的取值将为不定态 x 2007-12-7 P.145

5) 在仿真时, 只要右端赋值表达式内的任一操作数发生变化, 就会立即触发对被赋值连线型变量的更新操作 6) 如果持续赋值语句带有延时, 则在仿真时只要右端赋值表达式中的任一信号发生变化, 都将立即对赋值表达式进行重新计算, 然后进入延时等待状态, 待指定延时过去后再进行赋值 2007-12-7 P.146

例 : 用持续赋值语句实现 4 位全加器 module adder_4(a,b,ci,sum,co); input [3:0] a,b; input ci; output [3:0] sum; output co; assign {co,sum}=a+b+ci; endmodule 2007-12-7 P.147

2. 过程赋值语句 过程赋值是在 always 和 initial 语句内的赋 值, 它只能对寄存器数据类型的变量赋值 过程赋值语句的分类 阻塞型赋值 非阻塞型赋值 2007-12-7 P.148

格式 : < 被赋值变量 > = < 赋值表达式 > < 被赋值变量 > <= < 赋值表达式 > 阻塞型赋值 非阻塞型赋值 阻塞与非阻塞赋值一般使用在进程中, 包 括 always 和 initial 进程 assign 赋值等操作中 2007-12-7 P.149

1) 非阻塞型赋值方式 ( 如 b<=a;) 非阻塞赋值在整个过程块结束时才完成赋 值操作, 即 b 的值并不是立即就改变的 2) 阻塞赋值方式 ( 如 b=a;) 阻塞赋值在该语句结束时就立即完成赋值 操作, 即 b 的值在该条语句结束后立即改变, 如 果在一个语句块中有多条阻塞赋值语句, 则前 面赋值语句没有完成之前, 后面赋值语句不能 被执行, 仿佛被阻塞一样 2007-12-7 P.150

例 1: 非阻塞赋值 module non_block(c,b,a,clk); output c,b; input clk,a; reg c,b; always @(posedge clk) begin b<=a; c<=b; end endmodule 2007-12-7 P.151

2007-12-7 P.152

例 2: 阻塞赋值 module non_block(c,b,a,clk); output c,b; input clk,a; reg c,b; always @(posedge clk) begin b=a; c=b; end endmodule 2007-12-7 P.153

2007-12-7 P.154

四. 条件语句 条件分支语句 if-else 条件分支 case 条件分支 高级程序语句 2007-12-7 P.155 循环控制语句 forever repeat while for

1. if-else Verilog HDL 语言提供了 3 种形式的 if 语句 : 2007-12-7 P.156 1) if( 表达式 ) 语句 1; 2) if( 表达式 ) 语句 1; else 语句 2; 3)if if( 表达式 1) 语句 1; else if( 表达式 2) 语句 2; else if( 表达式 3) 语句 3; else if( 表达式 n) 语句 n; else 语句 n+1;

说明 : 1)3 种形式的 if 语句在 if 后面都有 表达式, 一 般为逻辑表达式或关系表达式 系统对表达式 的值进行判断, 若为 0,x,z, 按 假 处理 ; 若 为 1, 按 真 处理, 执行指定语句 2) 在 if 和 else 后面可以包含单个或多个语句, 多句时用 begin-end begin-end 块语句括起来 3) 在 if 语句嵌套使用时, 要注意 if 与 else 的配对 关系 2007-12-7 P.157

例 1:module sel-from-three(q,sela,selb,a,b,c); input sela,selb,a,b,c; output q; reg q; always @(sela or selb or a or b or c); begin if(sela) q=a; else if(selb) q=b; else q=c; end endmodule 2007-12-7 P.158

例 2: module count60(qout,cout cout,data data,load load,cin cin, reset,clk); input [7:0] data; input load,cin cin, reset, clk; output [7:0] qout; output cout; reg [7:0] qout; always @(posedge clk); begin if (reset) qout<=0; else if (load) qout<=data; 2007-12-7 P.159

else if (cin) begin if (qout[3:0]==9) begin qout[3:0]<=0; if (qout[7:4]==5) qout[7:4]<=0; else qout[7:4]<=qout[7:4]+1; end else qout[3:0]<=qout[3:0]+1; end end assign cout=((qout==8`h59)&cin)?1:0; endmodule 2007-12-7 P.160

2. case if 语句有两个分支, 而 case 语句是一种多 路分支语句, 故 case 语句可用于译码器 数据 选择器 状态机 微处理器的指令译码等 case 语句有 case casez casex 三种表示方式 : 2007-12-7 P.161

1) case 语句 格式 : case ( 敏感表达式 ) endcase 值 1: 语句 1; 值 2: 语句 2; 值 n: 语句 n; default: 语句 n+1; 2007-12-7 P.162

例 :BCD 码 - 七段数码管显示译码 module decode4_7(decodeout,indec); output [6:0] decodeout; input [3:0] indec; reg [6:0] decodeout; always @ (indec) begin case (indec) 4 d0 d0:decodeout=7 decodeout=7 b1111110; 4 d1 d1:decodeout=7 decodeout=7 b0110000; 2007-12-7 P.163

2007-12-7 P.164 4 d2 d2 d2:decodeout=7 decodeout=7 decodeout=7 b1101101; b1101101; b1101101; 4 d3 d3 d3:decodeout=7 decodeout=7 decodeout=7 b1111001; b1111001; b1111001; 4 d4 d4 d4:decodeout=7 decodeout=7 decodeout=7 b0110011; b0110011; b0110011; 4 d5 d5 d5:decodeout=7 decodeout=7 decodeout=7 b1011011; b1011011; b1011011; 4 d6 d6 d6:decodeout=7 decodeout=7 decodeout=7 b1011111; b1011111; b1011111; 4 d7 d7 d7:decodeout=7 decodeout=7 decodeout=7 b1110000; b1110000; b1110000; 4 d8 d8 d8:decodeout=7 decodeout=7 decodeout=7 b1111111; b1111111; b1111111; 4 d9 d9 d9:decodeout=7 decodeout=7 decodeout=7 b1111011; b1111011; b1111011; default default default : decodeout=7 decodeout=7 decodeout=7 bx; bx; bx; endcase endcase endcase end end end endmodule endmodule endmodule

2) casez 与 casex 语句 casez 与 casex 的格式与 case 完全相同, 但 在执行时有区别 case 语句比较规则 case 0 1 x z 0 1 x z 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 casez 语句比较规则 casez 0 1 x z 0 1 x z 1 0 0 1 0 1 0 1 0 0 1 1 1 1 1 1 2007-12-7 P.165

casex 语句比较规则 casex 0 1 x z 0 1 x z 1 0 1 1 0 1 1 1 1 1 1 1 1 1 0 1 2007-12-7 P.166

例 1: 用 casez 语句实现操作码译码 module decode_ casez(a, b, opcode, out); input[7:0] a, b; input[4:1] opcode; output[7:0] out; reg [7:0] out; always @ (a or b or opcode) 2007-12-7 P.167

end 2007-12-7 P.168 begin casez (opcode) 4 b1zzz: out=a+b; 4 b01??: out=a-b; 4 b0001: out=(~b)+1; endcase endmodule

例 2: 用 casex 语句实现操作码译码 module decode_ casez(a, b, opcode, out); input[7:0] a, b; input[4:1] opcode; output[7:0] out; reg [7:0] out; always @ (a or b or opcode) 2007-12-7 P.169

end 2007-12-7 P.170 begin casex (opcode) 4 b1zzx: out=a+b; 4 b01xx: out=a-b; 4 b0001: out=(~b)+1; endcase endmodule

3. 条件语句使用要点 2007-12-7 P.171 在使用条件语句时, 应注意列出所有条件 分支, 否则编译器认为条件不满足时, 会引进一 个触发器保持原值 在组合电路中应避免这种隐 含触发器的存在 因为每个变量至少有 4 种取值, 为包含所有 分支, 可在 if 语句后加上 else; 在 case 语句后加 上 default

例 : 隐含锁存器举例 module buried_ff(c,b,a); output c; input b,a; reg c; always @(a or b) 2007-12-7 P.172 begin end endmodule if((b==1)&&(a==1)) c=a&b; else c=0;

五. 循环语句 有 4 种类型的循环语句, 可用来控制语句的执行次数 : (1)forever forever: 连续地执行语句 (2)repeat repeat: 连续执行一条语句 n 次 (3)while while: 执行一条语句, 直到某个条件不满足 (4)for for: 有条件的循环语句 2007-12-7 P.173

1. forever 语句 功能 : 无限循环 一般用在 initial 中 格式 : 2007-12-7 P.174 forever 语句 ; 或 forever begin end 用途 : 产生周期性波形作为仿真测试信号

例 1: module clk_gen(clk); output clk; initial begin clk=0; #1000; forever #25 clk=~clk; end endmodule 2007-12-7 P.175

例 2: module clk_gen(clk); output clk; integer counter; initial begin 2007-12-7 P.176 counter=0; clk=0; #1000;

end begin begin: FOREVER_PART end 2007-12-7 P.177 forever begin counter=counter +1; if (counter>200) disable end endmodule #25 clk=~clk; disable FOREVER_PART;

2. repeat 语句 功能 : 该循环语句内的循环体部分被重复执行 格式 : 2007-12-7 P.178 指定的次数 repeat ( 循环次数表达式 ) 语句 ; 或 repeat ( 循环次数表达式 ) begin end

例 1: 用 repeat 循环语句来实现循环移位 module drift (data, num, ctrl); inout [16: 1] data; input [4: 1] num; input ctrl; reg [16: 1] data; reg tmp; always @ (ctrl) if (ctrl==1) 2007-12-7 P.179

repeat (num) begin end endmodule tmp=data[16]; data={data<<1, tmp}; 2007-12-7 P.180

例 2: 用 repeat 实现 8 位二进制数的乘法 module mult_repeat(outcome,a,b); parameter size=8; input[size:1] a,b; output[2 [2*size:1] outcome; reg[2 [2*size:1] temp_a,outcome; reg[size:1] temp_b; always @(a or b) begin outcome=0; 2007-12-7 P.181

temp_a=a; temp_b=b; repeat(size) // size 为循环次数 begin if(temp_b[1]) outcome=outcome+temp_a; temp_a=temp_a<<1; // 操作数 a 左移一位 temp_b=temp_b>>1; // 操作数 b 右移一位 end end endmodule 2007-12-7 P.182

3. while 语句 功能 : 条件循环 格式 : while ( 循环执行条件表达式 ) 语句 ; 或 while ( 循环执行条件表达式 ) begin end 2007-12-7 P.183

例 1: 用 while 实现显示一个 32 位整数的循环 module loop2; integer i; initial begin i=0; while(i<4) begin $display ("i=%h",i); i=i+1; end end endmodule 2007-12-7 P.184

4. for 语句 功能 : 条件循环 只有在指定的条件表达式成立 格式 : 时才进行循环 for( 循环变量赋初值 ; 循环条件结束 ; 循环变量增值 ) 执行语句 ; 2007-12-7 P.185

begin 语句 1; while( 条件表达式 ) begin 循环体语句或语句块 ; 语句 2; end end for ( 语句 1, 条件表达式, 语句 2) 2007-12-7 P.186 循环体语句或语句块 ;

例 1: 用 for 实现显示一个 32 位整数的循环 module loop1; integer i; initial for(i=0;i<4;i=i+1) begin $display("i=%h",i); end endmodule 2007-12-7 P.187

10.5 进程 任务与函数 进程 任务 函数 任务与函数的区别 2007-12-7 P.188

一. 进程 表示进程的方法 : always 过程块 initial 过程 assign 赋值语句 元件例化 2007-12-7 P.189

1. 进程的特点 1) 进程只有两种状态 : 执行 等待 2) 进程一般有敏感信号的变化来启动 3) 进程内部的语句是顺序执行的 4) 多进程之间是并行执行的, 与进程在程序中的位置无关 5) 进程之间的通信是由信号来传递的 2007-12-7 P.190

2. 举例 : 加法计数器中的进程 module count(data,clk,reset,load,cout,qout); output cout; output[3:0] qout; reg[3:0] qout; input[3:0] data; input clk,reset,load; 2007-12-7 P.191

always @(posedge clk) begin end if (!reset) 2007-12-7 P.192 qout= 4'h00; else if (load) qout= data; else qout=qout + 1; assign cout=(qout==4'hf)?1:0; endmodule

二. 任务 义, 行为描述模块内可以包含任务和函数定 这两部分在行为描述模块中都是可选的, 类似 与一种子程序结构 引入任务和函数的目的 : 将一个很大的程序模块分解成许多较小任 务和函数, 便于理解和调试 2007-12-7 P.193

1. 任务的定义 task < 任务名 >; // 注意无端口列表 2007-12-7 P.194 端口及数据类型声明语句 ; 局部变量说明 ; 语句 1; endtask 语句 n

说明 : 1) 端口及数据类型声明语句 用于对任务各个端口的宽度和类型进行说明 2) 局部变量说明 用来对任务内用到的局部变量进行宽度和类型说明 3) 语句 1~ 语句 n 行为语句, 指明了任务被调用时需要进行的操作 4) 任务定义与 过程块 连续赋值语句 及 函数定 义 以并列的方式存在于行为描述中, 任务定义 不能出现在任何过程块的内部 2007-12-7 P.195

任务定义举例 : task read_mem; input [15: 0] address; output [31: 0] data; reg [3: 0] counter; reg [7: 0] temp [1: 4]; begin for (counter=1; counter<=4; counter=counter+1) temp[counter]=mem[address+counter-1]; data={temp[1],temp[2],temp[3],temp[4]}; end endtask 2007-12-7 P.196

2. 任务的调用 格式 : < 任务名 > ( 端口 1, 端口 2,, 端口 n); 说明 : 1) 任务调用语句只能出现在过程块中 2) 当被调用的任务具有输入 输出端口时, 任务调用语句必须包含端口列表, 其列表内各端口名出现的顺序和类型必须与任务定义结构中端口说明部分的端口顺序和类型一致 3) 只有寄存器类的变量才能与任务的输出端口相对应 2007-12-7 P.197

对任务 read_mem read_mem 进行调用 module demo_task_invo; reg [7: 0] mem[128: 0]; reg [15: 0] a; reg [31: 0] b; initial begin a=0; 2007-12-7 P.198

end read_mem(a, b); #10 a=64; read_mem(a, b); < 任务 read_mem 定义部分 > endmodule 2007-12-7 P.199

3 函数 1. 函数的定义 function < 返回值位宽或类型说明 > 函数名 ; 2007-12-7 P.200 输入端口声明 ; 局部变量定义 ; begin 行为语句 1; 行为语句 n end endfunction

function [7: 0] get0; input [7: 0] x; reg [7: 0] count; integer i; begin count=0; for (i=0; i<=7; i=i+1) if (x[i]=1`b0) count=count+1; get0=count; end endfunction 2007-12-7 P.201 定义函数举例

2. 函数的调用 格式 : < 函数名 > (< 输入表达式 1>, < 输入表达式 m>); 说明 : 1) 函数的调用不能单独作为一条语句出现, 只能作为操作数出现在调用语句内 2007-12-7 P.202

例 1: 用函数和 case 语句描述的编码器 ( 不含优先顺序 ) module code_83(din,dout); input[7:0] din; output[2:0] dout; function[2:0] code; input[7:0] din; casex (din) 8'b1xxx_xxxx : code = 3'h7; 8'b01xx_xxxx : code = 3'h6; 8'b001x_xxxx : code = 3'h5; 2007-12-7 P.203

8'b0001_xxxx : code = 3'h4; 8'b0000_1xxx : code = 3'h3; 8'b0000_01xx : code = 3'h2; 8'b0000_001x : code = 3'h1; 8'b0000_000x : code = 3'h0; default: code = 3'hx; endcase endfunction assign dout = code(din) ; endmodule 2007-12-7 P.204

2) 函数调用既能出现在过程块中, 也能出现在 assign 连续赋值语句中 3) 定义函数时, 没有端口列表名, 但调用函数时, 需列出端口列表名, 端口名的排序和类型必须与 定义时的相一致 4) 函数不能调用任务, 但任务可以调用别的任务和 函数, 且调用个数不限 2007-12-7 P.205 ) 函数的调用与定义必须在一个模块

3. 任务与函数的区别 1) 输入与输出 任务 : 可有任意个各种类型的参数 函数 : 至少有一个输入, 不能将 inout 类型作为输出 2) 调用 任务 : 只可在过程语句中调用, 不能在 assign 中调用 3) 定时和事件控制 (@, # 和 wait) 任务 : 可包含定时和事件控制语句 函数 2007-12-7 : P.206 不可包含定时和事件控制语句

4) 调用其它任务和函数 任务 : 可调用其它任务和函数 函数 : 可调用其它函数, 但不可调用其它任务 5) 返回值 任务 : 不向表达式返回值 函数 : 向调用它的表达式返回一个值 2007-12-7 P.207

10.6 Verilog HDL 的描述 结构描述 风格 行为描述 数据流描述 2007-12-7 P.208

一. 结构描述 结构描述方式是将硬件电路描述成一个分 级子模块系统的一种描述方式 在这种描述方 式下, 组成硬件电路的各个子模块之间的相互 层次关系及相互连接关系都需要得到说明 可通过如下方式来描述电路的结构 : 1) 调用 Verilog 内置门元件 ( 门级结构描述 ) 2) 调用开关级元件 ( 开关级结构描述 ) 3) 用户自定义元件 UDP( 门级 ) 2007-12-7 P.209

1. Verilog 内置门元件 共内置 26 个基本元件, 其中 14 个是门级元 件,12 个为开关级元件 and 与门 ; xor 异或门 ; nand 与非门 ; xor 异或非门 ; nor 或非门 ; buf 缓冲器 ; or 或门 ; not 非门 2007-12-7 P.210

2. 门元件的调用 格式 : 门元件名字例化的门名字 ( 端口列表 ) 其中 : 1) 普通门的端口列表按下面的顺序列出 : ( 输出, 输入 1, 输入 2, ); 例 :/* 三输入与门, 名字为 a1*/ and a1(out, in1, in2, in3); 2007-12-7 P.211

2) 对三态门, 按如下顺序列出输入 输出端口 : ( 输出, 输入, 使能控制端 ); 例 :/* 高电平使能的三态门 */ bufif1 mytri1(out, in, enable); 3) 对 buf 和 not 两种元件的调用, 允许有多个输 出, 但只能有一个输入 例 :/*1 个输入 in,2 个输出 out1, out2 */ not n1(out1, out2, in); 2007-12-7 P.212

例 : 调用门元件实现 4 选一数据选择器 module mux4_1a(out,in1,in2,in3,in4,cntrl1,cntrl2); output out; input in1,in2,in3,in4,cntrl1,cntrl2; wire notcntrl1,notcntrl2,w,x,y,z; not (notcntrl1,cntrl2), (notcntrl2,cntrl2); 2007-12-7 P.213

and (w,in1,notcntrl1,notcntrl2), (x,in2,notcntrl1,cntrl2), (y,in3,cntrl1,notcntrl2), (z,in4,cntrl1,cntrl2); or (out,w,x,y,z); endmodule 2007-12-7 P.214

例 : 用 case 语句实现 4 选一数据选择器 module mux4_1b(out,in1,in2,in3,in4,cntrl1,cntrl2); output out; input in1,in2,in3,in4,cntrl1,cntrl2; reg out; always@ always@(in1 or in2 or in3 or in4 or cntrl1 or cntrl2) 2007-12-7 P.215

二. 行为描述行为描述的目标不是对电路的具体硬件 结构进行说明, 仅从电路的行为和功能的角 度来描述某一电路模块 结构级描述在进行仿真时优于行为描述 ; 行为描述在综合时更优越 ; 2007-12-7 P.216 对设计者来说, 采用的描述级别越高, 设计越容易 所以在电路设计中, 除非一些 关键路径的设计采用结构描述外, 一般更多 地采用行为描述方式

case({cntrl1,cntrl2}) 2'b00:out=in1; 2'b01:out=in2; 2'b10:out=in3; 2'b11:out=in4; default:out=2'bx; endcase endmodule 2007-12-7 P.217

三. 数据流描述 例 : 数据流方式描述的 4 选一数据选择器 module mux4_1c(out,in1,in2,in3,in4,cntrl1,cntrl2); output out; input in1,in2,in3,in4,cntrl1,cntrl2; assign out=(in1 & ~cntrl1 & ~cntrl2) (in2 & ~cntrl1 & cntrl2) (in3 & cntrl1 &~cntrl2) (in4 & cntrl1 & cntrl2); endmodule 2007-12-7 P.218

10.7 Verilog HDL 设计进阶 组合逻辑电路设计进阶 2007-12-7 P.219

组合逻辑电路举例 组合电路 Preset when counter value is H 7 2007-12-7 P.220

仿真结果分析 理论结果 实际结果 2007-12-7 P.221 Error

可编程器件有问题我再也不用它了 No, no, no... 这不是可编程器件的问题 How? OK! I can prove it to you 2007-12-7 P.222

一个最简单的组合逻辑电路 一个两输入的与门或者两输入的或门是最简单的电路!!! 但可编程器件对这么简单的电路的处理也会出错 2007-12-7 P.223

两输入与门的仿真结果 但问题真的是这么简单? 输入波形 这部分有问题这一定是器件的原因 2007-12-7 P.224 输出波形

再进一步分析 假设与门的内部延时是 0.2nS 这代表什么意思呢? 2007-12-7 P.225 对信号 B 进行简单计算 : (Trace delay of b) + AND gate internal delay = 8.1ns (Trace delay of b) + 0.2ns = 8.1ns (Trace delay of b) = 7.9ns 对信号 A 进行简单计算 : (Trace delay of a) + AND gate internal delay = 11.1ns (Trace delay of a) + 0.2ns = 11.1ns (Trace delay of a) = 10.9ns

结果再分析 Time : 0ns 10.9ns 11.1ns 8.1ns 7.9ns (Trace delay of a) = 10.9ns (Trace delay of b) = 7.9ns 01 1->0 0 0->1 1 1 0 01 Output Output C change C change from back 0 from to 1 1 at 8.1ns to 0 as the final result A 3 ns Pulse generate (10.9-7.9 = 3ns) 2007-12-7 P.226

总结 设计一个 2 输入的与门也不是象 1+1=2 那么简单 在组合逻辑设计中我们需要考虑 Trace Delay and Gate Delay 函数 : C 的输出为 0 时序 : C 的输出有一个 3ns 宽的毛刺 这 3ns 的毛刺主要是由 Trace Delay 造成的 组合电路工作时不仅和逻辑函数相关还和时序相关 2007-12-7 P.227

深入总结 当某一时刻同时有一个以上的信号发生变化时容易产生毛刺 组合逻辑电路是会产生毛刺的 2007-12-7 P.228

If you want your cirucit work RELIABLE, you need to consider TIMING FACTOR This is not Device Problem This is Design Problem 2007-12-7 P.229

再讨论第一个例子 这两个点之间的延时是什么样的呢? 2007-12-7 P.230

分 析 q2 q1 q0 2007-12-7 P.231 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 毛刺? 毛刺? 毛刺? 毛刺? 毛刺? 毛刺? 毛刺? No No No Yes No Yes No

仿真结果分析 从 3 变到 4 的时候产生毛刺 从 5 变到 6 的时候产生毛刺 两个不希望看到的毛刺 仿真结果正确, 可编程器件没有问题 2007-12-7 P.232

毛刺的宽度 3 to 4 011 -> 100 2007-12-7 P.233 5 to 6 101 -> 110

2007-12-7 P.234 结论 如果我们知道毛刺是什么产生的 我们可以计算出毛刺出现的具体时间 我们可以计算出毛刺的脉冲宽度 当组合逻辑输出用做以下功能时必须加以注意 触发器的 CLEAR 端 触发器的 PRESET 端 触发器的 CLOCK 端 锁存器的控制端 其他...

消除毛刺的方法 ( 一 ) 重新设计结构 2007-12-7 P.235

有毛刺的程序 : 2007-12-7 P.236 消除毛刺的方法 ( 二 ) module longframe1(clk,strb); parameter delay=8; input clk; output strb; reg strb; reg[7:0] counter;

always@(posedge clk) begin if(counter==255) counter=0; else counter=counter+1; end always@(counter) begin if(counter<=(delay-1)) strb=1; else strb=0; end endmodule 2007-12-7 P.237

加 D 触发器后消除毛刺的程序 : module longframe2(clk,strb); parameter delay=8; input clk; output strb; reg[7:0] counter; reg temp; reg strb; 2007-12-7 P.238

always@(posedge clk) begin if(counter==255) else end counter=0; counter=counter+1; always@(posedge clk) begin strb=temp; // 引入一个触发器 end 2007-12-7 P.239

always@(counter) begin if(counter<=(delay-1)) temp=1; else end endmodule temp=0; 2007-12-7 P.240

1. 三态门 组合逻辑电路举例 : module tri_1(in,en,out); input in,en; output out; tri out; bufif1 b1(out,in,en); // 注意三态门端口的排列顺序 endmodule 2007-12-7 P.241

用数据流方式描述的三态门 : module tri_2(out,in,en); output out; input in,en; assign out = en? in : 'bz; endmodule 2007-12-7 P.242

2. 译码器 module decoder_38(out,in); output[7:0] out; input[2:0] in; reg[7:0] out; always @(in) begin 2007-12-7 P.243

case(in) 3'd0: out=8'b11111110; 3'd1: out=8'b11111101; 3'd2: out=8'b11111011; 3'd3: out=8'b11110111; 3'd4: out=8'b11101111; 3'd5: out=8'b11011111; 3'd6: out=8'b10111111; 3'd7: out=8'b01111111; endcase end endmodule 2007-12-7 P.244

3. 8-3 优先编码器 module encoder8_3(none_on,outcode,a,b,c,d,e,f,g,h); output none_on; output[2:0] outcode; input a,b,c,d,e,f,g,h; reg[3:0] outtemp; assign {none_on,outcode}=outtemp; always @(a or b or c or d or e or f or g or h) begin 2007-12-7 P.245

if(h) else if(g) else if(f) else if(e) else if(d) else if(c) else if(b) else if(a) else end endmodule 2007-12-7 P.246 outtemp=4'b0111; outtemp=4'b0110; outtemp=4'b0101; outtemp=4'b0100; outtemp=4'b0011; outtemp=4'b0010; outtemp=4'b0001; outtemp=4'b0000; outtemp=4'b1000; else if(g) outtemp=4'b0110; else if(e) outtemp=4'b0100; else if(d) outtemp=4'b0011; else if(c) outtemp=4'b0010; else if(b) outtemp=4'b0001; else if(a) outtemp=4'b0000;

1. 基本 D 触发器 2007-12-7 P.247 时序逻辑电路举例 : module DFF(Q,D,CLK); output Q; input D,CLK; reg Q; always @(posedge CLK) begin Q <= D; end endmodule

2. 带异步清 0 置 1 的 D 触发器 module DFF1(q,qn,d,clk,set,reset); input d,clk,set,reset; output q,qn; reg q,qn; always @(posedge clk or negedge set or negedge reset) begin if (!reset) begin q <= 0; qn <= 1; end 2007-12-7 P.248

2007-12-7 P.249 else if (!set) begin q <= 1; qn <= 0; end else begin q <= d; qn <= ~d; end end endmodule

3. 带异步清 0 置 1 的 JK 触发器 module JK_FF(CLK,J,K,Q,RS,SET); input CLK,J,K,SET,RS; output Q; reg Q; always @(posedge CLK or negedge RS or negedge SET) begin if(!rs) else if(!set) else 2007-12-7 P.250 Q <= 1'b0; Q <= 1'b1;

case({j,k}) 2'b00 : Q <= Q; 2'b01 : 2'b10 : 2'b11 : default: endcase end endmodule Q <= 1'b0; Q <= 1'b1; Q <= ~Q; Q<= 1'bx; 2007-12-7 P.251

4. 8 位数据锁存器 module latch_8(qout,data,clk); output[7:0] qout; input[7:0] data; input clk; reg[7:0] qout; always @(clk or data) begin if (clk) qout<=data; end endmodule 2007-12-7 P.252

5. 8 位移位寄存器 module shifter(din,clk,clr,dout); input din,clk,clr; output[7:0] dout; reg[7:0] dout; always @(posedge clk) begin if (clr) dout<= 8'b0; 2007-12-7 P.253

else begin dout <= dout << 1; dout[0] <= din; end end endmodule 2007-12-7 P.254

层次化设计方法分层原则 将所有的算术运算安排在同一层中, 状态机 随机逻辑 数据路径等逻辑类型作为独立的模块设计 模块的输入尽量不要悬空, 输出应尽量寄存 单个功能块应保持在 3000~6000 门之间,HDL 语言的行数不超过 400 行 尽量采用专用的 IP 核进行设计 2007-12-7 P.255

作业题 ( 用 Verilog Verilog HDL 语言设计 ) 1 设计一个最多允许 90 人参加的会议电子表决器, 只有当赞成票不少于总数的三分之二时, 议案被 通过 ; 否则被否决, 要求输出表决结果及相应的票 数 sum 2 设计一个加法器, 实现 sum a a a, a 0 a 1 a 2 a 3 的宽度都是 8 位 3 设计实现一个 8 点的 FFT 运算模块 0 1 2 a3 2007-12-7 P.256

作业要求 : 1 写出设计流程图 ; 2 源程序中加注释语句 ; 3 仿真通过, 给出仿真波形 ; 4 使用的软件平台: MaxplusII 2007-12-7 P.257