举例:补码平方和
module resource_share (data_in, square);
input [7:0] data_in; //输入是补码
output [15:0] square;
wire [7:0] data_temp;
assign data_temp = (data_in[7])? (~data_in + 1) : data_in;
assign square = data_temp*data_temp;
endmodule

- 本例使用Synplify Pro7.2进行综合,关闭了“resource sharing”等所有优化选项;
- 不同的综合软件,同一软件的不同版本、不同的优化参数设置、不同的目标器件等因素都可能造成不同的综合结果;
- 目前很多综合软件都有“resource sharing”或类似的优化选项,软件在逻辑功能不变的情况下进行资源共享。上例中,如果打开Synplify的“resource sharing”选项,则综合结果与第二种代码描述的综合结果完全一致;
- 不能因为综合软件的优化能力增强,而片面的依靠它,还是要养成好的coding style。
--综合工具的优化能力还是有限的;
--依靠综合工具的优化能力并不可靠。
逻辑复制
- 逻辑复制是通过增加面积而改善时序条件的优化方法;
- 如果某个信号需要驱动后级的很多单元,为了增加这个信号的驱动能力,,就可以复制生成这个信号的逻辑,使多路同频同相的信号驱动后续电路;
- 可见,逻辑复制与资源共享,仍然体现了速度和面积的平衡问题。一个侧重于速度目标,一个侧重于面积目标。

逻辑复制:
sign data_out = (sel)? (a+b) : (c+d);


香农扩展
- 香农扩展(布尔逻辑扩展)也是一种通过逻辑复制、增加面积、提高速度的时序优化方法;
- 是卡诺逻辑化简的反向操作。
- 通过增加多路选择器,缩短了某个优先级高、但组合路径长的信号的路径时延,从而提高该关键路径的工作频率。
- 优化目标决定是否使用这种时序优化手段。


信号敏感表
-
信号敏感表:VHDL的process后、Verilog的always后的信号列表,模块的启动由信号敏感表中的信号来触发。
-
时序逻辑:在信号敏感表写明时钟信号的正负触发沿即可;
-
组合逻辑:
--将进程中使用到的所有输入信号和条件判断信号都列在信号敏感表中;
--不完整的信号敏感表会造成前仿真结果和综合、实现后仿真结果不一致;
--不同的综合工具处理方法不一样。一般综合软件的默认做法是,将处理进程中用到的所有输入和条件判断信号都默认添加到综合结果的信号敏感表中,并对原设计敏感表中遗漏的信号给出警告信息。
复位逻辑
- 复位方式:
--与设计内容有关;
--与目标器件的底层硬件结构密切相关。
- 异步复位 vs.同步复位:
--如果信号敏感表中含有复位信号的正沿或负沿触发,则属于异步复位逻辑;
--一般来说,采用同步复位逻辑的设计工作频率较高;
--使用异步复位逻辑的设计较简单;
- 对于全局复位逻辑,不同厂商的器件的推荐设计不同:
--对于CPLD,一般推荐使用异步的全局复位逻辑;
--Xilinx的新型FPGA器件不推荐使用全局复位逻辑;
--Lattice的多数FPGA器件推荐使用全局复位资源 。
有限状态机(FSM)设计
- 有限状态机是重要的逻辑设计方法,通过状态转移图可以将复杂的控制时序分解为状态之间的转换关系。
- 状态机类型:
--Moore型:状态机的输出仅是当前状态的函数,且仅在时钟跳变时发生变化;
--Mealy型:状态机的输出是当前状态和当前输入的函数,任何输入信号的变化都可能引起输出信号的变化,不与时钟同步。
- 状态机的编码:
--二进制编码 vs. One-Hot编码
-例:4个状态
-二进制编码:00, 01, 10, 11(或格雷码等)
-One-Hot编码:0001, 0010, 0100, 1000
--二进制编码使用较少的触发器和较多的组合逻辑;适用于CPLD和小型状态机设计;
--One-Hot编码使用较多的触发器和较少的组合逻辑;适用于FPGA和大型状态机设计;
--可通过设置综合软件的选项来选择状态机编码;
- 有限状态机设计的方法有两大类:
--将状态转移和状态操作和判断写在一个模块里;
--将状态转移写成一个单独的模块,将状态的操作和判断写到另一个模块中;
- 其中后者是比较好的设计方式。
--便于阅读、理解、维护;
--状态转移是用寄存器实现的,是同步时序部分;状态的判断是组合逻辑;
-利于综合工具优化代码;
-利于用户添加时序约束;
-利于布局布线软件对设计的实现。
- 个健壮的状态机应该具备初始化状态和默认状态(缺省状态);
--当芯片加电或复位后,状态机应该能够自动将所有判断条件复位,并进入初始化状态;
--状态机应该有一个默认状态,当转移条件不满足或状态发生突变时,保证逻辑不会陷入死循环。这就要求尽量使用完备的条件判断语句。
-VHDL中,使用case语句时,要用when others建立默认状态,使用if…then…else语句时,用else指定默认状态;
-Verilog中,使用case语句时,要用default建立默认状态,使用if…else语句时也要完备。
- 指定默认的输出值:
--能够防止无意生成的锁存器;
--输出经过一个寄存器,以获得更好的时序环境;
- 状态机输出逻辑复用
--如果在状态机中有多个状态都会执行某项操作,则可以在状态机外部定义这个操作的具体内容,在状态机中仅仅调用这个操作即可。
--相当于前面提到的资源共享。
- HDL设计源代码
--作为好的源代码,应该包含文件头和修订列表(以获得修改情况)。另外,每一个重要的操作和定义后都要加上注释。
--文件头包含以下内容:
-模块名
-文件名
-需要的库
-模块描述
-使用的仿真器--其运行平台和版本
-使用的综合工具,其运行平台和版本
-作者
- 修订列表包含以下内容:
--修订版本号
--改动的时间
--修订者
--改动的详细描述
例:文件头
-- Module : MAC (Multiply Accumulate Unit)
-- File : mac.vhd
-- Library : ieee,.......
-- Description : It is a general Purpose Multiply Accumulate Unit
-- Simulator : Modelsim 5.2 / Windows 95
-- Synthesizer : Synplify / Windows95
-- Author / Designer : Harish Y S (harish@opencores.org)
例:修改列表
--------------------------------------------------------------------
-- Revision Number : 1
-- Date of Change : 20th March 2000
-- Modifier : Harish Y S (harish@opencores.org)
-- Description : Initial Design
--------------------------------------------------------------------
-- Revision Number : 2
-- Date of Change : 15th July 2000
-- Modifier : XYZ (email)
-- Description : Modified the ????.to improve ????..
--------------------------------------------------------------------