文档库 最新最全的文档下载
当前位置:文档库 › VHDL语言编写规范

VHDL语言编写规范

VHDL语言编写规范
VHDL语言编写规范

VHDL语言编写规范

目录

目录 (1)

1 目的 (2)

2 范围 (2)

3 定义 (2)

4 规范内容:VHDL编码风格 (2)

4.1 标识符(Identifiers)命名习惯 (2)

4.2 数据对象和类型 (4)

4.3 信号和变量 (5)

4.4 实体 (5)

4.5 语句 (7)

4.6 运算符(Operator) (10)

4.7 function (10)

4.8 procedure (11)

4.9 类属( generics) (11)

4.10 package (12)

4.11 FSM(有限状态机) (12)

4.12 Comments (12)

4.13 TAB键间隔 (12)

4.14 语句书写规范规定 (13)

5 程序中的注释 (13)

6 代码模块划分 (14)

7 代码编写中容易出现的问题 (15)

7.1 资源共享问题 (15)

7.2 组合逻辑描述的多种方式 (15)

7.3 考虑综合的执行时间 (16)

7.4 避免使用Latch (16)

7.5 多赋值语句案例:三态总线 (16)

附录一VHDL保留字 (18)

附录二函数书写实例 (19)

附录三参数化元件实例 (20)

附录四程序包书写实例 (21)

1 目的

编写该规范的目的是提高书写VHDL代码的可读性、可修改性、可重用性;优化代码综合和仿真结果,指导设计工程师使用VHDL 规范代码和优化电路,规范化公司的ASIC/FPGA 设计输入,从而做到:

a、逻辑功能正确;

b、可快速仿真;

c、综合结果最优;

d、可读性最好。

2 范围

该规范设计VHDL编码风格、规定,编码中应注意的问题,VHDL代码书写范例等,适用于所有的采用VHDL代码进行设计的项目。

3 定义

VHDL:Very high speed IC Hardware Description Language,甚高速集成电路的硬件描述语言。

FSM:Finite Status Machine,有限状态机

Simulate:仿真,通过输入激励在计算机上验证设计是否正确。包括RTL仿真和门级仿真。

模拟:是指对一个物理器件的结构、功能或其他特性如延时特性等用抽象的语言或高级语言(如用C语言进行算法描述)所进行的建模。

4 规范内容:VHDL编码风格

设计必须文档化。要将设计思路,详细实现等写入文档,然后经过严格评审通过后才能进行下一步的工作。这样做乍看起来很花时间,但是从整个项目过程来看,绝对要比一上来就写代码要节约时间,且这种做法可以使项目处于可控、可实现的状态,便于对程序代码的修改、学习。

本文中提到的VHDL编码规则和建议适用于VHDL的任何一级(RTL,behavioral,gate_level),也适用于出于仿真,综合或二者结合的目的而设计的模块。

4.1 标识符(Identifiers)命名习惯

标识符用于定义实体名、结构体名、信号和变量名等,选择有意义的命名对设计是十分重要的。命名包含信号或变量诸如出处、有效状态等基本含义,下面给出一些命名的规则,包括VHDL语言的保留字。

1. 标识符定义命名规定

●标识符第一个字符必须是字母,最后一个字符不能是下划线,不许出现连续两个下划线。

●基本标识符只能由字母、数字和下划线组成。

●标识符两词之间需用下划线连接。

如:Packer_addr,Data_in,Mem_wr,Mem_ce

●标识符不得与保留字同名,VHDL保留字见附录一。

2. 标识符大小写规定

●对常量、数据类型、实体名和结构体名采用全部大写;

●对变量采用小写;

●对信号采用第一个词首字符大写;

●保留字一律小写。

3. 信号名连贯缩写的规定

长的信号名对书写和记忆会带来不便,甚至带来错误。采用缩写应注意同一信号在模块中的一致性。一致性的缩写习惯有利于文件的阅读理解和交流。

部分缩写的统一规定为:

Addr address;Clk clock;Clr clear;Cnt counter En enable;Inc increase;Lch latch;Mem memory Pntr pointer;Pst preset;Rst reset;Reg register;

Rd reader;Wr write;

常见多个单词的缩写:ROM RAM COU FIFO ALU CS CE

自定义的缩写词必须在文件头注释。

4. 信号的缩写及大小写规定

●单词的缩写若是信号名的第一个单词则首字母大写,如:Addr_in中的Addr。若该单词

缩写不是第一个单词则小写,如:Addr_en中的en。

●多个单词的首字符缩写都大写,不管该所写在标识符的什么位置,如:RAM_addr,

Rd_CPU_en。

5. 信号名一致性规定

同一信号在不同层次应保持一致性。

6. 信号命名的有关建议

建议用有意义而有效的名字,能简单包含该信号的全部或部分信息,如输入输出信息:Data_in(总线数据输入)、Din(单根数据线输入)、FIFO_out(FIFO数据总线输出);

如宽度信息:Cnt8_q(8位计数器输出信号的命名)。

对于时钟信号在命名时应该将时钟的频率标出,如:Clk_125MHz 或者Sysclk_100MHz,便于程序的理解

建议添加有意义的后缀,使信号更加明确,常用的后缀如下:

后缀意义

_clk 时钟信号

_d 寄存器的数据输入信号

_q 寄存器的数据输出信号

_z 连到三态输出的信号

_L _L加数字,表示信号延迟时钟周期数,如_L1

_s 实体端口信号的反馈信号

_en 使能控制信号

_n 低电平有效的信号

_xi 芯片原始输入信号

_xo 芯片原始输出信号

_xod 芯片的漏极开路输出

_xz 芯片的三态输出

_xbio 芯片的双向信号说明:

A.采用D触发器对信号进行延迟,延迟信号的命名在原信号名之后加后缀_L,若是在流水线设计中有级延迟,再分别加后缀_L1,_L2,......。L表示lock。

B.模块内的反馈信号,在原信号名之后加后缀_s,“s”表示same。

C.低电平有效的信号结尾要用_n标记,如rst_n:就表示低电平有效的复位信号。

●对于标识符的命名,禁止取单个字符(如i、j、k...),建议除了要有具体含义外,还

能表明其标识符类型、数据类型等,但i、j、k作局部循环变量是允许的。

说明:标识符,尤其是局部标识符,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。

4.2 数据对象和类型

1. 类型使用规定

●VHDL是很强的类型语言,可综合的数据类型为标量类型(包含可枚举类型、整型、浮

点型、物理类型)和组合类型(包含记录、数组),模拟模型的数据类型为存取类型、文件型。可综合的VHDL代码的编写不采用模拟类型、浮点型、物理类型。

●不同的基本类型的数据不能由另一个类型赋值,不同类型间的赋值需要使用运算符的重

载。如:Cnt8_q为STD_LOGIC_VECTOR类型,若不对…+?运算符进行重载,则

Cnt8_q <= Cnt8_q + 1

语句在综合中将出错。可通过对+运算符的进行重载即使用

use IEEE.std_logic_arith.all

语句,则上句赋值语句是正确的。

●常量名和数据类型必须用大写标识符来表示。

2. 数据及数据类型使用建议

●为改善代码的可读性,建议可把常用的常量和自定义的数据类型在程序中定义。

●建议使用别名来表识一组数据类型有利于代码的清晰。如:

Signal Addr :STD_LOGIC_VECTOR(31 downto 0);

Alias Top_addr :STD_LOGIC_VECTOR(3 downto 0) is Addr(31 downto 28);

3.数据使用注意内容

可枚举类型的值为标识符或单个字母的字面量,是区分大小写的,如Z和z将是两个不同的量。

4.3信号和变量

1. 信号不许赋初值。

2. 变量使用建议

变量主要用在高层次的模拟模型建模及用于运算的用途,但变量的综合较难定义,对于编写可综合的VHDL模块,在没有把握综合结果情况下建议不使用。

3. 信号、变量使用注意内容

●在VHDL中,信号(signal)代表硬件连线,因此可以是逻辑门的输入输出,同时,信

号也表达存储元件的状态,端口也是信号。

●在进程(process)中,信号是在进程结束时被赋值。因此,在一个进程中,当一个

信号被多个信号所赋值时,只有最后一个赋值语句起作用。如下例:

Sig_p: process( A, B, C)

begin

D <= A; ------ ignored!!

X <= C xor D;

D <= B; ------ overrids!!

Y <= C xor D;

end;

上面实际的结果是B赋值给D,(C xor D)结果赋值给X、Y。

●变量不能表达连线或存储元件。变量的赋值是直接的、非预设的。变量将保持其值直到

他重新赋值。如下例;

Ver_p:process( A, B, C)

variable d : STD_LOGIC;

Begin

D := A;

X <= C or d;

D := B;

Y <= C xor d;

end process;

实际结果是X <= C or A,Y <= C xor B。

●端口信号排列要统一,一个信号只占一行,最好按输入输出及从哪个模块来到哪个模块

去的关系排列,这样在后期仿真验证找错时会方便很多。

●禁止用计数器分频后的信号做其它模块的时钟,而要用改成时钟使能的方式,否则这种

时钟满天飞的方式对设计的可靠性极为不利,也大大增加了静态时序分析的复杂性。

●尽量在底层模块上做逻辑,在高层尽量做例化,顶层模块只能做例化,禁止出现任何胶

连逻辑(glue logic),哪怕仅仅是对某个信号取反。

4.4 实体

1. 实体、结构体使用规定

●Library IEEE; use IEEE.std_logic_ll64.all;除IEEE大写外,其余小写。

●实体名和结构体名必须用大写标识,实体名必须与文件名同名。自定义的其他标识符如

信号名、变量名、标号等不得与实体名、结构体名同名。

●实体端口数据模式不准使用buffer模式

缓冲模式主要用在实体内部可读的端口,如计数器的输出。为简化大型设计各模块间接口的配合,要求不要使用。需要反馈的信号可定义内部信号来解决。如计数器端口Cout,可内部定义信号signal Cnt8_q :STD_LOGIC_VECTOR(7 downto 0);

Cnt8_q该信号可在内部反馈,最后通过赋值语句:

Count <= Cnt8_q;来实现端口的定义。

●实体端口数据类型规定

实体端口的数据类型采用IEEE std_logic_1164标准支持的和提供的最合适于综合的数据类型STD_ULOGIC、STD_LOGIC和这些类型的数组。不采用IEEE 1076/93标准支持和提供的BIT、BIT数组、INTEGER及其派生类型。这是为保证模拟模型和综合模型的一致性及减少转换时间和错误。

●一个文件只对应一个实体。

实体是设计文件的基本单元,其书写规范要求如下:

一条语句占用一行,每行应限制在八十个字符以内。

如果较长(超出80个字符)则要换行。

代码书写要有层次既层层缩进格式、清晰、美观。

要有必要的注释(25%)

实体开始处应注明文件名、功能描述、引用模块、设计者、设计时间及版权信息等。

如:

--Fliename:

--Author:

--Description:

--Called by : Top module

--Revision History : 10-07-26

-- Revision 1.0

-- Email : M@**https://www.wendangku.net/doc/8a17769582.html,

--Company : contec

-- Copyright(c)

2. 实体使用建议

●实体名的命名建议能大致反映该实体的功能,如COUNTER8(8位宽的计数器模块),

DECODER38(3-8线译码器模块)。

●行为级的结构体名命名为BEHA VIOR,结构级的结构体名命名为STRUCTURE,若有

多个结构体,用后缀A、B、.....命名。如:

architecture BEHA VIOR of COUNTER8 is

begin

......

end BEHA VIOR;

●一个实体可以有多个结构体,对单个结构体的实体,文件要包含结构体和实体说明,便

于查阅。对多个结构体的实体,建议把常用的结构体放在文件中,其余结构体用单独文件表示,使用时用configuration语句进行配置。

3. 实体使用注意内容

●VHDL设计应是层级型设计。VHDL设计实体由实体说明和结构体结合而成。实体是

一个设计的基本单元模块。即顶层的设计模块由次一级实体构成,每个次一级实体又可由再下一层次的实体构成。最低层模块可以是表达式或最基本的实体模块构成。这种设计方法就是Top-To-down的设计方法。

●实体端口模式为in,out,buffer,inout。模式为in的信号不能被驱动,模式out的信号

不能用于反馈,同时必须仅被一个信号所驱动;缓冲模式的端口不能被多重驱动(除非用决断函数解决外)同时仅可以连接内部信号或另一个实体的缓冲模式的某个端口。

●VHDL设计各模块接口定义时要考虑模块间配合的方便,如实体端口的模式,端口的数

据类型等。

4.5 语句

1. VHDL各语句使用规定

●With-select-when语句书写规范规定

With-select-when 语句提供选择信号赋值,是根据选定信号的值对信号赋值。代码的书写规范为:

With selection_signal select

Select_name <= value_a when value_1_of_selection_signal,

value_b when value_1_of_selection_signal,

value_c when value_1_of_selection_signal,

.........

value_x when last_value_1_of_selection_signal;

●With-select-when语句的selection_signal的所有值必须具备完整性,若没写完整必须有

一个others语句,如下三个写法,其综合的效果是一致的,因为S的元素不是已知的逻辑值,X将不被定义,但对RTL仿真而言,其结果是不一致的,这是因为RTL仿真支持多值元素。

●With S select

X <= A when "00",

B when "01",

C when "10",

D when others;

With S select

X <= A when "00",

B when "01",

C when "10",

D when others;

With S select

X <= A when "00",

B when "01",

C when "10",

D when "11",

--- when others;

建议不使用第三种写法。

●With-select-when语句中对有相同的支项可合并书写如X <= A when "00"|"10"。

●When_else语句书写规范规定

When_else语句提供为条件信号赋值,即一个信号根据条件被赋一值,代码书写规范为:signal_name <= value_a when condition1 else

Value_b when codition2 else

Value_c when condition3 else

.......

Value_x;

●当条件是表达式时,表达式须用()括起来,使代码更为清晰。如:

When (a = b and c = '1' ) else

●if 必须有一个else对应(除在如下面例子的情况下可不写else语句)。

例:process(Clk, Rst)

begin

if (Rst = '1') then

Q <= '0';

elsif (Clk'event and Clk = '1') then

Q <= D;

end if;

end process;

当没有else语句时,将产生不希望的存储器。

●case-when 语句书写规范规定

该语句用于规定一组根据给定选择信号的值而执行的语句,可用with-select-when语句等效。

代码的书写规范为:

case selection_signal is

when value1_of_selection signal =>

Statements 1;

when value2_of_selection signal =>

Statements 2;

......

when last_value_of_selection signal =>

Statements X;

when others =>

Statements x;

end case;

●case_when语句必须有when others 支项。

●若信号在if-else或case-when语句作非完全赋值,必须给定一个缺省值。

●process显示敏感列表必须完整

对有Clk的process,不同综合工具有不同的要求,有些只要写Clk和Rst就可,建议根据具体情况简化设计书写。

●有Clk的process的敏感列表中,为方便修改,敏感列表书写规范如下:

Lab: process(Clk, Rst, list1, list2,....)

begin

●每个process前须加个lable。而且在process之前还应该有对该进程实现功能及实现方

法的注释

●不同逻辑功能采用不同的process进程块,把相同功能的放在同一进程中,如触发器组

进程块:

D_p: process(Clk, Rst, D1, D2, ...., Dn)

begin

if (Rst='1') then

Q1 <= '0';

Q2 <= '0';

...

Qn <= Dn;

elsif(Clk'event and Clk = '1') then

Q1 <= D1;

Q2 <= D2;

......

Qn <= Dn;

end if;

end process;

●generate语句书写规范规定

在需要重复生成多个器件如多个器件的重复例化时,使用生成机构可简便代码书写。如下32位总线的三态缓冲器的例化:

Gen_lab1: for I in 0 to 31 generate

inst_lab : threestate port map(

Din => value(i),

Rd => Rd,

Dout => value_out(i)

);

end generate;

●生成机构必须有一个标号,如上的Gen_lab1。

●if-then用在生成机构中,不能有else或elsif语句,如下复杂的生成机构语句:

G1: for I in 0 to 3 generate

G2: for j in 0 to 7 generate

G3: if (I<1) th en generate

Ua: thrst port map(Val(j),Rd,Val_out(j));

end generate;

G4: if (i = 1) then generate .......

●port map 语句书写规范规定

Uxx Module_name

port map

port1 => port 1,

port2 => port2,

.....

portn => port n

);

●为便于阅读,port map 采用名字对应( => )映射方法。

●port map中总线到总线映射时(X downto Y )要写全。

●向量采用降序方法即X downto Y 格式,向量有效位顺序的定义为从大数到小数。

●port map 的module (设计者自编写的entity )名用Uxx标识,cell 如厂家提供的库

元件、RAM、Core等)名用Vxx 标识。

2. VHDL语句使用建议

●作为可综合的代码编写,…- ?值建议不用。如下一个代码:

with tmp select

X <= A when “1---”,

B when“-1--”,

C when“--1-”,

D when“---1”,

0 when others;

该代码在RTL级仿真中不会出错,但在综合过程中可能编译出错视综合工具而定。●由于不同综合工具支持能力问题,建议不采用wait 语句,即不使用隐式敏感表。

3. VHDL语句使用注意内容

●when_else语句具有优先级,第一个when 条件级别最高,最后一个最低,可用顺序

语句的if-else 替代。书写时必须考虑敏感路径。

●当信号的值为不相关的值时,最好用选择信号赋值语句,如多路选择器;当信号的值为

相关时,选用when-else 语句,如编写优先编码器。

●注意If --elsif ---elsif ---else的优先级。最后一个else 优先级最低。必须把关键路径放在

优先级高的语句中。

4.6 运算符(Operator)

1. 表达式书写规定

为便于理解,用()表示逻辑运算符执行的优先级。如:

X <= ( A and B ) and ( C or (not D));

建议运算操作符两边都加上空格。

2. 比较运算符规定

向量比较时,比较的向量的位宽要相等,否责会引起warning或error。除非重载等值比较运算符(调用numeric_std 库)。

4.7 function

1. function使用规定

●function代码书写规范规定

function FUNCTION_NAME (参数1:参数类型,参数2 :参数类型.......)

return 返回类型is

begin

顺序语句;

end;

实例见附录二。

2. function使用建议

●函数主要用于类型的转换或重载运算符的定义,对于使用IEEE1164标准的面向综合的

VHDL设计,采用std_logic 类型,不必考虑与bit类型的转换,可调用numeric_std 标准程序包实现类型转换和+ 运算符的重载。建议少用厂家提供的函数或自定义的类型转换函数。

●对多次重复的表达式可用一个函数来定义。

3. function使用注意内容

●函数参数只能是输入类型,不能被赋值修改。

●只能有一个返回值。

●定义函数必须为顺序语句,且其中不能定义新的信号,但可在函数说明域中说明新的变

量,并在定义域中对其赋值。

●函数在结构体说明域中或程序包中定义见附录二。

4.8 procedure

1. procedure使用规定

●procedure 书写规范规定

procedure PROCEDURE_NAME(signal 参数名:模式类型;

signal 参数名:模式类型;

(i)

begin

过程体;

end procedure;

2. Procedure使用注意内容

●过程用于数值运算、类型转换、运算符重载或设计元件的最高层设计结构。

●过程参数缺省模式为in。

4.9 类属( generics)

1.generic 使用注意内容

●类属为传递给实体的具体元件的一些信息,如器件的上升下降沿的延时信息(对应类属

为rise 、fall)、用户定义的数据类型如负载信息(对应类属为load)及数据通道宽度、信号宽度等。

●对大型设计,建议使用类属来构造参数化的元件。其调用的方法为:

Uxx:参数化的实体名generic map (实参)

Port map (

端口映射表;

);

见附录三。

●若元件的类属在定义时已经指定默认值,在调用时,若不改变该参数值可不用定义实参

的映射即map(实参)可不写。

4.10 package

1. package 使用建议

●对大型设计,建议把全局的常量(如数据宽度等)/指令状态编码/元件组/函数和子程序组

分别用元素包、器件包、函数包来构造。如通过调用元件程序包,实体的结构体说明区域中就不必再对调用的器件进行component 说明。

●程序包通过use 语句使之可见。可通过保留字all使包中所有单元都可见。如:

use work..yourpacketname.all;

其中yourpacketname是你的packet名。

2. package使用注意内容

●程序包包括程序包说明和可选包体。程序包说明用来声明包中的类型、元件、函数和子

程序;包体则用来存放说明中的函数和子程序。

●不含有子程序和函数的程序包不需要包体。(见附录四)

●程序包中的类型、常量、元件、函数和其他说明对其他设计单元是可见的。

4.11 FSM(有限状态机)

FSM使用规定

●FSM使用单进程的有限状态机。

●VHDL的FSM 不必为状态分配,而用行为级的枚举类型定义状态,根据需要在综合时

选择状态的分配方式如one - hot 或二进制编码。

●状态机在上电时必须明确进入一个初始状态。

●必须包括对所有状态都处理,不能出现无法处理的状态,不能使状态机进入死循环。

4.12 Comments

Comments使用建议

●对更新的内容尽量要做注释。

●模块端口信号要做简要的功能描述。

●语法块做简要介绍。

4.13 TAB键间隔

对TAB键的间隔,我们建议采用4个字符,这与许多软件的缺省设置是一致的。并且,

VHDL语言中大多数保留字也是4个字符。

4.14 语句书写规范规定

●一行程序以小于80字符为宜,不要写得过长。

●较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,

操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。

●不允许把多个短语句写在一行中,即一行只写一条语句。

5 程序中的注释

●一般情况下,源程序有效注释量必须在25%以上。

说明:注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。

●注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、

修改日志等,头文件的注释中还应有函数功能简要说明。

下面是ISE软件中自动添加的代码开头部分的注释,当然,并不局限于此格式,但上述信息建议要包含在内。

-- Company:

-- Engineer:

--

-- Create Date: 09:59:14 07/26/2010

-- Design Name:

-- Module Name: LED - Behavioral

-- Project Name:

-- Target Devices:

-- Tool versions:

-- Description:

--

-- Dependencies:

--

-- Revision:

-- Revision 0.01 - File Created

-- Additional Comments:

说明:Description一项描述本文件的内容、功能、内部各部分之间的关系及本文件与其它文件关系等。

●边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有

用的注释要删除。

●注释的内容要清楚、明了,含义准确,防止注释二义性。

说明:错误的注释不但无益反而有害。

●避免在注释中使用缩写,特别是非常用缩写。

说明:在使用缩写时或之前,应对缩写进行必要的说明。

●注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)

相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。

●注释与所描述内容进行同样的缩排。

说明:可使程序排版整齐,并方便注释的阅读与理解。

●将注释与其上面的代码用空行隔开。

说明:避免程序看上去很紧凑。

●避免在一行代码或表达式的中间插入注释。

说明:除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。●在代码的功能、意图层次上进行注释,提供有用、额外的信息。

说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。

●注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中

文,除非能用非常流利准确的英文表达。

说明:注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。

6 代码模块划分

模块设计的好坏直接影响着系统的设计好坏,模块设计的不好,会给后面的设计流程带来许多麻烦。设计模块的基本原则是:

有利于模块的可重用性;

模块设计得好,可节省大量的重复工作,并且为以后的设计带来方便。

1. 在组合电路设计中应当没有层次

可提高代码的可读性,另外一方面是综合的时候方便,并且时序较易满足。

2. 每个模块输出尽量采用寄存器输出形式

这样设计是有利于时序的满足。

3. 模块的按功能进行划分,划分要合理

4. 模块大小应适中,不能太大,也不能太小,一般为2000门左右。具体情况,应当依

据综合工具的性能而定。

5. 模块的层次应当至少有三级

可将一个设计划分为三个层次:TOP 、MID、功能CORE

●TOP

包括实例化的MID和输入输出定义(如果用综合工具插入管脚则可不要此层次)。

●MID

由两部分组成:1)时钟产生电路,如分频电路和倍频电路;2)功能CORE的实例化。

●功能CORE

包括各种功能电路的设计。一个复杂的功能可以分成多个子功能来实现,即再划分子层。

7 代码编写中容易出现的问题

7.1 资源共享问题

资源共享的主要思想是通过数据缓冲或多路选择的方法来共享数据通路的工作单元。在VHDL设计中资源共享必须与敏感路径问题进行综合考虑后采用适当的设计方法。

如:

R <= ( A + B) when ( Source = ' 1' ) else

( C + D );

综合工具可综合成以下两种情况,当在综合工具选中Resource Sharing 时,将资源共享一个加法器。这时A、B、C或D到R是关键路径。如果关键路径是Source 到R,则不要要求资源共享。需要资源共享时可改成如下写法(建议采用该方式):

R <= A when ( Source = ' 1 ' ) else

C;

S <= B when ( Source = ' 1 ' ) else

D;

F <= R + S;

7.2 组合逻辑描述的多种方式

对组合逻辑的描述有多种方式,其综合结果是等效的。以4bit的与门为例:

C <= A and B;

等效于

C ( 3 ) <= A ( 3 ) and B ( 3 );

C ( 2 ) <= A ( 2 ) and B ( 2 );

C ( 1 ) <= A ( 1 ) and B ( 1 );

C ( 0 ) <= A ( 0 ) and B ( 0 );

等效于

for I in 3 downto 0 loop

C ( i ) <= A ( i ) and B ( i );

end loop;

可以选择简洁的写法。

7.3 考虑综合的执行时间

通常会推荐将模块划分得越小越好,事实上要从实际的设计目标、面积和时序要求出发。好的时序规划和合适的约束条件要比电路的大小对综合时间的影响要大。要依照设计的目标来划分模块,对该模块综合约束的scripts也可以集中在该特性上。要选择合适的约束条件,过分的约束将导致漫长的综合时间。最好在设计阶段就做好时序规划,通过综合的约束scripts来满足时序规划。这样就能获得既满足性能的结果,又使得综合时间最省。

7.4 避免使用Latch

使用Latch必须有所记录,不希望使用Latch时,应该对将条件赋值语句写全,如在if语句最后加一个else,case 语句加others。

不完整的if 和case 语句导致不必要的latch的产生,下面的语句中,DataOut会被综合成锁存器。如果不希望在电路中使用锁存器,它就是错误。

process(Cond )

begin

if( Cond = '1') then

Data_out <= Data_in;

end if;

end process;

7.5 多赋值语句案例:三态总线

一根总线上挂多个三态电路时必须用多个进程来表示,如:

Tri_p1: process ( Sel_a, A)

begin

if ( Sel_a = '1') then

T <= A;

else

T <= 'Z';

end if;

end process;

Tri_p2: process ( Sel_b, B)

begin

if (Sel_b = '1') then

T <= B;

else

T <= 'Z';

end if;

end process;

为什么不能在一个process中进行处理呢?如下所示:

Error : process ( Sel_a, A, Sel_b, B)

begin

if (Sel_a = '1') then

T <= A;

else

T <= 'Z';

end if;

if (Sel_b = '1') then

T <= B;

else

T <= 'Z';

end if;

end process;

这是因为:上述两个if语句彼此没有优先级,又由于是对同一个信号(信号T)进行处理,则后一个处理会覆盖前一个处理。正确的做法是将这两个if 语句放在两个process中进行。

注意:只有三态电路才可以在多个process中出现,其它非三态电路若是在多个process 中出现的话,有的综合工具会报告“短路”错误即多驱动问题,但在语法检查时不一定报错。

附录一VHDL保留字

VHDL语言的保留字如下:

absaccess after alias all and architecture array assert attribute begin block buffer bus case component configuration constant disconnect downto else elsif end entity exit file for function generate generic group guarded if impure in inertial inout is label library linkage literal loop map mod nand new next nor not null of on open or others out package port postponed procedure process pure range record register reject rem report return rol ror select severity signal shared sla sll sra srl subtype then to transport type unaffected units until use variablewait when while with xnor xor

附录二函数书写实例

以下是一个使用多表决函数的全加器

-- Filename ﹕FullAdd.vhd

-- Author ﹕suwenbiao

-- Description ﹕A example of function

-- Called by ﹕Top module

-- Revision History ﹕99-08-01

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_unsigned.all;

entity FULLADD is

port(

A : in STD_LOGIC;

B : in STD_LOGIC;

Carry_in : in STD_LOGIC;

Sum : out STD_LOGIC;

Carry_out : out STD_LOGIC

);

end FULLADD;

architecture BEHA VIOR of FULLADD is

function Majority (A,B,C : STD_LOGIC)

return STD_LOGIC is

begin

return (( A and b) or (A and C) or ( B and C ));

end Majority;

begin

Sum <= A xor B xor Carry_in;

Carry_out <= Majority(A,B,Carry_in);

end BEHA VIOR;

附录三参数化元件实例

-- Filename ﹕Reg_group.vhd

-- Author ﹕suwenbiao

-- Description ﹕A example of Reg Group with generic size

-- Called by ﹕Top module

-- Revision History ﹕00-03-18

library IEEE;

use IEEE.std_logic_1164.all;

entity REG_GROUP is

generic (Size : integer : = 2);

port(

Clk : in STD_LOGIC;

Rst : in STD_LOGIC;

Load : in STD_LOGIC;

D : in STD_LOGIC_VECTOR(Size - 1 downto 0);

Q : out STD_LOGIC_VECTOR(Size - 1 downto 0) );

end REG_GROUP;

architecture BEHA VIOR of REG_GROUP is

begin

R_p: process(Clk,Rst)

begin

if (Rst = '1') then

Q <= (others => '0') ;

elsif(Clk 'event and Clk = '1') then

Q <= D;

end if;

end process;

end BEHA VIOR;

调用语句:

U1:REG_GROUP map(4)

port map (

Clk => Clk,

Rst => Rst,

Load => Load,

D => D,

Q => Q);

则该寄存器数据宽度为4。

实验一 用VHDL语言设计组合逻辑电路

实验一用VHDL语言设计组合逻辑电路 一、实验目的:掌握用VHDL语言设计组合逻辑电路的方法。熟悉QuartusⅡ的 操作。 二、实验仪器:PC机一台 三、实验内容: 1.用VHDL语言设计4选1数据选择器。 2.用文本输入法输入 3.建立工程,编译,改错,直至编译通过 4.仿真,验证所设计电路的正确性 四、操作步骤: 1、在所使用的计算机数据盘里建立自己的文件夹 2、打开QuartusII 3、单击工具栏中的new,在出现的对话框中选择VHDL File,点击OK。 4、输入设计程序。 输入结束后,将程序保存在自己的文件夹中。注意:存盘的文件名应该跟实体名相同。 5、创建工程。创建工程有两种方法:第一种方法是在保存文件后出现的对话框 中点击‘是’,按提 示进行操作;

第二种方法是在出现的对话框点击‘否’。 第一种方法的具体过程: 点击‘是’,出项下面的框 点击‘Next’,出项 不需要任何修改,继续点击‘Next’,出项

继续点击‘Next’,在后面出现的框图中继续点击‘Next’,直到没有‘Next’选项,点击‘Finish’,这样就完成工程的创建。 第二种方法的具体过程:点击‘否’ 此时要创建工程,点击菜单File下的“New Preject Wizard”。出现框图: 点击‘Next’,出项

名,点击打开(或双击要创建工程的文件名),出现 项目名称和文件名称相同。点击‘Next’,出现

点击,在出现的对话框点击文件名,点击‘打开’,出现 点击右边的‘add’,出现

点击‘Next’,在后面出现的框图中继续点击‘Next’,直到没有‘Next’选项,点击‘Finish’,这样就完成工程的创建。 6、观察QUARTUS 界面 点击箭头所指图标,观察箭头上方的变化,点击+号,双击出项的文件

门电路VHDL语言

“非”门 library ieee; use ieee.std_logic_1164.all; entity not1 is port(a:in std_logic; b:out std_logic); end entity not1; architecture behav of not1 is begin b<=not a; end architecture behav; “与”门 library ieee; use ieee.std_logic_1164.all; entity and2 is port(a,b:in std_logic; c:out std_logic); end entity and2; architecture behav of and2 is begin c<=a and b; end architecture behav; “与非”门 library ieee; use ieee.std_logic_1164.all; entity nand2 is port(a,b:in std_logic; c:out std_logic); end entity nand2; architecture behav of nand2 is begin c<=not(a and b); end architecture behav; “或非”门 library ieee; use ieee.std_logic_1164.all; entity nor2 is port(a,b:in std_logic; c:out std_logic); end entity nor2; architecture one of nor2 is begin c<=not(a or b); end architecture one; “异或非”门 library ieee; use ieee.std_logic_1164.all; entity xor2 is port(a,b:in std_logic; c:out std_logic); end entity xor2; architecture one of xor2 is Begin c<=not( ( (not a)and b)or(a and(not b) ) ); end architecture one; D触发器 library ieee; use ieee.std_logic_1164.all; entity dffa is port(D,clk,clr:in std_logic; Q:out std_logic); end entity dffa; architecture behave of dffa is begin process(clk,D,clr) begin if clr='1' then Q<='0'; Elsif clk'event and clk='1' then Q<=D; end if; end process; end architecture behave; T触发器 library ieee; use ieee.std_logic_1164.all; entity tffa is port(T,clk,clr: in std_logic; Q: buffer std_logic); end entity tffa; architecture behave of tffa is begin process(clk,T,clr) begin if clk'event and clk='1'then if clr='1' then Q<='0'; Elsif t='1'then Q<=not Q; else Q<=Q; End if; end if; end process; end architecture behave; JK触发器 library ieee; use ieee.std_logic_1164.all; entity jk is port(J,K,clk, in std_logic; Q: buffer std_logic); end entity tffa; architecture behave of jk is begin process(clk,J,K) begin if clk'event and clk='1'then Q<=( (J and(not Q) )or( (not K)and Q) ); end if; end process; end architecture behave;

vhdl语言编写的门电路

ENTITY AND2A IS PORT (A,B:IN BIT; C:OUT BIT); END ENTITY AND2A; ARCHITECTURE EX1 OF AND2A IS BEGIN C<=A AND B; END ARCHITECTURE EX1; 用VHDL设计一个具有高电平使能端的三态非门LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY trigate IS PORT( A, EN: IN STD_LOGIC; Y: OUT STD_LOGIC ); END trigate; ARCHITECTURE a OF trigate IS BEGIN PROCESS( A, EN) BEGIN IF EN ='0' THEN Y<= 'Z'; ELSE Y<= A; END IF; END PROCESS; END a;

entity nand3a is port (A,B,C:in bit; Y:out bit); end entity nand3a; architecture text2 of nand3a is begin Y<=not (A and B and C ); end architecture text2; 用VHDL设计电路 entity b3 is Port (A, B,Ci: in bit; S,Co:out bit); end entity b3; architecture text2 of b3 is begin S<= A xor B xor Ci ; Co<=( A and B) or (Ci and (A xor B )); end architecture text2;

EDA中VHDL基本逻辑电路设计

第三章基本逻辑电路设计 3.1 组合逻辑电路设计 一、简单门电路设计 例:3输入“与非”门电路 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY nand3 IS PORT(a,b,c:IN STD_LOGIC; y:OUT STD_LOGIC); END nand3; ARCHITECTURE nand3_1 OF nand3 IS BEGIN y<=NOT(a AND b AND c); END nand3_1; LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY nand3 IS PORT(a,b,c:IN STD_LOGIC; y:OUT STD_LOGIC); END nand3; ARCHITECTURE nand3_2 OF nand3 IS BEGIN t4:PROCESS(a,b,c) VARIABLE comb:STD_LOGIC_VECTOR(2 DOWNTO 0); BEGIN comb:= a & b & c; CASE comb IS WHEN “000” =>y<=‘1’; WHEN “001” =>y<=‘1’; WHEN “010” =>y<=‘1’; WHEN “011” =>y<=‘1’; WHEN “100” =>y<=‘1’; WHEN “101” =>y<=‘1’; WHEN “110” =>y<=‘1’; WHEN “111” =>y<=‘0’; WHEN OTHERS=>y<=‘X’; END CASE; END PROCESS; END nand3_2; 二、编码器、译码器、选择器 例:地址译码器 假设一个微处理器存储空间为从0000H到FFFFH, 将其分成5部分,它们的地址分配如下: 0000H—DFFFH为动态随机存储器DRAM使用;E000H—E7FFH为I/O设备使用; E800H---EFFFH备用; F000H—F7FFH为第一个只读存储器ROM1使用;F800H—FFFFH为第二个只读存储器ROM2使用;其中选通控制信号DRAM1,IO,ROM1,ROM2均为低电平有效。 例:地址全译码 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY ad_decoder IS PORT( address : IN STD_LOGIC_VECTOR(15 downto 0); DRAM1,IO,ROM1,ROM2 : OUT STD_LOGIC); END ad_decoder ; ARCHITECTURE a OF ad_decoder IS BEGIN PROCESS(address) BEGIN IF address<=x”dfff” THEN DRAM<=‘0’; IO<=‘1’; ROM1<=‘1’; ROM2<=‘1’; ELSIF address>=x”e000” AND address<=x”e7ff” THEN DRAM<=‘1’; IO<=‘0’; ROM1<=‘1’; ROM2<=‘1’; ELSIF address>=x”f000” AND address<=x”f7ff” THEN DRAM<=‘1’; IO<=‘1’; ROM1<=‘0’; ROM2<=‘1’; ELSIF address>=x”f800” THEN DRAM<=‘1’; I/O<=‘1’; ROM1<=‘1’; ROM2<=‘0’; END IF; End PROCESS; END a;

七人表决器-VHDL语言编写代码

------------------------------------- -- Title: 七人表决器-- -- Author:Pan hongtao -- -- Data: 2006-10-1 -- ---------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; -------------------------------------------------------------------- entity exp12 is port( k1,K2,K3,K4,K5,K6,K7 : in std_logic; --输入:7个人 ledag : out std_logic_vector(6 downto 0); --数码管显示 m_Result : out std_logic --表决结果 ); end exp12; -------------------------------------------------------------------- architecture behave of exp12 is signal K_Num : std_logic_vector(2 downto 0); signal K1_Num,K2_Num: std_logic_vector(2 downto 0); signal K3_Num,K4_Num: std_logic_vector(2 downto 0); signal K5_Num,K6_Num: std_logic_vector(2 downto 0); signal K7_Num : std_logic_vector(2 downto 0); begin process(K1,K2,K3,K4,K5,K6,K7) --计算表决同意人数 begin K1_Num<='0'&'0'&K1; K2_Num<='0'&'0'&K2; K3_Num<='0'&'0'&K3; K4_Num<='0'&'0'&K4; K5_Num<='0'&'0'&K5; K6_Num<='0'&'0'&K6; K7_Num<='0'&'0'&K7; end process; process(K1_Num,K2_Num,K3_Num,K4_Num,K5_Num,K6_Num,K7_Num) begin K_Num<=K1_Num+K2_Num+K3_Num+K4_Num+K5_Num+K6_Num+K7_Num; end process; process(K_Num) --根据人数输出结果 begin

VHDL语言编写规范

VHDL语言编写规范 目录 目录 (1) 1 目的 (2) 2 范围 (2) 3 定义 (2) 4 规范内容:VHDL编码风格 (2) 4.1 标识符(Identifiers)命名习惯 (2) 4.2 数据对象和类型 (4) 4.3 信号和变量 (5) 4.4 实体 (5) 4.5 语句 (7) 4.6 运算符(Operator) (10) 4.7 function (10) 4.8 procedure (11) 4.9 类属( generics) (11) 4.10 package (12) 4.11 FSM(有限状态机) (12) 4.12 Comments (12) 4.13 TAB键间隔 (12) 4.14 语句书写规范规定 (13) 5 程序中的注释 (13) 6 代码模块划分 (14) 7 代码编写中容易出现的问题 (15) 7.1 资源共享问题 (15) 7.2 组合逻辑描述的多种方式 (15) 7.3 考虑综合的执行时间 (16) 7.4 避免使用Latch (16) 7.5 多赋值语句案例:三态总线 (16) 附录一VHDL保留字 (18) 附录二函数书写实例 (19) 附录三参数化元件实例 (20) 附录四程序包书写实例 (21)

1 目的 编写该规范的目的是提高书写VHDL代码的可读性、可修改性、可重用性;优化代码综合和仿真结果,指导设计工程师使用VHDL 规范代码和优化电路,规范化公司的ASIC/FPGA 设计输入,从而做到: a、逻辑功能正确; b、可快速仿真; c、综合结果最优; d、可读性最好。 2 范围 该规范设计VHDL编码风格、规定,编码中应注意的问题,VHDL代码书写范例等,适用于所有的采用VHDL代码进行设计的项目。 3 定义 VHDL:Very high speed IC Hardware Description Language,甚高速集成电路的硬件描述语言。 FSM:Finite Status Machine,有限状态机 Simulate:仿真,通过输入激励在计算机上验证设计是否正确。包括RTL仿真和门级仿真。 模拟:是指对一个物理器件的结构、功能或其他特性如延时特性等用抽象的语言或高级语言(如用C语言进行算法描述)所进行的建模。 4 规范内容:VHDL编码风格 设计必须文档化。要将设计思路,详细实现等写入文档,然后经过严格评审通过后才能进行下一步的工作。这样做乍看起来很花时间,但是从整个项目过程来看,绝对要比一上来就写代码要节约时间,且这种做法可以使项目处于可控、可实现的状态,便于对程序代码的修改、学习。 本文中提到的VHDL编码规则和建议适用于VHDL的任何一级(RTL,behavioral,gate_level),也适用于出于仿真,综合或二者结合的目的而设计的模块。 4.1 标识符(Identifiers)命名习惯 标识符用于定义实体名、结构体名、信号和变量名等,选择有意义的命名对设计是十分重要的。命名包含信号或变量诸如出处、有效状态等基本含义,下面给出一些命名的规则,包括VHDL语言的保留字。 1. 标识符定义命名规定

数字电路设计实验vhdl语言实验报告

实验一秒表计数器的设计 一、实验目的: 本实验通过设计四种频率可选的数字时钟系统,以达到熟悉VHDL 语言编程语法、设计思路和熟练掌握Quartus II 开发软件的目的。 二、实验内容: 该数字时钟的显示格式如下所示:HH:MM:SS,其中HH表示时计数的两位,MM表示分计数的两位,SS表示秒计数的两位。本系统输入信号分别为复位信号rst(高有效)、sel(两位信号,分别可以选择2分频、4分频8分频和16分频)、clk_in(时钟信号)、8位时输出、8位分输出、8位秒输出(其中高4为表示对应的高半字节、低4位表示的低半字节,譬如当时间为08:59:30时,时输出为”0000_1000”,分输出为”0101_1001”,秒输出为”0011_0000”)。该时钟系统可以通过Sel信号时钟运行的快慢。 三、实验流程: 通过对实验内容的分析:可以考虑时钟系统的可由三部分组成:1、分频器: 分频器为时序电路并且通过《数字电路》理论课程的学习可知由计数器来实现,同学可以回想一下实验1中是如何实现计数器电路的设计),该模块主要产生2、4、8、16分频的时钟信号; 2、多路选择器: 在VHDL中多路选择器为组合逻辑,可以有多种实现方法,在这里主要选用了case语句来实现。该模块的作用是从分频器中根据Sel

信号选择适当的时钟信号; 3、时钟控制器: 该模块比较复杂,主要实现功能是实现一个24小时的计时。当时间为00:00:59的时候下一个时钟到来时状态的跳变为00:01:00,计时中多数计数为加1操作,有几个特殊状态需要重点考虑:当时间产生分进数时,譬如上例。当时间产生时进数时,譬如00:01:59时刻的下一个状态为00:02:00;当时间产生时进数时,譬如00:59:59是个的下一个状态为01:00:00。当时间产生天进数时,譬如23:59:59的下一个状态为00:00:00。 四、仿真要求: 本次试验的结果全部采用功能仿真分析: 1、在结果图中能够看到让复位信号rst为有效的情况下,所有的输出为00:00:00; 2、当频率选择输出分别为”00”、”01”、”10”、”11”时秒为的进数分别包含2、4、8、16倍clk_in的时钟周期; 3、可以看到完整的计时周期00:00:00->23:59:59->00:00:00。 五、实验代码: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL;

相关文档
相关文档 最新文档