编程语言介绍:Cupl
CUPL(Compiler for Universal Programmable Logic)是一种高级硬件描述语言,专门用于可编程逻辑器件(PLD)的设计和开发。由Logical Devices公司开发,现被Atmel等多家半导体厂商采用作为其PLD/CPLD开发工具的标准语言(以下代码均使用Ateml公司开发的WinCupl开软软件)。关于WinCupl的基础使用可以参考WinCupl及WinSim基础操作
可编程逻辑基本概念
这里先讲述下可编程逻辑的基本概念,可编程逻辑是指一类包含逻辑元素阵列(与门、或门、反相器、锁存器、触发器等)的组件家族。这些逻辑元素可以根据用户需求和支持的组件功能,配置成任何所需的逻辑功能。可编程逻辑器件包含多个类别:ASIC(专用集成电路)、FPGA(现场可编程门阵列)、PLA(可编程逻辑阵列)、PROM(可编程只读存储器)、PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)以及复杂PLD(可编程逻辑器件)。
ASIC(专用集成电路)
在Atmel官方文档中,ASIC(专用集成电路)被特别提及,因为它们是用户可定义器件。与其他器件不同,ASIC可能包含模拟功能、数字功能以及模数混合功能。一般来说,ASIC是掩模可编程的,而不是用户可编程的。这意味着制造商会根据用户规格配置器件。ASIC主要用于将大量逻辑功能集成到单个器件中。然而,这些器件具有较高的初始成本,因此主要应用于需要大批量生产的场合。由于ASIC的特性,CUPL和其他可编程逻辑语言无法支持这些器件。用户可编程器件是指具有预定义通用架构的器件,用户可以通过一套开发工具将设计编程到器件中。而通用架构可能有所不同,但通常包含一个或多个与项和或项阵列,用于实现逻辑功能。许多器件还包含触发器和锁存器的组合,这些存储元素可用于器件的输入和输出端。更复杂的器件包含宏单元,宏单元允许用户根据设计需求配置输入和输出类型。这种架构设计使得用户能够灵活实现各种数字逻辑功能,同时通过可编程特性满足不同应用场景的需求。现代可编程逻辑器件的发展使得设计人员能够在保持设计灵活性的同时,获得接近专用芯片的性能表现。
PAL(可编程阵列逻辑器件)
PAL(Programmable Array Logic)器件内部架构由可编程的与项驱动固定的或项构成。所有输入信号都可以通过与逻辑进行组合,但特定的与项专用于特定的或项。如果器件包含宏单元,通常采用PAL架构。典型宏单元可通过三态使能配置为输入、输出或输入/输出(I/O)模式(宏单元特性)。通常配备输出寄存器,这些寄存器可选择是否与相关I/O引脚配合使用(寄存器功能)。部分宏单元配备多个寄存器,支持多种阵列反馈机制,偶尔还支持宏单元间反馈(高级功能)。PAL主要用于替代多个TTL逻辑功能,也就是GGBond教授常言的"胶合逻辑"。
基本PAL架构如下(原图来自ATMEL手册):
GAL(通用阵列逻辑器件)
GAL(Generic Array Logic)器件设计用于通过宏单元仿真多种常见PAL器件。如果用户设计需要多个PAL实现,可通过配置相同GAL器件来仿真各个PAL功能。CAL显著减少库存器件种类,提高单种器件采购量,大批量的采购同种器件可降低单价,同时它支持电擦除特性,极大方便设计工程师进行设计迭代。
基本GAL架构如下(原图来自ATMEL手册):
PLA(可编程逻辑阵列)
PLA(Programmable Logic Array)器件同时包含可编程的与项和或项,允许任何与项馈送到任何或项。在逻辑功能方面具有最高灵活性,通常具有从或阵列反馈至与阵列的能力,可用于实现异步状态机。制造商们开发了称为序列器的PLA变种,具有从或阵列输出到与阵列的注册反馈,更适合同步状态机实现(序列器变种)
复杂PLD(复杂可编程逻辑器件)
复杂PLD(Complex Programmable Logic Device)正如其名,是具有PLA某些特性的超大规模PAL器件。它的基本架构类似PAL,但能够为任何固定或项增加与项数量,通过借用相邻与项或使用扩展阵列的与项实现资源扩展,能够实现大多数逻辑设计需求
FPGA(现场可编程门阵列)
FPGA(Field Programmable Gate Arrays,现场可编程门阵列)本质上是包含多级逻辑结构的电可编程门阵列集成电路。这类器件突破了传统与-或阵列的架构限制,提供了高度灵活的可编程逻辑解决方案。FPGA器件支持大规模门电路集成,可以提供优异的处理速度,同时支持大量用户可定义的输入输出端口(远多于传统的PLD或CPLD输入输出端口),提供类似门阵列的标准化设计平台,具备高度灵活的布线方案。
FPGA内部采用矩阵式可配置逻辑块(Configurable Logic Blocks, CLBs)结构,周边环绕输入输出块(I/O Blocks, IOBs)环:每个CLB包含可编程组合逻辑单元和存储寄存器,组合逻辑部分能够实现输入变量的任何布尔函数,存储寄存器提供时序逻辑实现能力。IOB模块具有高度可配置特性,可独立编程为输入模式、支持三态控制的输出模式、可配置为双向引脚,同时内置触发器用于输入输出缓冲。FPGA采用更先进的互连技术,在CLB行列间形成水平垂直布线网络,连接IOB和CLB的输入输出到邻近线路(可编程开关),贯穿器件全长或全宽,绕过交叉点以最小延迟传输关键信号(长线资源)
基本FPGA架构如下(原图来自ATMEL手册):
Cupl语言代码基础结构
这里先上一段官方的基础代码(使用f1504来制作JK触发器):
Name JKTest ;
PartNo ATF1504 ;
Date 11/17/99 ;
Revision 01 ;
Designer Yad Dhami ;
Company Atmel ;
Assembly None ;
Location San Jose ;
Device f1504plcc44 ;
/* *************** INPUT PINS *********************/
PIN 9 = A ; /* */
PIN 6 = B ; /* */
PIN 43 = CLK ; /* */
/* *************** OUTPUT PINS *********************/
PIN 11 = Emulate ;
/* */
/* */
/* D = (J & !Q) # (J & !K) # (!K & Q); */
/* T = (J & K) # (!J & K & Q) # (J & !K & !Q); */
/* Emulating the JK FLip flop using D Flip Flops available in Device*/
$Macro JK_Flip_Flop Qout Jin Kin;
Qout.d = (Jin & !Qout) # (Jin & !Kin) # (!Kin & Qout);
$Mend
Emulate.ck =CLK;
EmulateJ = A & B;
EmulateK = !(A & B);
JK_Flip_Flop(Emulate, EmulateJ, EmulateK);/*Implement JK Flip Flop*/
在创建设计时,采用"自上而下"(Top-Down)的设计方法,从设计的全局定义开始,然后对主定义的每个元素重复全局定义过程,如此迭代直至完整定义整个项目。
基础的Cupl代码通常分为四个模块:
1.头部声明模块(Header Section)
头部模块提供项目的元数据,确保编译器和编程工具能正确识别设计目标:
Name JKTest ;
PartNo ATF1504 ;
Date 11/17/99 ;
Revision 01 ;
Designer Yad Dhami ;
Company Atmel ;
Assembly None ;
Location San Jose ;
Device f1504plcc44 ;
Name:定义设计名称"JKTest",用于标识项目文件。PartNo:指定目标器件型号ATF1504,属于Atmel CPLD系列。Date/Revision:记录设计日期(1999年11月17日)和版本号(01),用于版本管理。Designer/Company:声明设计者(Yad Dhim)和公司信息(Atmel)。Assembly/Location:保留的装配和位置信息,本例中未使用。Device:具体器件型号"f1504plcc44",指向44引脚PLCC封装的ATF1504器件。
二、输入引脚定义模块(Input Pin Definitions)
引脚定义必须在源文件开头声明,这自然成为设计的起点。用于定义埋入寄存器的节点和引脚节点也应在源文件开头声明。如果设计者已确定目标器件,需要进行引脚分配;但在创建虚拟设计时,只需填写后续将分配给引脚的变量名称,通常包含引脚编号的区域留空。
这里有一点需注意,在ATF1504器件中,引脚43通常为专用全局时钟输入,确保低歪斜时钟分配。代码中的引脚6和9为通用I/O,配置为输入模式。
/* *************** INPUT PINS *********************/
PIN 9 = A ; /* 输入信号A */
PIN 6 = B ; /* 输入信号B */
PIN 43 = CLK ; /* 全局时钟信号 */
三、输出引脚定义模块(Output Pin Definitions)
引脚11分配为输出信号"Emulate",代表JK触发器的状态输出,该引脚将显示根据J、K输入和时钟边沿变化后的触发器状态。输出引脚直接映射到器件的宏单元输出,通过D触发器结构模拟JK触发器行为。
/* *************** OUTPUT PINS *********************/
PIN 11 = Emulate ; /* JK触发器仿真输出 */
四、逻辑实现模块(Logic Implementation)
定义宏JK_Flip_Flop,参数包括输出Qout、J输入Jin和K输入Kin。宏体实现标准JK触发器的特征方程:Q⁺ = J·Q' + K'·Q,通过D触发器仿真:D = (J & !Q) # (J & !K) # (!K & Q),输入A和B组合生成J和K控制信号,当时钟边沿到来时,D触发器根据JK逻辑方程更新状态,输出引脚Emulate实时反映JK触发器的状态变化。
/* *************** 宏定义 *********************/
$Macro JK_Flip_Flop Qout Jin Kin;
Qout.d = (Jin & !Qout) # (Jin & !Kin) # (!Kin & Qout);
$Mend
/* *************** 时钟分配 ********************/
Emulate.ck =CLK;
/* *************** 控制信号生成 ****************/
EmulateJ = A & B;
EmulateK = !(A & B);
/* *************** 宏调用 *********************/
JK_Flip_Flop(Emulate, EmulateJ, EmulateK);
Cupl基础语法
这里再放一段更加基础的代码,使用最简单的PLD芯片来制作各种逻辑门
Name Gates;
Partno CA0001;
Revision 04;
Date 9/12/89;
Designer G. Woolhiser;
Company Logical Devices, Inc.;
Location None;
Assembly None;
Device g16v8a;
/****************************************************************/
/* */
/* This is a example to demonstrate how CUPL */
/* compiles simple gates. */
/* */
/****************************************************************/
/*
* Inputs: define inputs to build simple gates from
*/
Pin 1 = a;
Pin 2 = b;
/*
* Outputs: define outputs as active HI levels
*
*/
Pin 12 = inva;
Pin 13 = invb;
Pin 14 = and;
Pin 15 = nand;
Pin 16 = or;
Pin 17 = nor;
Pin 18 = xor;
Pin 19 = xnor;
/*
* Logic: examples of simple gates expressed in CUPL
*/
inva = !a; /* inverters */
invb = !b;
and = a & b; /* and gate */
nand = !(a & b); /* nand gate */
or = a # b; /* or gate */
nor = !(a # b); /* nor gate */
xor = a $ b; /* exclusive or gate */
xnor = !(a $ b); /* exclusive nor gate */
标准逻辑运算符
如以上代码所示,CUPL提供四种标准逻辑运算符,下表按优先级从高到低列出:
| 运算符 (Operator) | 示例 (Examples) | 描述 (Description) | 优先级 (Precedence) |
|---|---|---|---|
| ! | !A | NOT (非运算) | 1 (最高) |
| & | A & B | AND (与运算) | 2 |
| # | A # B | OR (或运算) | 3 |
| $ | A $ B | XOR (异或运算) | 4 (最低) |
关键字


其余还有关键字:
VARIABLE:定义中间变量。CONDITION:条件语句,替代复杂IF-ELSE逻辑。REPEAT:循环宏,用于生成重复模式(如$REPEAT)。TITLE、PARTNO等:头部信息关键字,用于文档管理
算数运算符(用于 $repeat和 $macro命令)

算术函数(计算以x为底的对数)

逻辑方块
使用布尔方程定义组合逻辑,运算符包括 !(NOT)、&(AND)、#(OR)、$(XOR):
EQUATIONS
OUT1 = A & B; // AND 门
OUT2 = !(A # B); // NOR 门
状态机
使用 SEQUENCE关键字定义同步状态机,包括状态转换和输出,自动处理状态编码和寄存器配置,支持D、T、JK等多种触发器类型(通过扩展如 .D、.T):
SEQUENCE STATE_MACHINE {
PRESENT S0 IF (INPUT == 1) NEXT S1 OUT OUT1;
PRESENT S1 NEXT S2 OUT OUT2;
DEFAULT NEXT S0;
}

真值表
使用 TABLE直接映射输入组合到输出,适用于解码器或查找表。如以下代码TABLE语法实现硬连线查找表,在嵌入式系统中实现将6位半径值映射到8位周长近似值,避免实时浮点运算
Name Lookup;
Partno CA0017;
Revision 01;
Date 3/10/85;
Designer T. Kahl;
Company Assisted Technology, Inc.;
Location San Jose, CA.;
Assembly Example;
Device g22v10cplcc;
/** Inputs **/
/* Pin [2..3,9..12] = [R0..5]; Radius of Circle */
Pin [2..3] = [R0..R1];
Pin [9..12] = [R2..R5];
/** Outputs **/
Pin [19..20] = [P4..P5]; /* Perimeter of Circle */
Pin 21 = P3;
Pin 23 = P0;
Pin [24..25] = [P2..P1];
Pin 26 = P6;
Pin 18 = P7;
/** Declarations and Intermediate Variable Definitions **/
Field Radius = [R5..0];
Field Perimeter = [P7..0];
/** Logic Equations **/
Table Radius => Perimeter {
/* Radius Perimeter Radius Perimeter */
/* ------ --------- ------ --------- */
'd'00 => 'd'000; 'd'01 => 'd'006;
'd'02 => 'd'013; 'd'03 => 'd'006;
'd'04 => 'd'025; 'd'05 => 'd'019;
'd'06 => 'd'040; 'd'07 => 'd'031;
'd'08 => 'd'050; 'd'09 => 'd'044;
'd'10 => 'd'063; 'd'11 => 'd'069;
'd'12 => 'd'075; 'd'13 => 'd'082;
'd'14 => 'd'088; 'd'15 => 'd'094;
'd'16 => 'd'101; 'd'17 => 'd'107;
'd'18 => 'd'113; 'd'19 => 'd'119;
'd'20 => 'd'126; 'd'21 => 'd'132;
'd'22 => 'd'138; 'd'23 => 'd'145;
'd'24 => 'd'151; 'd'25 => 'd'157;
'd'26 => 'd'163; 'd'27 => 'd'170;
'd'28 => 'd'176; 'd'29 => 'd'182;
'd'30 => 'd'188; 'd'31 => 'd'195;
'd'32 => 'd'201; 'd'33 => 'd'207;
'd'34 => 'd'214; 'd'35 => 'd'220;
'd'36 => 'd'226; 'd'37 => 'd'232;
'd'38 => 'd'239; 'd'39 => 'd'245;
'd'40 => 'd'251;
}
扩展变量
通过后缀(如 .CK、.OE)配置宏单元功能,如时钟、输出使能等,比如.CK:产品项时钟(REG.CK = CLK;),允许精细控制设备资源,如使用 .CK替代全局时钟以优化时序。
宏和包含文件
使用 $INCLUDE和宏库实现代码复用,如以下TTL代码使用的ttl.m文件
Name TTL;
Partno CA0001;
Revision 01;
Date 11/12/89;
Designer J. Liu;
Company Logical Devices, Inc.;
Location None;
Assembly None;
Device G20V8A;
/****************************************************************/
/* */
/* This is an example to demonstrate how CUPL can be */
/* used to incorporate TTL devices into CUPL syntax. */
/* */
/****************************************************************/
$include ttl.m
/** Inputs **/
Pin 1 = CLK ; /* */
Pin 2 = INA ; /* */
Pin 3 = INB ; /* */
Pin 4 = INC ; /* */
Pin 5 = IND ; /* */
Pin 6 = INE ; /* */
Pin 7 = INF ; /* */
Pin 8 = ING ; /* */
Pin 9 = INH ; /* */
/** Outputs **/
Pin 22 = OUT22 ; /* */
Pin 21 = OUT21 ; /* */
/** Logic Equations **/
TTLSN7400( INA, INB, IM1, INC, IND, IM2, GND, NC, NC, NC, NC, NC, NC, VCC );
TTLSN7402( IM1, IM2, OUT22, NC, NC, NC, GND, NC, NC, NC, NC, NC, NC, VCC );
TTLSN7454( INA, INB, INC, IND, INE, NC, GND, OUT21, INF, ING, NC, NC, INH, VCC );
更多推荐
所有评论(0)