第2章 VHDL语言程序的基本结构 一个VHDL设计由若干个VHDL文件构成,每个文件主要包含五个部分的一个或全部:在max+plusⅡ中后缀为(VHD). 其中1~4为可分别编译 的源设计单元。 1.程序包 ( Package ) 2.实体 (Entity) 3.结构体 (Architecture)

Slides:



Advertisements
Similar presentations
阻塞操作. 在 linux 里,一个等待队列由一个 wait_queue_head_t 类型的结构来描述 等待队列的初始化: static wait_queue_head_t testqueue; init_waitqueue_head(&testqueue);
Advertisements

做实验过程中发现的问题: 新建时工程文件夹建立了,但所建实体文件并没存放在其中 文件名不能用汉字
实验四 利用中规模芯片设计时序电路(二).
《 E D A 技 术》 课 程 教 学 讲授:伍宗富 湖南文理学院电气与信息工程学院 2017年3月19日星期日.
第4章 VHDL设计初步.
5.4 顺序脉冲发生器、 三态逻辑和微机总线接口 顺序脉冲发生器 顺序脉冲 计数型 分类 移位型.
Oracle数据库 Oracle 子程序.
第三章 组合逻辑电路 第一节 组合电路的分析和设计 第二节 组合逻辑电路中的竞争与冒险 第三节 超高速集成电路硬件描述语言VHDL
VHDL數位電路實習與專題設計 文魁資訊-UE301
VHDL數位電路實習與專題設計 文魁資訊-UE301
8.9二进制振幅键控(ASK) 调制器与解调器设计
Ch01-2 Verilog語法 資料流(DataFlow)設計 行為(Behavior)設計
VHDL 硬體描述語言 數位電路設計實務 第四章 VHDL 的語言結構.
VHDL 硬體描述語言 數位電路設計實務 第六章 函數副程序以及套件程式庫.
EDA原理及应用 何宾
使用VHDL設計—4位元減法器 通訊一甲 B 楊穎穆.
EDA原理及应用 何宾
欢迎参加VHDL培训 VHDL培训教程 浙江大学电子信息技术研究所 电子设计自动化(EDA)培训中心
使用VHDL設計—向上&向下計數器 通訊一甲 B 楊穎穆.
使用VHDL設計-XOR_GATE 通訊一甲 B 楊穎穆.
走进编程 程序的顺序结构(二).
第14章 其它DSP设计库 14.1 总线控制库 14.2 复数信号库 14.3 Gates库 14.4 状态机函数库
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
使用VHDL設計--Moore Machine
陳慶瀚 機器智慧與自動化技術(MIAT)實驗室 國立中央大學資工系 2013年5月28日
时序逻辑电路实验 一、 实验目的 1.熟悉集成计数器的功能和使用方法; 2.利用集成计数器设计任意进制计数器。 二、实验原理
第12章 图像边缘检测器的设计与分析 12.1 系统设计要求 12.2 系统设计方案 12.3 主要LPM原理图和VHDL源程序
第二章 Java语言基础.
CPU结构和功能.
第五章 VHDL设计基础 本章重点: 本章难点: VHDL程序结构 VHDL的基本数据类型 VHDL的基本描述语句 基本组合逻辑电路设计
義守大學電機工程學系 陳慶瀚 第3章 VHDL Concurrent語法 義守大學電機工程學系 陳慶瀚
第六章 VHDL设计共享.
第五章 VHDL主要描述语句.
移相正弦信号发生器设计 采用直接数字综合器DDS发生器的设计 原理:图1是此电路模型图
使用VHDL設計—4位元ALU電路 通訊一甲 B 楊穎穆.
第一次上机安排 第六周 第七周 周一晚(提高1、2,通信001~012) 周二上(通信014~085) 周四上(通信086~154)
第4章 PHP流程控制语句.
C语言程序设计 主讲教师:陆幼利.
抢答器 设计一个2人抢答器。要求如下: 设计任务 1.两人抢答,先抢为有效,用发光二极 管显示是否抢到优先答题权。
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
8.4 ADC0809接口电路及程序设计.
计算机学院 数字逻辑实验的要求.
第二章 补充知识 2.1 总线和三态门 一、总线(BUS) 三总线结构 数据总线DB(Data Bus)
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
數位邏輯設計 VHDL.
信号量(Semaphore).
第4章 Excel电子表格制作软件 4.4 函数(一).
组合逻辑电路 ——中规模组合逻辑集成电路.
实验三 16位算术逻辑运算实验 不带进位控制的算术运算 置AR=1: 设置开关CN 1 不带进位 0 带进位运算;
使用VHDL設計-XOR_GATE 通訊一甲 B 楊穎穆.
第九节 赋值运算符和赋值表达式.
iSIGHT 基本培训 使用 Excel的栅栏问题
长春理工大学 电工电子实验教学中心 数字电路实验 数字电路实验室.
实验二 带进位控制8位算术逻辑运算实验 带进位控制8位算术逻辑运算: ① 带进位运算 ② 保存运算后产生进位
3.16 枚举算法及其程序实现 ——数组的作用.
使用VHDL設計-8x1多工器 通訊一甲 B 楊穎穆.
College of Computer Science & Technology
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
ASP.NET实用教程 清华大学出版社 第4章 C#编程语言 教学目标 教学重点 教学过程 2019年5月5日.
魏新宇 MATLAB/Simulink 与控制系统仿真 魏新宇
学习目标 1、了解基本运算符 2、运算符优先级.
第7章 VHDL设计应用实例 7.1 8位加法器的设计 7.2 分频电路 7.3 数字秒表的设计.
使用VHDL設計-七段顯示 通訊一甲 B 楊穎穆.
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
Programmable Logic System Design
陳慶瀚 機器智慧與自動化技術(MIAT)實驗室 國立中央大學資工系 2013年5月28日
第七章 基本逻辑电路设计.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
第九章 存储器和可编程逻辑器件 本章主要内容 半导体存储器 只读存储器 随机存取存储器 存储器容量的扩展 可编程逻辑器件
编译原理实践 6.程序设计语言PL/0.
Presentation transcript:

第2章 VHDL语言程序的基本结构 一个VHDL设计由若干个VHDL文件构成,每个文件主要包含五个部分的一个或全部:在max+plusⅡ中后缀为(VHD). 其中1~4为可分别编译 的源设计单元。 1.程序包 ( Package ) 2.实体 (Entity) 3.结构体 (Architecture) 4.配置(configuration) 5.库(library) 库用来存放已编译过 的实体、构造体、包 和配置。

2.1 VHDL语言设计的基本单元 基本单元:基本设计实体,可很简单,如门, 也可很复杂,如包含CPU的系统。 设计一个数字系统,首先要解决两个问题: 1) 输入、输出是什么; 2)内部完成什么功能。 对于1,由实体(Entity)说明来描述; 对于2,由构造体(Architecture)来描述。

实体说明部分 构造体说明部分 Entity mux is Generic (m: Time:=1ns); Port(do,d1,sel: IN Bit; q: out Bit); End mux; Architecture connect Of mux is Signal tmp: Bit; Begin cale: Process(d0,d1,sel) Variable tmp1,tmp2,tmp3:Bit; tmp1:=d0 AND sel; tmp2:=d1 AND (NOT sel); tmp3:= tmp1 OR tmp2; tmp<=tmp3; q<=tmp AFTER m; END PROCESS; END CONNECT; 实体说明部分 构造体说明部分 一个二选一数据选择器的描述

2.1.1 实体说明 实体的格式 1.类属参数说明 实体中定义电路单元和使用环境的接口,实体名必须与电路名相同。 ENTITY 实体名 IS [类属参数说明]; [端口说明]; END 实体名; 1)VHDL语言书写不分大 小写;(个别例外) 2)[ ]中内容有时可不要; 3)END后的实体名可省。 1.类属参数说明 1)类属参数说明(generic)用来为设计引入信息,如时间; 2)类属参数说明(generic)必须放在端口之前;

2.端口说明 3)类属参数说明(generic)常用来设计通用元件。 格式: Port(端口名{,端口名}:方向 数据类型名; … 端口名{,端口名}:方向 数据类型名); 1)端口名 电路外部引脚的名称,通常用英文字母加数字命名,如d0,A1, En,clk,LD. 2) 端口方向(模式) 端口方向定义外部引脚信息的方向,共有五种: in, out, inout, buffer, linkage 常用前4种 Linkage: 不指定方向,任何方向均可连接,只在文挡中使用。

端口模式可用下图说明:(黑框代表一个设计或模块) ●IN 信号进入实体但并不输出; ●OUT 信号离开实体但并不输入;并且不能在有内部反 馈情况下使用; ●INOUT 信号是双向的(既可以进入实体,也可以离开实 体); ●BUFFER 信号输出到实体外部,同时也可在实体内部反馈; BUFFER (缓冲)是INOUT(双向)的子集,但不是由外部 驱动。 端口模式可用下图说明:(黑框代表一个设计或模块) IN OUT BUFFER INOUT

3)数据类型 VHDL中有10种数据类型,但逻辑设计只用两种,另在库中还定 义了多种数据类型: Bit 2. bit_vector Bit :位逻辑数据类型,取值为0或1; bit_vector:位矢量,取值为一组二进制位。 Port(do,d1,sel: IN Bit; q: out Bit; bus:out bit_vector(7 downto 0)); Library ieee; 在编译时在指定的库、 Use ieee.std_logic_1164.all 包中寻找这种数据类型 Entity mu is Port(do,d1,sel: IN std_logic; q: out std_logic; bus:out std_logic__vector(7 downto 0)); End mu;

2.1.2 构造体 定义语句 构造体(Architecture)定义实体的实现,即电路的具体描述. 构造体的一般格式如下: Architecture<architecture_name 构造体名> of <entity_name> is --构造体声明区域 --声明构造体所用的内部信号及数据类型 --如果使用元件例化,则在此声明所用的元件 定义语句 begin –以下开始构造体,用于描述设计的功能 --concurrent signal assignments 并行语句信号赋值 --processes 进程(顺序语句描述设计) --component instantiations 元件例化 end<architecture_name>;

如: Architecture beh Of mux is 1.构造体名称的命名:一般以描述方法命名,描述方法一般有: 行为特性:behavioral 简写为beh 结构: structural 简写为 str 数据流: dataflow 如: Architecture beh Of mux is 2. 定义语句:位于architecture和begin之间,用于对构造体内部使用的信号、变量、数据类型和函数定义。 Architecture beh Of mux is signal n1:bit; … begin 1)信号为内部使用,不须加方向 2)信号应有名和数据类型 3.并行处理语句:位于begin和end 之间,描述构造体的行为和电路 连接关系。 所谓并行,指多个语句不以书写顺序执行。

y=a0s1s0+a1s1s0+a2s1s0+a3s1s0 =(a0s0+a1s0)s1+(a2s0+a3s0)s1 一数据选择器的构造体: architecture arch of mux4 is begin y<=((((a0 and not (s(0))) or (a1 and s(0)))) and not (s(1))) or (((a2 and not s(0))) or (a3 and s(0))) and s(1)); end archmux; y=a0s1s0+a1s1s0+a2s1s0+a3s1s0 =(a0s0+a1s0)s1+(a2s0+a3s0)s1

2.2 VHDL 语言构造体的子结构 2.2.1 BLOCK语句结构描述 一个构造体可以用几个子结构来构成,即一个系统可以用几个比较独立的模快来构成。 BLOCK语句结构 PROCESS语句结构 SUBPROGRAMS语句结构 2.2.1 BLOCK语句结构描述 1.BLOCK语句的结构 格式: 块结构名; block begin … end block 块结构名;

Entity mux is Port(d0,d1,sel: IN Bit; q: out Bit); End mux; Architecture connect Of mux is Signal tmp1,tmp2,tmp3 : Bit; Begin cale: block tmp1<=d0 AND sel; tmp2<=d1 AND (NOT sel); tmp3<= tmp1 OR tmp2; q<=tmp3 ; End block cale; END CONNECT; 一个二选一数据选择器的描述

2.块(block)和子原理图的关系:一个block相当于总图中的一个 子图,分块设计有利于编辑查错。 4.卫式block(Guarded block):指满足条件时,块语句执行,不满足 时不执行。 1)卫式块不能综合; 2)after语句不能综合; 3)当满足clk=1时执行。 例:… begin G1: block(clk=‘1’) q<=guarded d after 5ns; qb<=guarded not(d) after 7ns; end block G1; d q qb clk

2.2.2进程(process)语句结构描述 例如: 变量只在进程中定义和使用。 1.process语言结构 Begin … End process; Architecture connect Of mux is Signal tmp: Bit; Begin cale: Process(d0,d1,sel) Variable tmp1,tmp2,tmp3:Bit; tmp1:=d0 AND sel; tmp2:=d1 AND (NOT sel); tmp3:= tmp1 OR tmp2; tmp<=tmp3; q<=tmp AFTER m; END PROCESS; END CONNECT; 例如: 变量只在进程中定义和使用。

2.2.3 子程序(subprogram)语句结构描述 2. process中语句的顺序性:process中的语句按顺序执行。 process语句的启动:process( )括号内的量称为敏感量, 敏感量发生变化,启动进程。 Process的同步描述:当一个构造体内含有多个process时,进 程之间为并行的,进程之间能通信。 2.2.3 子程序(subprogram)语句结构描述 子程序有两类:1)过程(procedure) 2) 函数(function) 1.过程语句格式

过程中的参数可以是输入,也可以是输出。 Procedure 过程名(参数1,参数2,…)is [定义语句];(变量等定义) Begin [顺序处理语句]; (过程语句) End 过程名; 过程中的参数可以是输入,也可以是输出。 见教材例2-7 z: 输入,位矢量 x_flag:输出 ,布尔量 q:输入输出,整数 该过程实现将二进制数转换为整型数,x_flag为出错标志 在过程中,如不作说明,则认为in为常量,out和inout为变量。

如在过程调用后要将属性为in和inout的参数传递给信号,则要事先在过程中说明。(见例2-8) 2)过程语句中的顺序性 过程语句按顺序执行 调用:①将初始值传递给过程的输入参数 ②执行语句 ③将输出值拷贝到out和inout所定义的变量和信号 中去

如定义过程: Architecture rtl of ex is procedure cale (a,b : in integer; avg,max: out integer) is – 默认为变量 begin avg:=(a+b)/2 if a>b then max:=a; else max:=b; end if; end cale; 调用 过程 Begin cale (d1,d2,q1,q2); --错误,并行语句。 Process(d3,d4) Variable a,b: integer; cale(d3,d4,a,b);--正确 …

2.函数语句 子程序可定义在进程、包和构造体中。例2-9为定义在包中的例子。定义了一 个max 函数。 1)格式: function 函数名 (参数1,2…) return 数据类型名 is [定义语句] begin 顺序语句 [返回变量名] end 函数名; 子程序可定义在进程、包和构造体中。例2-9为定义在包中的例子。定义了一 个max 函数。

2)函数调用及结果返回 ①函数调用和一般高级语言相同; ②函数调用既可在并行语句中,也可在顺序语句中; ③函数和过程通常不必指定参数的矢量长度; ④例2-9是将max 函数放在了名为bpac的包中,而bpac 包应放在库中。 ⑤例2-10第1行应写为 library ieee; library newlib; ⑥由例2-10可知,bpac包存放在newlib库中。

2.3 包集合、库及配置 包集合、库及配置是三个可独立编译的源设计单元。

2.3.1库(Library) 库专门存放预先编译好的程序包、实体、构造体和配置等,这样它们就可以在其它设计中被调用。库的功能类似一个子目录或文件夹。使用库时,要进行库说明。 LIBRARY ieee; library newlib; 1.库的种类 有5种: ieee; std; 面向ASIC的库; work;用户定义库。 其中:ieee库为ieee正式认可的库,使用库中包时要说明; std库为VHDL的标准库,使用该库中数据可不必说明;但 使用库中TEXTIO包须说明。

VHDL类型,如bit,bit_vector 库名 程序包名 包中预定义内容 std standard VHDL类型,如bit,bit_vector ieee std_logic_1164 定义std_logic,std_logic_vector等 numeric_std 定义了一组基于std_logic_1164中定义的类型的算术运算符,如“+”,“-”,SHL,SHR等 std_logic_arith 定义有符号与无符号类型,及基于这些类型上的算术运算。 std_logic_signed 定义了基于std_logic与std_logic _ vector类型上的有符号的算术运算 std_logic_unsigned 定义了基于std_logic与std_logic_ vector类型上的无符号的算术运算

由工具商提供的库,在MAX-PLUSⅡ中,有ALTERA公司自己定义的库,名为ALTERA.里面 面向ASIC库: 由工具商提供的库,在MAX-PLUSⅡ中,有ALTERA公司自己定义的库,名为ALTERA.里面 存放两个程序包。 1) maxplus2; 2) megacore. WORK 库:现行作业库,使用不必说明。 用户定义库:由用户自己定义,使用需要说明。使用工作 界面窗口中的options 选项,在user libraries 选项中选择你所要存放库的路径。

2.库的使用 1)库的说明 如: library ieee; use ieee.std_logic_1164.all; 2) 库说明的作用范围 作用范围为它下面的一个设计(包括实体、构造体和配置等)。 当有两个实体时,应有两个库使用说明。(如例2-11)

包集合中存放信号定义、常量、数据类型、元件语句、函数、过程等,它可以编译,使用时用use语句。 2.3.2 包集合 包集合中存放信号定义、常量、数据类型、元件语句、函数、过程等,它可以编译,使用时用use语句。 如: use ieee.std_logic_1164.all; 包结构: package 包集合名 is [说明语句]; end 包集合名; Package body 包集合名 is 包的说明部分(包头) 包体(可选)

--包头说明 PACKAGE Logic IS TYPE Three_level_logic IS (‘0’, ‘1’, ‘Z’); CONSTANT Unknown_Value:Three_level_logic:=‘0’; FUNCTION Invert (input:Three_level_logic) RETURN Three_level_logic; END Logic;

--包体说明 PACKAGE BODY Logic IS --如下是函数的子程序体 FUNCTION Invert (input:Three_level_logic) RETURN Three_level_logic; BEGIN CASE input IS WHEN ‘0’=>RETURN ‘1’; WHEN ‘1’=>RETURN ‘0’; WHEN ‘Z’=>RETURN ‘Z’; END CASE; END Invert; END Logic;

关于包: 1)一个元件、函数或过程如只在包体中定义,则只能在 本包体中调用(例2-12) ,如要在其它设计中调用, 必须在包头中说明,建议函数和过程在包中定义; 2)包可以只有包头,无包体;(例2-13) 例2-13 在包upac中,定义了 k: 常量; instruction: 枚举类型(一种数据类型) cpu_bus: 4位位矢量。

2.3.3 配置 配置语句描述层与层之间,实体与结构体之间的连接关系。 如:一个电路,实体是一个(表示框图),但构造体可有多个(实现方法多种),可利用配置语句把不同的构造体连接起来,验证其性能。 格式: Configuration 配置名 of 实体名 is [语句说明];(如for 选配构造名 end 选配构造名;) end 配置名;

关于配置: ①配置只用于模拟仿真; ②综合工具忽略所有的配置,只对最后输入的结构体进行综合; 见例2-14,实体是一个计数器,构造体 small_count为8位计数器, 构造体 big_count为16位计数器。 如编译: Configuration small_count of counter is … end small_count; 则实现8位计数器;

Configuration big _count of counter is … end big_count; 则实现16位计数器; 如编译: Configuration big _count of counter is … end big_count; 则实现16位计数器; ③在例2-14中,由于max-plusⅡ中的std_std_logic包中无T_wlogic类 型,可改用ieee库中的std_logic_1164包,用std_logic类型 ④在例2-14中,实体中data_in和data_out均为整数类型(integer), 则自动设置为32位(由计算机定); ⑤例2-14,综合结果为32位输出的模216计数器。

第3 章 VHDL语言的数据类型及运算操作符

例 constant vcc: real:=5.0; 3.1 VHDL语言的客体及其分类 在逻辑设计中,VHDL语言常用的数据对象为信号、常量、变量,数据对象称为客体。 3.1.1常量(或常数) 常量在设计描述中保持某一规定类型的特定值不变 。如利用它可设计不同模值的计数器,模值存于常量中,不同的设计,改变模值仅需改变此常量值。 格式:CONSTANT 常量名:数据类型:=表达式; 常量赋值符号为“ : = ”。 例 constant vcc: real:=5.0;

例:variable cnt: integer range 0 to 255 :=10; 变量只在给定的进程中用于声明局部值或用于子程序中,可以是任意类型。赋值符号为“ : = ”。 变量说明格式: variable 变量名 :数据类型 约束条件:=表达式; 例:variable cnt: integer range 0 to 255 :=10; 变量赋值立即生效,不产生附加延时, 不能写成:y:=x after 10ns;

信号赋初值 用“:=” 程序中信号代入用“<=” 例: signal a: bit; 3.1.3 信号(Signal) 信号表示一条连线,通常在构造体、包集合和实体中说明, 信号是全局量,内部信号说明不要注明数据流向,外部信号(外部信号对应为in,out,inout,buffer)说明时signal省略。 信号也可在状态机中表示状态变量。信号赋值符号为“<=”。 信号说明格式: signal 信号名:数据类型 约束条件:=表达式; 信号赋初值 用“:=” 程序中信号代入用“<=” 例: signal a: bit;

2)信号的代入和语句的处理在时间上是分开的。 3.1.4 信号和变量值代入的区别 1)变量赋值是立即执行的; 2)信号的代入和语句的处理在时间上是分开的。 在例3-1的前部分,A,B,C,D为信号,当语句处理时,信号并不立即代入,当结束进程时,信号才被代入。 在例3-1的前部分,A,B,C,D为变量,当语句处理时,变量立即赋值。所以前后两部分结果不同。 下面是一个加法器的例子:

Port(op1,op2 :in integer range 0 to 15; Entity bcdadder is Port(op1,op2 :in integer range 0 to 15; result :out integer range 0 to 31 ); End dcdadder; Architecture behavior of bcdadder is constant adjustnum :integer:=6 --定义一常量:整数型,值为6 signal binadd :integer range 0 to 18; --定义一个信号,以保存两数二进制相加的和.

binadd<=op1+op2; --信号赋值 process(binadd) Begin binadd<=op1+op2; --信号赋值 process(binadd) variable tmp : integer:=0; -- 定义一个变量,并赋初值为0 begin if binadd>9 then tmp:=adjustnum; --变量赋值,立即起作用 else tmp:=0; end if; result<=binadd+tmp; end process; End behavior;

3.2 VHDL 语言的数据类型 3.2.1 标准的数据类型 标准的数据类型共10种,见下表。

数据类型 含 义 整数(integer) 32位,-2147483647~ 2147483647 实数(real) 浮点数,-1.0E+38~+1.0E+38 位(bit) 逻辑“0”或“1” 位矢量(bit_vector) 多位“0”和“1”的组合 布尔量(boolean) 逻辑“真”或逻辑“假”: true 和 false 字符(character) ASCII字符 时间(time) 时间单位:fs,ps,ns,μs,ms,sec,min,hr 错误等级(severity level) Note, warning,error,failure 自然数(natural) 正整数(positive) ≥0的整数 >0的整数 字符串(string) 字符矢量

格式:type 数据类型名 {,数据类型名} 数据类型定义; 3.2.2 用户定义的数据类型 VHDL允许用户自己定义数据类型: 格式:type 数据类型名 {,数据类型名} 数据类型定义; 由用户定义的数据类型可有多种: 枚举;整数;实数;浮点数;数组;存取;文件;记录;时间 3.2.3 用户定义的子类型 VHDL允许用户自己给数据类型加以限制,形成子类型: 格式 subtype 子类型名 is 数据类型名 范围;

3.2.4 数据类型的转换 功能 函数名 1)std_logic_1164包集合 To_stdlogicvector(A) To_bitvector(A) To_stdlogic(A) To_bit(A) Bit_vector → std_logic_vector std_logic_vector→ Bit_vector Bit → std_logic Std_logic→ bit 2)std_logic_arith包集合 Conv_std_logic_vector(A,位长) Conv_integer(A) Integer,unsigned,signed→ Std_logic_vector Unsigned,signed→ integer 3)std_logic_unsigned包集合 Std_logic_vector → integer

数据类型的说明: 1)boolean 型 常量、信号和变量均可说明为boolean 型,综合工具将false译为0,将true译为1。 2)integer 型 没有定义长度,由工具而定,一般为32位。不用32位时, 可采用: a)自定义类型,如: type digit is integer range 0 to 9; b) 直接注明范围,如:port( x: in integer range 0 to 9);

3) 位和位矢量 VHDL标准中只定义了bit和bit_vector,而bit只能取“0”和“1”,给设计带来限制: a) 不能描述三态 b)不能使同一信号具有多个驱动源 c)不能给信号赋未知值 d)不能给信号赋无关值 解决方法:由ieee制定了标准化数据类型。 在ieee.std_logic_1164包中定义了 std_ulogic类型 具有9种不同的值(见p44) Std_logic 类型 是std_ulogicd的决断子类型

含义:当一个信号有多个驱动器驱动时,则调用定义的决断函数以解决冲突,并决定给信号赋什么值,这可用在三态总线中。 4) Character 字符型 由ASCII码表示的128个字符,要用单引号标注,如‘c’,多数综合工具支持VHDL-87定义的字符,可综合。 5) std_logic是决断类型 含义:当一个信号有多个驱动器驱动时,则调用定义的决断函数以解决冲突,并决定给信号赋什么值,这可用在三态总线中。

Use ieee.std_logic_1164.all; Entity ex is Library ieee; Use ieee.std_logic_1164.all; Entity ex is port(d,c,en1,en2: in std_logic; dbus: out std_logic); End; Architecture rtl of ex is Begin dbus<=d when en1=‘1’ else ‘Z’; dbus<=c when en2=‘1’ else ‘Z’; en2 en1 c d dbus

使用std_logic型后,缺点是如误将两个驱动器驱动同一信号,也不会有出错报告。 6)关于数组(array) type 类型名 is array 范围 of 原数据类型名 Type A_4 is array (3 downto 0) of std_logic; 表示一维数组(4行1列,每个元素为一位) b) Type A_43 is array (3 downto 0) of std_logic_vector(2 downto 0); 表示一维数组(4行1列,每个元素为三位的位矢量) c) Type A_453 is array (3 downto 0, 4 downto 0) of std_logic_vector (2 downto 0); 表示二维数组(4行5列,每个元素为三位的位矢量)

如一个信号a,为A_453类型,即如下形式: “101” 3 2 1 4 3 2 1 0 “011” a(1,2) a(1,2)(0)

如: type state_type is (start,idle,waiting,run,error); 7) 枚举类型 格式:type 名 is (.., .., ..); 枚举类型经常用时序电路的设计中,时序电路有许多状态,这些 状态在设计中可编码,如用枚举类型,就可以自己不去编码,而 交给工具。大多数综合工具都支持枚举类型。 如: type state_type is (start,idle,waiting,run,error); signal state: state_type; 表示state可取5个值,综合工具将每个状态转换为3位矢量,表示5种不同值。

如信号 A 为bit_vector类型,下列的赋值均为正确的: A<=“10011” (二进制) 8)关于转换函数 如信号 A 为bit_vector类型,下列的赋值均为正确的: A<=“10011” (二进制) A<=B”10011” (二进制,和上面等价) A<=O”456” (八进制) A<=X”FFA6” (十六进制) A<=259 (十进制,必须为常量) A<=4.6E-4 (综合工具不支持) 为改善可读性,可加下划线: A<=B”1100_0110_1011” 等价于 A<=B”110001101011” A<=X”C3_D8” 等价于 A<=X”C3D8” *有下划线时,前面的进位标志不能省略,下面是错的: A<=”1100_0110_1011”

VHDL语言为强类型语言,不允许不经转换而把 Bit_vector赋给std_logic_vector,如: A 为Bit_vector,B为std_logic_vector,当把A赋给B时,必须使用转换函数to_stdlogicvector(A) 9)关于记录类型: 格式: type 数据类型名 is record 记录定义; end record;

高级综合工具支持记录类型,但对记录中的数据类型有限制,故在仿真中用的更多。 例如: Architecture beh of ex is Type data_data is record Year: integer range 1996 to 2099; Month: integer range 1to 12; Date:integer range 1 to 31; End record; Signal d: data_data; Begin d.year<=1999; d.month<=4; d.date<=8; End; 等效为: D<=(1999,4,8); 高级综合工具支持记录类型,但对记录中的数据类型有限制,故在仿真中用的更多。

9) 关于子类型 子类型通常是对已有的一些类型作一些限制。 格式:subtype 名 is 数据类型名 [范围]; 如: subtype abus is std_logic_vector(7 downto 0); 则 abus类型为8位矢量。

在VHDL语言中,有时可以用所描述的上下关系来判断某一数据 的数据类型。 3.2.5 数据类型的限定 在VHDL语言中,有时可以用所描述的上下关系来判断某一数据 的数据类型。 (1)用文字的上下关系判断 signal a : std_logic_vector(7 downto 0); a<=“10011010”; ( 则“10011010”必为std_logic_vector型) (2)在数据前加类型名 a<=std_logic_vector“10011010”;

3.2.6 IEEE标准 “STD_LOGIC”、”STD_LOGIC_VECTOR” Std_logic型数据可有9种值 ‘U’ (初始值);‘X’ (不定);‘0’;‘1’;‘Z’(高阻); ‘W’(弱信号不定);‘L’(弱信号0);‘H’(弱信号1); ‘-’(不可能情况)

3.3 VHDL语言的运算操作符 ·算术运算符(Arithmetic operators) + 加 - 减 * 乘 / 除 ** 乘方 + 加 - 减 * 乘 / 除 ** 乘方 mod 求模 rem 求余 ** 指数 abs 求绝对值 + 正(一元运算) 负(一元运算)

·关系运算符 = 等于 /= 不等于 < 小于 <= 小于或等于 > 大于 >= 大于或等于 注:其中‘ <=’ 操作符也用于表示信号的赋值操作

·并置运算符 and 逻辑与 or 逻辑或 nand 与非 nor 或非 逻辑运算符 xor 异或 xnor 同或 not 逻辑非 & 连接,将两个对象或矢量连接成 维数更大的矢量 ·并置运算符

说明: 关系运算:关系运算产生一个boolean值,即ture或false,关系运算符可以直接用于integer,bit_vector和std_logic_vector等。运算符= 和/=可用于所有已定义的数据类型。 大多数综合工具都支持所有的关系运算。 算术运算符:算术运算符适用于整数、实数和时间等数据类型,如要对std_logic_vector类型进行算术运算,则必须使用程序包Ieee.std_logic_unsigned或ieee.std_logic_signed 综合工具一般支持“+”、“-”、“*”和分母为2乘方时的“/”

第 4 章 VHDL语言构造体的描述方法 4.1 构造体的行为描述方法 4.1.1代入语言 行为描述是对系统的数学模型的描述,较抽象。 第 4 章 VHDL语言构造体的描述方法 4.1 构造体的行为描述方法 行为描述是对系统的数学模型的描述,较抽象。 行为描述的程序特点是大量采用算术运算、关系运算、惯性延时和传输延时,有些描述难以综合。 4.1.1代入语言 一般格式: 信号量<= 敏感信号量表达式; 如: a<= b; (只要b变化,就代入新的值) 如: z<= a nor(b nand c); (只要a、b、c变化,就代入新的值)

a<=b after 5ns; (b发生变化后5ns代入新值) 具有延时的代入语句: a<=b after 5ns; (b发生变化后5ns代入新值) 例4-2为有条件的代入语句: with sel select q<=i0 after 10 ns when 0, i1 after 10 ns when 1, i2 after 10 ns when 2, i3 after 10 ns when 3, ‘X’ after 10 ns when others; sel<=0 when a=‘0’ and b=‘0’ else 1 when a=‘1’ and b=‘0’ else 2 when a=‘0’ and b=‘1’ else 3 when a=‘1’ and b=‘1’ else 4;

4.1.2 延时语句 1)惯性延时(inertial) a)为VHDL的默认延时; 尖峰脉冲不能传输(如果使用after语句) 常用作元件延时 2)传输延时(transport) a)脉冲均可传输,与宽度无关 可以很好地表示接连线延时 q1<=a after 5 ns; 惯性延时 q2<=transport a after 5ns; 传输延时

(综合工具不支持延时) a b b<=a after 5 ns; b<= transport a after 5 ns; a b

generic (类属说明语句)用于不同层次之间的信息传递。 如:位矢量长度,数组长度,器件延时时间。 4.1.3 多驱动描述语句 创建一个驱动器可以由一条信号代入语句来实现。 当出现下例情况,称为多个驱动器b、d共同驱动一个信号a. a<=b after 5 ns; a<=d after 5 ns; 这时, a的值由判决函数来确定。(见例4-3) (综合不支持判决函数) 4.1.4 generic (类属说明语句) generic (类属说明语句)用于不同层次之间的信息传递。 如:位矢量长度,数组长度,器件延时时间。

例4-4定义了一个与门,与门输出的上升和下降延时时间用类属说明generic定义了两个参数:(rise,fall). 在例4-5中,描述一个由三个与门构成的电路,当调用例4-4定义的与门时,用语句: U0: and2 generic map(5 ns,5 ns) U1: and2 generic map(8 ns,10 ns) U2: and2 generic map(9 ns,11 ns) 这里三个门的延迟时间均不相同。

4.2 构造体的寄存器传输(RTL)描述方式 行为描述的可综合性差,RTL描述方式是真正的可以进行逻辑综合 的描述方式,RTL描述也称为数据流描述。 4. 2 .1 RTL描述方式的特点 1)采用寄存器硬件的一一对应的直接描述; 2)采用寄存器功能描述。 RTL常用句法: Case---when ; with—select—when; 布尔方程。 例4-6为四选一数据选择器的RTL描述。属寄存器功能描述方法。(用了when—else语句)

4.2.2 使用RTL描述方式应注意的几个问题 例4-8是二选一数据选择器的例子,用了寄存器硬件的一一对应的直接描述;(描述电路的结构) 1)“X”状态的传递 “X”状态的传递是指不确定信号的传递,它使逻辑电路产生不确定的结果。这种不确定的结果,,对RTL仿真是允许的,但对综合后的门级电路仿真是不允许的。 例4-9的含义: 当sel=1 则 y=0, 否则 y=1; 这意味着当sel=‘X’时,y=1。 其实设计者要想表达的意思是相同的,但得到的结果不同。在编程时要注意。 例4-10下一段程序为改进方法。 例4-10的含义: 当sel=0 则 y=1, 否则 y=0; 这意味着当sel=‘X’时,y=0。

2. 寄存器RTL描述的限制(指对寄存器的描述) 1)禁止在一个进程中存在两个寄存器描述 例: process(clk1,clk2) begin if (clk1’event and clk1=‘1’) then y<=a; end if ; if (clk2’enent and clk2=‘1’) then z<=b; End process;

2)禁止使用if 语句中的else项 (使用if 语句描述寄存器功能时) 例: process(clk1) begin if (clk’event and clk=‘1’) then y<=a; else --禁止使用 y<=b; end if ; End process; D Q clk a y

3. 关联性强的信号应放在一个进程中 3)寄存器描述中必须代入信号值 见例4-13(即寄存器作为一个实体,要随变量变化。) 例中,tmp为变量,而y为寄存器的输出信号,当变量tmp 变化时,y要跟着变化。 3. 关联性强的信号应放在一个进程中 在图4-7中,输入有5个信号,输出有4个信号,其中a,zin,yin和dout和eout关联,a,b,c和gout关联,b和fout关联。则在写程序时,将着三种情况分别 写在三个进程中。例4-14和例4-15描写的结果相同,但4-15要好。

所谓构造体的结构描述,就是在多层次的设计中,高层次的设计模块调用低层次的设计模块,或者直接调用门电路来设计复杂逻辑电路。 4.3 构造体的结构描述方式 所谓构造体的结构描述,就是在多层次的设计中,高层次的设计模块调用低层次的设计模块,或者直接调用门电路来设计复杂逻辑电路。 这种描述结构清晰,对设计人员的要求较高。 4.3.1构造体结构描述的基本框架 aa u1 u3 u2 u4 ab d0 d1 sel & 1 ≥1 q nsel 例4-16 为一个二选一的例子。 q=(d0 and sel) or (d1 and (not (sel)))

1. ASIC级结构描述:一般是门级或更低层次 编程的思路为: 1)先说明要调用的三 个元件: and、or2、inv 2)用 PORT MAP语句 进行连接元件。 aa u1 u3 u2 u4 ab d0 d1 sel & 1 ≥1 q nsel 结构描述的三个层次: 1. ASIC级结构描述:一般是门级或更低层次 例4-17是 ASIC级结构描述的一个例子(门级描述),形成了多个块(block),每个block为一个ASIC芯片。将这些ASIC芯片放入库中,以备调用。

2.插件板级结构描述:由多个ASIC芯片形成插件板。如 例4-18,一个插件板为一个构造体。存入库中时将其视作元件。 3.系统级结构描述:由多个插件板形成系统。如例4-19。 在实际设计中一个元件,或一个BLOCK,或一个实体,经编译后均可认为是一个设计单元。

4.3.2 元件说明语句和元件例化语句 元件说明是对VHDL模块的说明,使之可在其它模块中使用,元件说明可放在程序包中,也可以在某个设计的结构体中声明。 元件例化指元件的调用。 元件说明语法: Component<元件实体名> Generic <参数说明>; port <元件端口信息,同该元件实现时 的实体的port部分>; End component;

<例化名>:<实体名,即元件名>port map(<端口列表>) --元件例化: <例化名>:<实体名,即元件名>port map(<端口列表>) 例如: u2: and2 port map (nsel,d1,ab); 意思是将与门的输入端(a,b)接(nsel,d1),输出端(c)为ab. 也可写成: u2: and2 port map (a=>nsel,b=>d1,c=>ab); 第一种写法为位置映射法,第二种写法为名称映射法。 & a b c and2

第 5 章 VHDL语言的主要描述语句

VHDL 常用语句分并行(Concurrent)语句和顺序(Sequential)语句: 并行语句总是处于进程(PROCESS)的外部。所有并行语句都是并行执行的,即与它们出现的先后次序无关。如when..else语句 顺序语句(Sequential): 顺序语句总是处于进程或子程序的内部,并且从仿真的角度来看是顺序执行的。如if-then-else语句

5.1顺序描述语句 5.1.1 wait 语句 wait 语句的四种类型: wait 无限等待 wait on 敏感信号量变化 wait until 条件满足 wait for 时间到

Wait on 格式:wait on 信号[,信号]; 下面两段程序等效: process(a,b) process begin begin y<=a and b; y<=a and b; end process; wait on a,b; end process; 可综合 高级工具可综合 不能在一段程序中既用进程敏感量又用wait on 语句。

2. Wait until 3. Wait for process begin wait until a=‘1’; c<=not a; end process; 可综合 process begin c<=not a; wait until a=‘1’ for 10 ns; end process; 不可综合,在仿真中使用 4. 多条件wait语句用的不多;5. 超时等待是处理等待时间过长的方法。 *综合工具对时间量不支持。

断言语句用于仿真,便于调试中进行人机会话。 5.1.2 断言 (assert)语句 断言语句用于仿真,便于调试中进行人机会话。 格式: ASSERT 条件 [report 输出信息][severity 级别] 条件为真,向下执行;条件为假,输出错误信息,信息中的字符串用“ ”,以及错误等级。 VHDL错误级别有:failure, error, warning, note 5.1.3 信号代入语句 格式: 目的信号量<=信号量表达式; 1)“<= ”和小于等于号相同,由文中内容区别; 2)代入符号两边的信号量的位长度应一致。

5.1.4 变量赋值语句 格式: 目的变量 := 表达式; 例: a:=2; b:=“11101011”; 5.1.5 if 语句 5.1.4 变量赋值语句 变量赋值只能在进程或子程序中使用,无法传递到进程之外。 格式: 目的变量 := 表达式; 例: a:=2; b:=“11101011”; 5.1.5 if 语句 2 . 二选择控制 If 条件 then 顺序处理语句; else end if ; 门闩控制 If 条件 then 顺序处理语句; end if ;

算:=,/=,>, <等,也可用 逻辑运算操作的组合表达式。 3 . 多选择控制 If 条件 then 顺序处理语句; elsif 条件 then … else end if ; If 语句常用于选择、比较和 译码等场合; *if 后的条件判断,输出为逻 辑量,即“真”或“假”,故条 件表达式中只能使用关系运 算:=,/=,>, <等,也可用 逻辑运算操作的组合表达式。 例5-6 为一个D触发器的描述。 d q clk

例5-8 为四选一数据 选择器描述。 例5-7 为二选一数据选择器描述。 MUX a b sel c 1 MUX input(0) 例5-8 为四选一数据 选择器描述。 MUX input(0) sel(1) y 1 sel(0) 2 3 input(1) input(2) input(3)

5.1.6 case 语句 格式: case 表达式 is when 条件表达式=>顺序处理语句; … end case; 四种形式: when 值=>顺序处理语句; when 值|值|…|值=>顺序处理语句;(表示“或”) when 值 to 值=>顺序处理语句; when others=>顺序处理语句; 例5-9 为一个数据选择器程序,编程思路: 1) 将位信号a,b转换为整型数sel; 2) 用case语句判断sel值,决定选择什么数据。

1)sel<=‘0’;(因为sel为整型数,而‘0’表示0为位量) 2)程序中sel为信号,并在进程中使用,而在进程中 例5-9 有两处错误: 1)sel<=‘0’;(因为sel为整型数,而‘0’表示0为位量) 2)程序中sel为信号,并在进程中使用,而在进程中 信号值的改变要等进程执行结束后进行,这和编 程的要求相异。 * 应把sel在进程中定义为变量,并把所有的sel<= 改为sel:= 。 例5-10 为3-8译码器的例子 2 1 5 4 3 7 6 Y(7~0) c b a & EN G2B G2A G1 编程思路: 1)将码输入信号c,b,a合成为位矢量(indata)(用并置符&); 2) 用if语句判断使能信号是否有效,如有效,则进入3); 3)用case语句判断输出。

例5-11 为二--十进制编码器的例子。 1)为普通编码器,不能同时多个信号有效; 2)当无信号输入或有多个信号有效时,程序处理为使 y=“XXX”,可使电路简单。 例5-12 为二--十进制优先编码器的例子。 本例使用多条件if语句进行逐条判断,完成优先编码,例 中input(0)优先级最高。

格式: for 循环变量 in 离散变量 loop 顺序处理语句; end loop[标号]; 例:asum: for i in 1 to 9 loop sum:=i+sum; end loop asum; 其中:i为循环变量,循环变量不必说明。

例5-13 描述一个奇偶校验电路: i为循环变量(整数),不必说明; tmp为变量,不能出进程; y为信号,可以在进程之外; 只有单循环时,标号可不要。 2) While 条件 格式: [标号]: while 条件 loop 顺序处理语句; end loop;

例: i:=1; sum:=0; sbcd: while (i<10) loop sum:=i+sum; i:=i+1; end loop sbcd; 例5-14同样是一个奇偶校验电路的描述: 使用了while…loop语句; 在进程 中i作为整型变量不必要定义(如定义也可); For…loop语句较while…loop语句使用的多。

5.1.8 next语句 格式: next [标号][when 条件]; 在loop语句中Next语句用来跳出本次循环。 Next语句执行时将停止本次迭代,而转入下一次迭代。Next后的标号表明下一次迭代的起始位置,而when 条件表明next语句执行的条件。 如果next语句后面既无标号,又无when条件说明,则只要执行到该语句就立即无条件地跳出本次循环,从loop语句的起始位置进入下一次迭代。

5.1.9 exit语句 格式: exit [标号][when 条件]; exit语句也是loop语句中使用的循环控制语句。与 Next语句不同的是,执行exit语句将结束循环状态,从loop语句中跳出。 如果exit语句后面既无标号,又无when条件说明,则只要执行到该语句就立即无条件地从loop语句中跳出,结束循环状态。继续执行loop语句后继语句。

5.2 并发描述语句 5.2.1进程(process)语句 进程语句的几个特点: *一个构造体中可以有几个进程,它们并发运行,进程中 可以存取构造体或实体中所定义的信号; *进程内的语句都是顺序执行的; *为启动进程,应包含一个显式的敏感表,或包含一个 wait语句; *进程间的通信是通过信号量传递的。

5.2.2 并发代入语句( <=) 信号代入语句在进程内使用,作为顺序语句;在进程外 使用时,作为并发语句。 5.2.3 条件代入语句 格式: 目的信号量<=表达式1 when 条件1 else 表达式2 when 条件2 else … else 表达式 n; 例5-17为用条件代入语句描述数据选择器的例子。

条件代入语句和if语句的区别: 5.2.1 选择信号代入 If 只能用在进程内部,为顺序语句; 条件代入when后一定要有else,而if 后可以没有else,当if 后没有else时,可以是电路具有保持功能,形成锁存器。由于条件代入中不能自身代入,故不能形成锁存器。 5.2.1 选择信号代入 格式: with 表达式 select 目的信号量<= 表达式 1 when 条件1, 表达式 2 when 条件2, … 表达式 n when 条件n;

5.2.5 并发过程调用语句 例5-18和5-19功能相同,均为描述数据选择器。选择条件代入语句和顺序语句case类似。 在例2-7中定义了一个名为vector_to_int的过程,一个过程有完整的输入和输出,在调用时: *在前面加标号; *并发过程调用语句应带有in,out或inout参数, 参数放在( )内; * 并发过程调用可有多个返回值; *并发过程调用时,返回量一定要是信号; *在进程中也可调用过程。

5.2.6 块(block)语句 格式: 标号:block 块头 {说明语句}; begin {并发处理语句}; end block 标号; 1)块头通常用语信号的映射及参数 的 定义,常用下列语句: generic, generic_map port, port_map 格式: 标号:block 块头 {说明语句}; begin {并发处理语句}; end block 标号; 2)说明语句和构造体语句说明语句 相同,主要是对该块所要用到的客 体加以说明。可说明的项目有: * use子句; *子程序说明及子程序体; *类型; *常量说明; *信号说明; *元件说明。 3.并发语句常用于结构 体的结构化描述。

例5-20 为一个简单CPU芯片设计实例框架。芯片包含一个ALU和一个REG8。而REG8又由8个子模块组成,子模块分别为:REG1,…,REG8。在每一个块内有局部信号、数据类型、常数等说明。 程序的前6行,定义了一个数组tw32(一维,32个元素),存放在Bit32包中; 实体为CPU,定义clk,interrupt为输入,adder为输出,data为inout(双向); 构造体名为cpu_blk,内部包括两个大的block(ALU和REG8),其中REG8块中又包含8个子块( REG1,…, REG8);

说明: 1)clk, intrrupt, adder, data, 为端口信号,全局使用; 2)信号ibus,dbus是在构造体名和begin之间定义的,可以 在构造体内部使用; 3)qbus是在ALU块内部定义的,只能在ALU内部使用, 另外在REG1中也定义了一个qbus,这两个信号不相同 (建议不要采用同名定义); 4)block中可以嵌套,内层block可使用外层块的信号,但 外层块不能使用内层块的信号。

端 口 函 数 5)块是一个独立的子结构,通过port map和generic map语句可以实现块内和块外信息传递 语句把块内的信号和块外的信号相连接。 函 数 ALU BLOCK abus ibus bbus dbus ctbus comt D_out 构造体 data 端 口

5.3 其它语句和有关规定 5.3 .1 命名规则和注释的标记 1)std_logic和std_logic_vector中的不定值‘X’要大写; 2) 在VHDL中使用的名字: 1. 首位一定是英文字母; 2. 只能使用英文字母和数字,以及‘_’,字名最后不能用 ‘_’ ; 3. 不能连续使用‘_’ 。

5.3.2 attribute(属性)描述与定义语句 属性描述与定义语句可以从所指定的客体中获得关心的数据或信息。 通过预定义属性描述语句,可以得到客体的有关值、功能、类型和范围。 预定义的属性类型有: 数值类,函数类,信号类,数据类型类和数据范围类。 1. 数值类属性 用于得到数组,块或者数据的有关值。分为3个子类: a) 一般数据的数值属性; b) 数组的数值属性; c) 块的数值属性。

如将 0 TO 9改为 9 DOWNTO 0, 则情况就不一样了。 一般数据的数值属性 (共4种) 格式:客体’属性名。 一般数据的数值属性 (共4种) 格式:客体’属性名。 1. T’LEFT——得到数据类或子类区间的最左端的值; 2. T’RIHHT——得到数据类或子类区间的最右端的值; 3. T’HIGH——得到数据类或子类区间的最高端的值; 4. T’LOW——得到数据类或子类区间的最低端的值. 例: TYPE number IS 0 TO 9; 则: I:=number’LEFT; --I:=0 I:=number’RIGHT; --I:=9 I:=number’HIGH; --I:=9 I:=number’LOW; --I:=0 如将 0 TO 9改为 9 DOWNTO 0, 则情况就不一样了。

Tim1<=tim’left;--得到sec Tim2<=reverse_tim’left;--得到min(应该为month) 例5-23 是枚举类型的属性分析 TYPE tim IS (sec, min, hous, day, month, year); 这种枚举,将左(sec)视为低位,右(year)视为高位. TYPE reverse_tim IS tim RANGE month DOWNTO min; Tim1<=tim’left;--得到sec Tim2<=reverse_tim’left;--得到min(应该为month) *教材(p96) tim5和tim6可能有误。 2) 数组的数值属性 A’length—得到数组A的长度。 例:Type bit4 is array (0 to 3)of bit; len1:=bit4’length; ---len1=4

数值属性也可用于枚举类型,见例5-25: 1. t_4val类型为位,有四种取值:‘X’,’0’,’1’,’Z’ 。 2. t_4valx1类型为一维数组,其中 (t_4val’low to t_val4’high)和(0 to 3)等效。 t_4valx1型数组表示:数组中有四个元素,每个 元素为一位,取值为t_4val型。 3. t_4valx2类型为一维数组,4×1,其中每个元素 为四位,取值为t_4valx1型。 4. t_4valmd类型为二维数组,4×4,每个元素为 一位,取值为t_4val型。 5. Andsd为常量,类型为t_4valx2。(用数组表示 ‘X’、’0’、’1’、’Z’四个两之间的“与”函数值)

5. Andmd为常量,类型为t_4valmd。(用数组表 示‘X’、’0’、’1’、’Z’四个两之间的“与”函数值) 在例5-26中: len1和len2 均得到一维数组的长度=4; len3得到得是二维数组的第一区间(行)长度=4; len4得到得是二维数组的第二区间(列)长度=4; 3) 块的数组属性 ① ’structure ② ’behavior 1. 用于块的构造体中 2. 如块有标号说明,或构造体有构造体说明, 并在块和构造体内不存在component语句,那么

3.如果在 块和构造体中只有component语句或 被动进程,那么属性’structure得到true信息。 ’behavior将得到true信息。 3.如果在 块和构造体中只有component语句或 被动进程,那么属性’structure得到true信息。 例题5-27分析:描述了一个四位移位寄存器 1)程序开始说明了元件dff; 2)从第一个begin到q=>right描述了以下结构: d q d q cp left right dff clk i1 i2 i3 u1 u2 u3 u4

3)进程checktime用来检测时钟跳变间隔是否为 20ns,如不是,输出错误信息和错误级别 spike on clock (时钟破坏) 错误级别: warning (警告) 其中:last_time是时间型变量; 4)在构造体中,第一个begin中只有元件说明, 进程checktime中无代入语句,(这种进程称 为被动进程或无源进程),所以如对构造体 施加‘behavior和’structure属性,则 structural’behavior-----得到“假”; structural’structure-----得到“真”。 用来检测构造体的描述方式。

2.函数类属性 属性以函数的形式,让设计人员得到有关数据 类型、数组、信号的某些信息: 1)数据类型属性函数 首先应指定一个输入自变量,如 x 。 则:’pos(x) ----得到x值的位置序号 ’val(x) ----得到位置序号为x的值 ’succ(x) ----得到输入x值的下一个值 ’pred(x) ----得到输入x值的前一个值 ’leftof(x) ----得到邻接输入x的左边值 ’rightof(x) ----得到邻接输入x的右边值

例5-28说明:将物理量μA、μV、ohm转换为 整数的实例。 1)包ohms_law定义了current,voltage ,resistance 三种数据类型及基本单位,如mA,V等。 2)实体部分 i e r 框图中的三个量分别用包中 定义的类型。

3)构造体定义三个变量(整型数):convi, conve, int_r 然后将输入量转换为整型数进行运算,最后将 运算结果为电阻量输出。 程序中: convi:=current’pos( i ) --得到输入i的位置序号, 由于i的基本单位为微安,范围为0-1000000, 所以当输入为10μA时,序号为10,convi=10. resistance’Val(int_r) 将整数int_r转换为单位为 ohm的电阻量。 其他属性比较容易理解,请参考例5-29。

2)数组属性函数: 利用数组属性函数,可得到数组的区间信息。 ’left(n) –得到所引号为n的区间的左端位置号。n 指多维数组中所定义的多维区间的序号, n缺省时代表对一维区间操作。 ’right(n) –得到所引号为n的区间的右端位置号。 ’high(n) –得到所引号为n的区间的高端位置号。 ’low(n) –得到所引号为n的区间的低端位置号。 在递增区域:数组’low=数组‘left; 数组’high=数组‘right 。

在递减区域:数组’low=数组’right; 数组’high=数组’left 。 例5-30说明:随机存取存储器 1)包p_ram: 定义: a)一维数组:ram_data(0-511)(每个元素 为整型数); b)常量 : x_val= -1; c)常量 : z_val= -2 . 2)实体 ram: R A M data_in addr cs r_wb data

3) 构造体 a)进程:main_proc,敏感量(cs,add,r_wb) b)定义变量 ram_data1, 数组 ,暂存存储器内容; ram_init, 清零标志,布尔量,初值为‘假’。 c)给数组ram_data1清零: (应用ram_data1’low to ram_data1’high loop) d)以下流程图为存取过程:

cs=‘x’ Y 或r_wb=‘x’ Data= -1 N cs=‘0’ Data= -2 片选无效 片选有效 (写) r_wb=‘1’ 地址为 -1或-2 片选有效 片选无效 (写) (读) 将ram_data1中地址为 addr中的 数送到输出 端data. 给出出错信息及等级 并将输出data置为-1。 data_in=>ram_data1(addr) ram_data1(addr)=>data

3)信号属性函数 信号属性函数得到信号行为信息。 s’event 返回布尔值。反映在当前相当小的一 段时间内,是否有事件发生。(含义更广泛) b)s’active 返回布尔值。反映在当前相当小的一 段时间内,是否信号发生变化。 c)s’last_event 返回时间值。反映信号前一个事件 发生到现在所经过的时间。 d)s’last_value 返回一个值。反映信号最后一次 改变前的值。 e)s’last_active 返回时间值。反映信号前一次改变 到现在所经过的时间。

例5-31:想用来检测上升沿,即0→1,但如出现 由X →1,仍然作为条件满足。 P105页,最后三行,增加了(clk’last_value=‘0’), 则,如条件满足,一定是0→1。 例5-32:利用‘last_event属性对d触发器信号变化 的建立时间进行检查的实例。 1)在实体中引入了一个无源进程(进程中没有 代入语句),检查上一次d的 变化到clk的上 升沿时间是否大于setup_time. 2) 实体中引入进程,可以被所有构造体共享。 (本例的 检查也可以放在构造体中进行)

属性’active和’last_active由信号发生变化或事件 发生时被触发,当一个模块的 输入或输入输出 端口发生某一事件时,将启动模块执行。 (VHDL对信号有严格说明) 3.信号类属性 信号类属性用于产生一种特别的 信号,这个特别 的信号是以所加属性的信号为基础而形成的 。 4种信号类属性 s’delayed[(time)]----产生一个延时信号,延时信 号特征与属性所加信号相同。

s’stable[(time)]----返回布尔值,在括号内的时间 表达式所说明的时间内,若参 考信号没有发生事件,得到“真”。 s’quiet[(time)]----返回布尔值,在括号内的时间 表达式所说明的时间内,若参 考信号没有发生转换或其他事件, 得到“真”。 s’transaction----可建立一个bit型信号,当属性所加 信号发生转换或事件时,其值都将 发生改变。

设计举例

1) 多数决定的数字滤波器(4位) 滤波器输出信号d_f的取值由滤波器输入信号前 N次采样值表决而定,原则是多数取胜。假定采 样次数N为3,若 (d_in(N-2)+d_in(N-1)+d_in≥2 则d_f的取值为‘1’,否则为‘0’。 提示:设计要利用数组和循环语句。 见文件 majority.vhd

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity majority is port (clk,resetn: in std_logic; d_in: in std_logic_vector(3 downto 0); d_f : out std_logic_vector(3 downto 0)); end; architecture rtl of majority is type array_4 is array(3 downto 0)of std_logic_vector(2 downto 0); signal s_d:array_4; signal d_f_i:std_logic_vector(3 downto 0);

该进程完成将三位数并行读入 begin end loop; process(clk,resetn) end if; end process; if resetn='0' then for i in 0 to 3 loop s_d(i)<="000"; end loop; elsif clk'event and clk='1'then s_d(i)(0)<=d_in(i); for j in 0 to 1 loop s_d(i)(j+1)<=s_d(i)(j); end loop; end if; end process; 该进程完成将三位数并行读入

该进程完成输出数据计算 process (s_d) type array_42 is array(3 downto 0)of std_logic_vector(1 downto 0); variable ct:array_42; begin for i in 0 to 3 loop ct(i) :=('0'&s_d(i)(2))+('0'&s_d(i)(1))+('0'&s_d(i)(0)); if ct(i)>=2 then d_f_i(i)<='1'; else d_f_i(i)<='0'; end if; end loop; end process; 该进程完成输出数据计算

该进程完成输出赋值 process (clk,resetn) begin if resetn='0' then d_f<=(others=>'0'); elsif clk'event and clk='1' then d_f<=d_f_i; end if; end process; end; 该进程完成输出赋值

2) 二进制转换为格雷码(8位) 提示:设二进制码为A=a7a6a5a4a3a2a1a0 格雷码为Y=y7y6y5y4y3y2y1y0 则:y7=a7 ; yi=ai+1 ai ; i≠7 见文件: bintogray.vhd

library ieee; use ieee.std_logic_1164.all; entity bintogray is port (a: in std_logic_vector(7 downto 0); y: out std_logic_vector(7 downto 0)); end;

architecture rtl of bintogray is begin process (a) variable tmp:std_logic_vector(7 downto 0); tmp(7):=a(7); for i in 6 downto 0 loop tmp(i):=a(i) xor a(i+1); end loop; y<=tmp; end process; end rtl;

3) 设计一个乘常数的电路 从资源和速度考虑,常系数乘法运算可用移位 相加来实现。(下例为乘71电路设计) 算法:71=26 + 23 – 1 下面是一个9位数din和71相乘的例子,结果舍去 了最后一位。 程序见cx71.vhd

LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; ENTITY cx71 is PORT ( clk : IN STD_LOGIC; Din : IN SIGNED (8 DOWNTO 0); Dout : OUT SIGNED (14 DOWNTO 0) ); END cx71;

ARCHITECTURE a OF cx71 IS SIGNAL s1 : SIGNED (11 DOWNTO 0); SIGNAL s2 : SIGNED (11 DOWNTO 0); SIGNAL s3 : SIGNED ( 9 DOWNTO 0); SIGNAL s4 : SIGNED (14 DOWNTO 0); BEGIN s1(11 DOWNTO 3)<=Din; s1( 2 DOWNTO 0)<="000"; --implementing 2^3*Din - Din s2<=(s1 - Din); --implementing 2^6*Din + 2^3*Din - Din s3<=(Din + s2(11 DOWNTO 6)); s4(14 DOWNTO 5)<=s3; -- truncating one bit s4( 4 DOWNTO 0)<=s2(5 DOWNTO 1);

-- pipeling dff: PROCESS BEGIN WAIT UNTIL clk = '1'; Dout<= s4; END PROCESS; END a;

4) Mealy 型状态机 组合逻辑 寄存器 Input Output clk reset 当前状态

一个Mealy 型状态机的例子 S1 S0 S2 S3 程序见mealy.vhd 1/1001 0/1100 0/0000 1/1111 其他/0000 其他/1001 其他/1100 其他/1111 1/1001 0/1100 1/1111 0/0000 程序见mealy.vhd

library ieee; use ieee.std_logic_1164.all; ENTITY mealy IS PORT(clk,in1,reset: IN STD_LOGIC; out1: OUT STD_LOGIC_vector(3 downto 0)); END ; architecture bhv of mealy is type state_type is (s0,s1,s2,s3); signal state:state_type;

该进程完成状态转换的描述 WHEN s2 =>if in1='1'then begin state<=s3; p0: process (clk,reset) if reset='1' then state<=s0; elsif clk'event and clk='1'then CASE state IS WHEN s0 =>if in1='1'then state<=s1; end if; WHEN s1 =>if in1='0'then state<=s2; WHEN s2 =>if in1='1'then state<=s3; end if; WHEN s3 =>if in1='0'then state<=s0; END CASE; end process p0; 该进程完成状态转换的描述

out_p:process(state,in1) begin case state is when s0 => if in1='1' then out1 <="1001"; else out1 <="0000"; end if; when s1 => if in1='0' then out1 <="1100"; out1 <="1001";

该进程完成由状态和输入决定输出 when s2=> if in1='1' then out1 <="1111"; else end if; when s3 => if in1='0' then out1 <="0000"; out1 <="1111"; end case; end process; end bhv; 该进程完成由状态和输入决定输出

5) Moore型状态机 组合逻辑 寄存器 input output clk reset 当前状态 次状态 Process p1 p0 p2

前一个例子的moore型形式: S0 S1 S2 S3 1 1111 0000 1001 1100 程序分析见moore.vhd

library ieee; use ieee.std_logic_1164.all; ENTITY moore IS PORT( clk,in1,reset : IN STD_LOGIC; out1: OUT STD_LOGIC_vector(3 downto 0)); END ; architecture bhv of moore is type state_type is (s0,s1,s2,s3); --状态说明 signal current_state,next_state:state_type;

begin p0: process (clk,reset) --时钟进程 if reset='1' then current_state <= s0; elsif clk'event and clk='1'then current_state<=next_state; end if; end process;

p1: process(current_state,in1) --组合进程 begin CASE current_state IS WHEN s0 =>if in1='1'then next_state<=s1; end if; WHEN s1 =>if in1='0'then next_state<=s2; end if; WHEN s2 =>if in1='1'then next_state<=s3; end if; WHEN s3 =>if in1='0'then next_state<=s0; end if; END CASE; end process;

p2:process(current_state) --组合进程 begin case current_state is when s0 => out1 <="0000"; when s1 => out1 <="1001"; when s2 => out1 <="1100"; when s3 => out1 <="1111"; end case; end process; end bhv;

6)带有类属参数的计数器 通过类属参数,可以方便地改变计数器的模。 分析见程序cntnbits.vhd

nreset ci clk co qcnt 计数器

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity cntnbits is generic(cwh:integer:=5); port(ci,nreset,clk : in std_logic; co : out std_logic; qcnt :buffer std_logic_vector(cwh-1 downto 0)); end cntnbits;

architecture behave of cntnbits is constant allis :std_logic_vector(cwh-1 downto 0):=(others=>'1'); begin co<='1' when(qcnt=allis and ci='1') else '0'; process(clk,nreset) if(nreset='0')then qcnt<=(others=>'0'); elsif(clk'event and clk='1')then if(ci='1')then qcnt<=qcnt+1; end if; end process; end behave;

7) 寄存器和移位寄存器 下面的实例介绍触发器、移位寄存器的设计, 说明元件、过程调用等方面知识。

a) 一个带异步清零的D触发器 见程序dff1.vhd library ieee; use ieee.std_logic_1164.all; entity dff1 is port(d,clk,r:in std_logic; q:out std_logic); end ; architecture rtl of dff1 is begin process(clk,r) begin if r='1' then q<='0'; elsif (clk'event and clk='1') then q<=d; end if; end process; end rtl; 见程序dff1.vhd

b) 串行输入、串行输出移位寄存器shift8 方法一:调用dff1组成。(dff1和shift8在同一目录下)

见程序shift8.vhd library ieee; use ieee.std_logic_1164.all; entity shift8 is port(a,clk,r:in std_logic; b:out std_logic); end; architecture rtl of shift8 is component dff1 port(d,clk,r:in std_logic; q:out std_logic); end component; signal z :std_logic_vector(0 to 8); begin z(0)<=a; g1:for i in 0 to 7 generate dffx: dff1 port map (z(i),clk,r,z(i+1)); end generate; b<=z(8); end rtl; 见程序shift8.vhd

方法二:直接利用信号来连接。注意信号赋值的特点。 library ieee; use ieee.std_logic_1164.all; entity shift8a is port(a,clk : in std_logic; b: out std_logic); end; architecture rtl of shift8a is Signal d_1,d_2,d_3,d_4,d_5,d_6, d_7,d_8 :std_logic; begin process(clk) if(clk'event and clk='1')then d_1<=a; d_2<=d_1; d_3<=d_2; d_4<=d_3; d_5<=d_4; d_6<=d_5; d_7<=d_6; d_8<=d_7; b<=d_8; end if; end process; end rtl; 程序见shift8a.vhd

c) 循环移位寄存器 在计算机的运算操作中经常用到循环移位。八位循环左移的寄 存器电路框图如下。电路有八个数据输入端din(7)~din(0),移位和置 数控制端enb,时钟信号输入端clk,移位位数控制输入端s(2)~s(0), 八位数据输出端dout(7)~dout(0). 功能:当enb=1时,根据s(2)~s(0)输入的数值,确定在时钟脉冲 作用下,循环左移几位; 当enb=0时,在时钟作用下,将数据din直接传输到dout。

dout ( 7 ) ~ 例如:当enb=1时,s(2)s(1)s(0)=100时。 电路设计方法: MSB LSB 移位前 移位后 电路设计方法: 1)将循环左移寄存器描述为一个名为shiftp的过程(procedure); 将过程shiftp定义在包名为cpac的包中; 在实体描述中调用过程,实现移位。

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; package cpac is procedure shiftp(din,s :in std_logic_vector; signal dout :out std_logic_vector); end cpac; package body cpac is signal dout :out std_logic_vector)is

程序见cpac.vhd variable sc :integer; begin sc:=conv_integer(s); for i in din'range loop if(sc+i<=din'left)then dout(sc+i)<=din(i); else dout(sc+i-din'left)<=din(i); end if; end loop; end shiftp; end cpac; 程序见cpac.vhd

八位移位寄存器描述: library ieee; use ieee.std_logic_1164.all; use work.cpac.all; entity bsr is port(din:in std_logic_vector(8 downto 1); s:in std_logic_vector(2 downto 0); clk,enb:in std_logic; dout :out std_logic_vector(8 downto 1)); end;

architecture rtl of bsr is begin process(clk) if (clk'event and clk='1') then if (enb='0') then dout<=din; else shiftp(din,s,dout); end if; end process; end rtl; 程序见bsr.vhd,由于maxplusII 不支持过程调用语句,该程序 可利用quartusII运行。

8) 存储器 存储器分为: 只读存储器(ROM) 随机存取存储器(RAM) 下面是两个可综合的ROM和RAM的例子。

R O M 一个容量为4×8的rom例子实现 方法:(改变参数可改变容量) 1)把ROM中要存放的内容先定 义为一个数组,并存放在一个 包文件内; 2)在实体中调用数组,进行 初始化。 clk addr[1..0] 1 0 q[7..0] R O M 4×8

ROM clk 4×8 1 0 q[7..0] addr[1..0] library ieee; 1 0 q[7..0] ROM 4×8 library ieee; use ieee.std_logic_1164.all; package rom is constant rom_width:integer:=8; constant rom_length :integer:=4; subtype rom_word is std_logic_vector(rom_width-1 downto 0); type rom_table is array(0 to rom_length-1)of rom_word; constant rom: rom_table :=rom_table'("00101111","11010000","01101010", "11101101"); end; 说明:1)该包可以单独保存在当前目录下,也可以直接放在下面的实体前; 2)本设计定义了一个常量型数组,即为ROM中内容; 3)常量型数组的这种定义方式,maxplusII不支持,quartusII支持。

clk q[7..0] 1 0 addr[1..0] library ieee; use ieee.std_logic_1164.all; 1 0 q[7..0] W A V E F O R M library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use work.rom.all; entity waveform is port(clk:in std_logic; addr: in std_logic_vector(1 downto 0); q: out rom_word); end;

architecture test of waveform is signal tmp: rom_word; begin tmp<=rom(conv_integer(addr)); process(clk) if clk='1' then q<=tmp; end if; end process; end test;

一个容量为8×8的RAM 例子实现方法: (改变参数可改变容量) 1) 有3根地址线,可选8个字; 2) 8根数据输入线,即字长 为8; 3) wr为写控制线,rd为读控制线,cs为片选控制线; 4) cs=1,wr信号由低变高时,将din上的数据写入adr所指定的单元; cs=1,rd=0时,由adr所指定单元的内容将从dout输出。 Dout[7..0] Din[7..0] wr rd cs Adr[2..0] 8×8 SRAM

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity sram64 is generic(k:integer:=8; w:integer:=3); port (wr,rd,cs:in std_logic; adr:in std_logic_vector(w-1 downto 0); din:in std_logic_vector(k-1 downto 0); dout:out std_logic_vector(k-1 downto 0)); end sram64;

architecture beh of sram64 is subtype word is std_logic_vector(k-1 downto 0); type memory is array(0 to 2**w-1)of word; signal adr_in :integer range 0 to 2**w-1; signal sram :memory; begin adr_in<=conv_integer(adr); process(wr) if(wr'event and wr='1‘ and cs=‘1’) then sram(adr_in)<=din ; end if; end process;

见程序sram64.vhd,程序在quartusII上运行。 process(rd,cs) begin if(rd='0' and cs='1')then dout<=sram(adr_in); else dout<="ZZZZZZZZ"; end if ; end process; end beh; 见程序sram64.vhd,程序在quartusII上运行。

c) 一个带时钟的容量为8×8的RAM例子实现方法: (改变参数可改变容量) 1) 有3根地址线,可选8个字; 2) 8根数据输入线,即字长 为8; 3) wr为写控制线,rd为读控制线,cs为片选控制线; 4) cs=1,wr=1时,clk的上升沿来到时将din上的数据写入adr所指定的单元; cs=1,rd=0时, clk的上升沿来到时将adr所指定单元的内容送至dout输出。 Dout[7..0] Din[7..0] wr rd cs Adr[2..0] 8×8 SRAM clk

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity sram64clk is generic(k:integer:=8; w:integer:=3); port(clk,wr,rd,cs:in std_logic; adr:in std_logic_vector(w-1 downto 0); din:in std_logic_vector(k-1 downto 0); dout:out std_logic_vector(k-1 downto 0)); end ;

architecture beh of sram64clk is subtype word is std_logic_vector(k-1 downto 0); type memory is array(0 to 2**w-1)of word; signal adr_in :integer range 0 to 2**w-1; signal sram :memory; begin adr_in<=conv_integer(adr); process(clk) if( wr='1' and cs='1') then if(clk'event and clk='1') then sram(adr_in)<=din ; end if; end process;

程序见sram64clk.vhd, 在quartusII上运行。 process(clk) begin if(clk'event and clk='1' )then if(rd='0' and cs='1')then dout<=sram(adr_in) ; else dout<="ZZZZZZZZ"; end if; end if ; end process; end beh; 程序见sram64clk.vhd, 在quartusII上运行。

9) 并行输入、串行输出的寄存器PISO 8位Piso功能: 在实际电路系统的应用中,当需要远距离通信传输时,常需要 将A/D转换过的并行信号先加载,然后再一串行信号的形式传送 到远方,需要使用PISO。 piso ld Par_in clk Ser_out busy Sh_comp 8位Piso功能: 在时钟上升沿,若 ld=1,则将8位并行输入 信号par_in加载到转换电路的内部寄存器,并将状态标志 busy置位为‘1’;在8位并行数据全部移出之前,busy保持 为‘1’,并禁止再次加载数据; b) 在时钟上升沿, 若busy=1,则逐位将内部寄存器的数据移 出,在数据全部移出之前,移位终止信号sh_comp保持为‘0’, 在数据全部移后,将sh_comp置为‘1’,busy置为‘0’。

piso ld Par_in clk Ser_out busy Sh_comp library ieee; use ieee.std_logic_1164.all; entity par_to_ser is port(clk,ld:in std_logic; par_in:in std_logic_vector(7 downto 0); busy: buffer std_logic; ser_out:out std_logic; sh_comp: out std_logic); end;

architecture alg of par_to_ser is signal reg:std_logic_vector(7 downto 0); begin process(clk,reg,ld) variable i:integer ; if( clk'event and clk='1') then if (ld='1' and busy='0') then i:=0; reg<=par_in; busy<='1'; elsif (busy='1') then

if i<=7 then sh_comp<='0'; ser_out<=reg(0); reg<='0'&reg(7 downto 1); i:=i+1; else sh_comp<='1'; busy<='0'; end if; end if ; end process ; end alg; 程序见par_to_ser.vhd

10) 双向电路和三态控制电路 a) 三态门 library ieee; use ieee.std_logic_1164.all; Dataout{7..0] enb Datain{7..0] [7..0] a) 三态门 library ieee; use ieee.std_logic_1164.all; entity tri_gate is port(enb :in std_logic; datain:in std_logic_vector(7 downto 0); dataout :out std_logic_vector(7 downto 0)); end ;

architecture beh of tri_gate is begin process(enb,datain) if enb='1' then dataout<=datain; else dataout<="ZZZZZZZZ"; end if ; end process; end beh; 程序见tri_gate.vhd

b) 双向端口电路 原理示意图 结构图 (图中in1和out1可以合在一起) Control=1: in/out1输入, [7..0] In/out2[7..0] 原理示意图 Control=0: in/out1输出, in/out2输入。 out1{7..0] control in1{7..0] [7..0] In/out2[7..0] 结构图 (图中in1和out1可以合在一起)

library ieee; use ieee.std_logic_1164.all; entity tri_state1 is port(control :in std_logic; in1:in std_logic_vector(7 downto 0); inout2 :inout std_logic_vector(7 downto 0); out1:out std_logic_vector(7 downto 0)); end ;

程序见tri_state1.vhd 原理图文件见tri1.bdf architecture beh of tri_state1 is begin process(control,inout2,in1) if control='0' then out1<=inout2; inout2<="ZZZZZZZZ"; else inout2<=in1; out1<="ZZZZZZZZ"; end if ; end process; end beh; 程序见tri_state1.vhd 原理图文件见tri1.bdf

11) A/D0809采样控制电路 ADC0809是CMOS的 8位A/D转换器,片内有8路模拟开关,可 转换时间约100μ含锁存控制的 8路多路开关,输出有三态缓冲器 控制,单5V电源供电。 In3 In4 In5 In6 In7 START EOC ID4 IOE CLK VCC REF+ GND D6 In2 In1 In0 ADDA ADDB ADDC ALE D0 D1 D2 D3 D7 REF- D5 ADC 0809 主要控制信号说明: 1)输入信号: START:转换启动信号,高电平有效; ALE:3位通道地址锁存信号,高电平有效; OE : 输出使能,高电平有效。 2)输出信号: EOC:转换状态信号,当START有效后约 (100μ)后,EOC产生一个负脉冲,以 示转换结束,在EOC上升沿后,可以读 出数据。

} { START ALE EOC OE D[7..0] ZZZZZZZ ADC0809工作时序 START CLK ALE 送到 控制电路 DATA ADC0809工作时序 D[7..0] EOC CLK START ALE OE ADDA LOCK1 Q[7..0] LOCK REGL 控制电路 { 来自 0809 } 送到

library ieee; use ieee.std_logic_1164.all; entity adcint is port(d:in std_logic_vector(7 downto 0); --0809的8位数据输出 clk,eoc:in std_logic; lock1,ale,start,oe,adda:out std_logic; --lock1为输出数据锁存信号 q:out std_logic_vector(7 downto 0)); end; architecture beh of adcint is type states is (st0,st1,st2,st3,st4,st5,st6); --定义各状态(枚举类型) signal current_state,next_state:states:=st0; signal regl :std_logic_vector(7 downto 0); signal lock :std_logic; --转换后数据输出锁存时钟 begin adda<='1';lock1<=lock;

pr0: process(current_state,eoc) Begin -- 规定各状态转换方式 case current_state is when st0=>ale<='0';start<='0';oe<='0';lock<='0';next_state<=st1; when st1=>ale<='1';start<='0';oe<='0';lock<='0';next_state<=st2; when st2=>ale<='0';start<='1';oe<='0';lock<='0';next_state<=st3; when st3=>ale<='0';start<='0';oe<='0';lock<='0'; if(eoc=‘1’)then next_state<=st3; --测试EOC的下降沿 else next_state<=st4;--下降沿到 end if;

when st4=>ale<=‘0’;start<=‘0’;oe<=‘0’;lock<=‘0’;--EOC为低电平 if(eoc='0')then next_state<=st4; else next_state<=st5; --EOC上升沿到 end if; when st5=>ale<=‘0’;start<=‘0’;oe<=‘1’; --转换结束,输出使能有效 lock<='0';next_state<=st6; when st6=>ale<='0';start<='0';oe<='1'; lock<=‘1’;next_state<=st0; --lock的上升沿,将数据存入REGL when others=>ale<='0';start<='0';oe<='0';lock<='0';next_state<=st0; end case; end process pr0;

pr1:process(clk) begin if(clk'event and clk='1')then current_state<=next_state;--在时钟上升沿,转换到下一个状态 end if; end process pr1;--由信号current_state将当前状态值带出此进程,进入进程pro pr2:process(lock)—此进程中,在LOCK的 上升沿,将转换好的数据保存并输出 if (lock='1' and lock'event) then regl<=d; end process pr2; q<=regl; end beh;

12)移位相加型乘法器(8位)设计 乘法器以8位加法器为核心,辅以移位寄存器组成。乘法原理: 乘法通过逐项移位相加原理实现,从被乘数的 最低位开始,若为1,则乘数 左移后与上一次的 和相加;若为0,乘数左移后加0,直至被乘数的 最高位。 并入串出 移位寄存器 8位 被乘数 乘法器 1×8位 乘数 8位加法器 输出 [15..0] 16位锁存器 右移寄存器 9位 输出高8位 [15..8] clk

a)8位右移寄存器 library ieee; use ieee.std_logic_1164.all; entity sreg8b is port(clk,load:in std_logic; din:in std_logic_vector(7 downto 0); qb :out std_logic); end;

architecture beh of sreg8b is signal reg8: std_logic_vector(7 downto 0); begin process(clk,load) if load='1' then reg8<=din; elsif clk'event and clk='1' then reg8(6 downto 0)<=reg8(7 downto 1); end if; end process; qb<=reg8(0); --- 输出最低位 end beh;

b) 1×8位乘法器(可有多种结构) library ieee; use ieee.std_logic_1164.all; entity andarith is—结构(1) port(abin:in std_logic; din:in std_logic_vector(7 downto 0); dout :out std_logic_vector(7 downto 0)); end; architecture beh of andarith is begin process(abin,din) for i in 0 to 7 loop dout(i)<=din(i) and abin; end loop; end process; end beh;

library ieee; use ieee.std_logic_1164.all; entity andarith1 is—结构(2) port(abin:in std_logic; din:in std_logic_vector(7 downto 0); dout :out std_logic_vector(7 downto 0)); end; architecture beh of andarith1 is begin process(abin,din) if abin='0' then dout<="00000000"; else dout<=din; end if; end process; end beh;

library ieee; use ieee.std_logic_1164.all; entity andarith2 is --结构(3) port(abin:in std_logic; din:in std_logic_vector(7 downto 0); dout :out std_logic_vector(7 downto 0)); end; architecture beh of andarith2 is begin dout<="00000000" when (abin='0') else din; end beh;

c) 8位加法器 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity adder8 is port(a,b :in std_logic_vector(7 downto 0); s :out std_logic_vector(8 downto 0)); end; architecture beh of adder8 is begin s<='0'&a+b; end beh;

d) 16位锁存器/右移寄存器 library ieee; use ieee.std_logic_1164.all; entity reg16b is port(clk,clr:in std_logic; d:in std_logic_vector(8 downto 0); q :out std_logic_vector(15 downto 0)); end; architecture beh of reg16b is signal r16s: std_logic_vector(15 downto 0);

if clr='1' then r16s<=(others=>'0'); begin process(clk,clr) if clr='1' then r16s<=(others=>'0'); elsif clk'event and clk='1' then r16s(6 downto 0)<=r16s(7 downto 1); r16s(15 downto 7)<=d; end if; end process; q<=r16s; end beh; 8位乘法器可用上面四各电路组成, 原理图文件见mult8.bdf,在quartusII 上运行。(8个clk后为正确值).

延时电路的几个例子

下例调用了一个定义在process中的函数inc实现二进制计数器, 最终实现输出信号延时。 library ieee; use ieee.std_logic_1164.all; entity delay is port(reset,clk:in std_logic; time_out :out std_logic); end; architecture beh of delay is Begin process(reset,clk) variable count:std_logic_vector(3 downto 0);

function inc(x:in std_logic_vector) return std_logic_vector is variable xv:std_logic_vector(x'length-1 downto 0); begin xv:=x; for i in 0 to xv'high loop if xv(i)='0' then xv(i):='1'; exit; else xv(i):='0'; end if; end loop; return xv; end inc;

begin if reset='1' then count:="0000";time_out<='0'; elsif clk'event and clk='1' then count:=inc(count); end if; if(count="1111")then time_out<='1'; end process ; end beh;

下例同样调用函数inc实现二进制计数器,和上例不同的是先将 函数定义在包mypack_1中,然后调用,最终实现输出信号延时。 library ieee; use ieee.std_logic_1164.all; package mypack_1 is function inc(x:in std_logic_vector) return std_logic_vector ; end; package body mypack_1 is return std_logic_vector is variable xv:std_logic_vector(x'length-1 downto 0);

begin xv:=x; for i in 0 to xv'high loop if xv(i)='0' then xv(i):='1'; exit; else xv(i):='0'; end if; end loop; return xv; end inc; end mypack_1; library ieee; use ieee.std_logic_1164.all; use work.mypack_1.all; entity delay_2 is port(reset,clk:in std_logic; time_out :out std_logic); end; architecture beh of delay_2 is begin

process(reset,clk) variable count:std_logic_vector(3 downto 0); begin if reset='1' then count:="0000";time_out<='0'; elsif (clk'event) and (clk='1') and (clk'last_value='0')then count:=inc(count); if(count="1111") then time_out<='1'; end if; end process ; end beh;

下例采用移位方法求延时,移位算法:按下算法(四位)最长序列为15 library ieee; use ieee.std_logic_1164.all; entity delay_1 is port(reset,clk:in std_logic; time_out :out std_logic); end; architecture beh of delay_1 is begin

process(reset,clk) variable count:std_logic_vector(3 downto 0); begin if reset='1' then count:="0001"; time_out<='0'; elsif clk'event and clk='1' then count:=(count(1)xor count(0))&count(3 downto 1); end if; if(count="0011")then time_out<='1'; end process; end beh;

use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; 下例采用一般计数器的设计方法,实现延时: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity delay_3 is port(CLK,CLRN :IN STD_LOGIC; CO:OUT STD_LOGIC); END; ARCHITECTURE BEH OF delay_3 IS

BEGIN PROCESS(CLK,CLRN) variable q :std_logic_vector(3 downto 0); IF (CLRN='1') THEN q:="0000";co<='0'; ELSIF(CLK'EVENT AND CLK='1') THEN IF (q="1111")THEN q:="0000"; co<='1'; ELSE q:=q+1; END IF; END PROCESS; END BEH;

Data[ ][ ]和 Result[ ]端口宽度 输入数据流的数目,等于2LPM——WIDTHS MAX+PLUSII 开发软件中的参数化模块 1.参数化数据选择器lpm_mux宏模快 端口名称 功 能 描 述 输入端口 Data[ ][ ] 数据流输入端口 Sel[ ] 地址选择线 输出端口 Result[ ] 数据输出线 参数设置 LPM_WIDTH Data[ ][ ]和 Result[ ]端口宽度 LPM_WIDTHS Sel[ ]端口宽度 LPM_SIZE 输入数据流的数目,等于2LPM——WIDTHS 另有清零和寄存设置

Dataa[ ]+ Datab[ ]+cin或Dataa[ ]- Datab[ ]+cin-1 2.参数化加法器/减法器lpm_add_sub宏模快 端口名称 功 能 描 述 输入端口 Dataa[ ] 被加数/被减数 Datab[ ] 加数/减数 输出端口 Result[ ] Dataa[ ]+ Datab[ ]+cin或Dataa[ ]- Datab[ ]+cin-1 Cout 进位和借位标志 Cout用于无符号数运算 Overflow用语有符号数运算Cout和Overflow不同时出现 Overflow 溢出标志 参数设置 LPM-width Dataa[ ] 、Datab[ ] 和Result[ ]端口宽度 LPM_DIRECTION ADD表示执行加法运算 SUB表示执行减法运算 DEFAULT缺省设置为加法器 LPM_REPRESENTATION 指定参与运算的数值是无符号数还是有符号数 另有清零和寄存设置

3.参数化乘法器lpm_mult宏模快 输入端口 输出端口 参数设置 另有清零和寄存设置 功 能 描 述 端口名称 被乘数 乘数 功 能 描 述 输入端口 Dataa[ ] 被乘数 Datab[ ] 乘数 Sum[ ] 部分和(可以不使用) 输出端口 Result[ ] Result[ ] =Dataa[ ]×Datab[ ]+sum 参数设置 LPM-WIDTHA Dataa[ ] 端口宽度 LPM-WIDTHB Datab[ ]端口宽度 LPM-WIDTHP Result[ ]端口宽度 LPM-WIDTHS SUM端口宽度 LPM_REPRESENTATION 指定参与运算的数值是无符号数还是有符号数 USE_EAB 选择使用EAB或逻辑单元实现乘法器,“on”为使用EAB, “ off”为使用逻辑单元。 另有清零和寄存设置

4.参数化译码器lpm_decode宏模快 端口名称 功 能 描 述 输入端口 data[ ] 输出端口 eq[ ] 参数设置 数据输入 输出端口 eq[ ] 译码输出 参数设置 LPM_WIDTH Data[ ] 端口宽度 LPM_DECODES 译码器输出的端口数目 等于2LPM_WIDTHS 另有清零和寄存设置

参数化RAM可以随时在任一指定地址写入或读出 数据 。有多个模块 模块名 功能描述 Csdpram 参数化循环共享双端口RAM Lpm_ram_dp 参数化双端口RAM Lpm_ram_dq 参数化RAM,输入/输出端口分离 Lpm_ram_io 参数化RAM,输入/输出端口共用

下面为Lpm_ram_dq的参数表一 端口名称 功能描述 输入端口 Data[] 输入数据 Address[ ] 地址端口 we Inclock 同步写入时钟 Outclock 同步读取时钟 输出端口 Q[ ] 数据输出端口 参数设置 LPM_WIDTH Data[] 和Q[ ]端口的数据线宽度 LPM_WIDTHAD Address[ ]端口宽度 LPM_numwords RAM中存储单元的数目 USE_EAB 选择使用EAB或逻辑单元

下面为Lpm_ram_dq的参数表二 同步数据读/写操作 同步数据读取 异步存储器操作 inclock we 功能描述 Not~ x outclock Not~ x 状态不变 L ~(写) H 写入数据 ~ 读出数据 ~(读) “~”表示时钟发生变化,“not~”表示时钟不发生变化