随着微电子技术和超大规模集成电路技术的高速发展,进行电子系统设计时的系统复杂度不断加大,系统软件硬件的异构度提高,软件在系统中所占的比例也越来越大。传统的设计方法在进行电子系统设计时,一般先由系统工程师设计整个系统的架构,画出系统框图(包括各个模块),再用高级编程语言(一般是C/C++/JAVA)实现各个模块的算法,然后进行整个系统的仿真,确定系统的最佳结构、最佳实现算法及其它相关参数。待系统模型确定以后,进行系统软硬件分割设计,但由于缺乏统一的软硬件协同设计验证平台,大多只能根据经验来定义软件和硬件部分各自应完成的功能。对于整个系统的功能和行为,在设计最初阶段,描述时尚无硬件的概念,经过软硬件划分之后,将系统规范描述分成软件实现和硬件实
现两部分。虽然VHDL等语言也支持算法级描述,但是大部分硬件描述语言HDL(HardwareDescripTIonLanguage)如VHDL、Verilog等基本上还是面向硬件的描述,面向较低的硬件抽象等级。同时由于高级编程语言(C/C++/JAVA)不能描述硬件设计中的时间、延迟、信号等物理信息,与后续的硬件设计不兼容,硬件部分需重新用VHDL、Verilog等硬件描述语言来设计,造成大量的设计重复,也增加了系统设计的复杂度。
另外,许多要用硬件实现的功能,例如快速傅立叶变换FFT、扫描线算法、消隐算法等成熟而又常用的算法都有现成、完善的C语言描述,如果可以复用这些资源将节省大量的系统设计时间。
很多EDA工具只能理解HDL语言的描述,它是设计者和系统之间的界面,设计者通过HDL语言将自己的设计方案告诉EDA工具,在EDA工具的帮助下进行模拟、综合和验证。所以系统设计中用C语言的描述要转换为HDL语言才能被EDA工具接受。在众多HDL语言中,VHDL语言是被广泛使用的,因此设计和实现一个从C语言转换到VHDL语言的编译器具有重要意义和很大的实用价值。
C与VHDL的语言特征
C语言是目前国际上广泛流行的一种计算机高级语言,适合于作为系统描述语言,既可用来编写系统软件,也可用来编写应用软件。C语言是在B语言的基础上发展起来的,既保持了B语言的优点(精练,接近硬件),又克服了其缺点(过于简单,数据无类型等)。后来,C语言多次作了改进。1978年后,C语言已先后移植到大、中、小、微型机上,并独立于UNIX和PDP。
1983年,美国国家标准化协会(ANSI)对C语言的各种版本进行综合和扩充,制定了新的标准,称为ANSIC。总的说来,C语言适合描述过程和算法,它的运行环境是图灵机模型。它具有很多灵活的描述方式,具有较高的抽象能力,不区分函数和过程。数组的定义以及对指针的灵活应用大大方便了程序的书写,同时因其是为开发软件而设计的语言,因而更善于描述串行程序。但是由于其不能体现硬件设计中的时间、延迟、信号等物理特性,硬件模块部分需重新用硬件描述语言来设计,与后续设计缺乏连贯性,也增加了系统设计的复杂度。
VHDL(Very-High-SpeedIntegratedCircuitHardwareDe2scripTIonLanguage)语言是目前应用较广泛的一种硬件描述语言,被IEEE(TheInsTItuteofElectricalandElectricEngineers)和美国国防部确定为标准硬件描述语言,并得到了众多EDA公司的支持,在电子工程领域已成为事实上的通用硬件描述语言。VHDL既可以结构化的分层次的描述电路结构特性,也可以表示电路输入输出信号的关系特性,还可以描述和芯片布图有关的几何特性。它是一种较规整的语言,适合于描述并发程序。但是由于其最初目的并非是为电路设计的,而是用来描述电路的,因此它不适合进行系统级的软件设计和算法设计,特别是现在系统中越来越多的功能由软件来完成时。
设计方案
C语言和VHDL语言是两种面向不同领域,各有所长的语言,设计与实现一个C到VHDL的编译器即是把要用硬件来实现的C语言算法描述翻译成VHDL语言的行为描述。为了完成从C语言向VHDL的编译转换,首先用Lex和Yacc完成词法分析和语法分析。在语法分析的时候生成一棵C的语法树,,并在自下而上生成语法树的过程中收集综合属性。同时在此过程中进行语义分析———只分析和翻译与编译转换有关的信息,那些与C语言本身有关的语义则不做分析,比如是否有变量被重复定义等。在语法树的展开过程中向下传递继承属性并进行转化,将C的规约规则翻译为相应的VHDL规约规则。
图1C到VHDL的编译器实现过程
编译器的具体设计与实现过程见图1。在语法分析的过程中生成一棵语法树———多叉树,其叶子节点记录C程序中的单词,并记录单词的位置、属性、值等,非叶子节点记录C语言的规约规则以及要传递的属性———包括综合属性和继承属性。
由于C语言较灵活而VHDL语言较规整,因此这里只选择一定范围内的较常用的C语言语法子集进行转换;因为VHDL只有可综合子集可以实现,所以在转换时必须考虑可综合子集的限制;并且VHDL语言的数据类型有限,我们必须编写扩充数据类型的VHDL程序包,在展开语法树完成转换过程中用来描述复杂的逻辑。
转换过程
由于C语言善于描述串行程序而VHDL适合描述并发程序,因此对于C程序中的非main函数转化为VHDL中的函数(有返回值的)和过程(无返回值的);对于main函数,将main函数的参数作为enTIty的输入信号,将main的返回值作为entity
的输出信号,将main的函数体作为architecture的一个process。虽然VHDL通常描述并发程序,但其子程序和process仍是顺序执行的,与C语言的原始描述一致。具体函数对应情况见表1。
转换过程中,通过分析两种语言的差别,对于C语言的一些独特、灵活的描述方式———指针、类型转化、连等、i++和++i的处理、数组、逗号表达式等方面的正确翻译比较关键和重要。
对于C语言中的指针,要将它在C语言中的作用完全翻译到VHDL比较困难,因为C语言的指针实质上是与地址、与内存的分配有关。而VHDL作为一种描述硬件的语言,不存在地址的概念。因此在具体转换中将指针类型翻译为整数类型,并记录所指向数组的名字,整数值表示指向数组中的第几个元素。由于C的高维指针经过内存分配所得到,在VHDL中很难实现,因此初步实现一维指针,而带高维指针的C程序可以转换为一维指针来实现。
对于i++和++i,翻译i++时先记录哪些变量要经过这类操作,在完成对表达式的翻译后再处理。而翻译++i时因为变量值立刻变化,因此在翻译时必须将一个完整的表达式分开,并引入临时变量来处理。
相对于C语言中灵活的类型转化,VHDL则严格的多,不允许不同类型之间运算。由于C语言没有boolean类型,而VHDL语言有boolean类型,所以在条件表达式中要将整数或其它类型的数转换为boolean类型。同时,在处理C中整数的逻辑运算时,必须先将整数转换为VHDL的Bit-Vector来运算,计算后再转换回来。
另外,由于C语言不区分函数和过程,但是VHDL严格区分,而且函数只能出现在表达式中,因此对于没有出现在表达式中的函数调用,翻译时要将其放在一个临时表达式中,赋值给一个临时变量。
测试及分析
为了测试本文提出的设计方案的正确性和有效性,在设计过程中选取了一些常用的数字电路系统来比较C源程序和VHDL目标程序的功能一致性。例如对于一个无控制端口的加法器电路,其电路示意图见图2
该加法器不带任何控制端口,有两个输入端口in1和in2,一个输出端口pout,它们的类型皆为位向量。当输入信号中有任何一个或者两个都发生变化时,进程就要再重新执行一遍。从电路功能的角度来理解:只要在输入端有新的数据输入,那么加法器必然要重新开始工作,将新的数值相加并送到输出端口,这样不断地进行加法操作。对于加法器电路的C语言描述如下
利用本文提出的设计方案对实现加法器功能的C 语言程序进行编译转换, 得到转换后的目标程序———VHDL 程序如下:
通过分析编译转换后的目标程序的语法语义和功能证明转换方案是正确和有效的。由于用C 语言进行算法和程序设计,可以大大提高系统描述的层次和系统设计效率,并且有大量成熟、完善的用C 描述的算法可以复用,而VHDL 语言则是大多数EDA 工具所接受的硬件描述语言,因此设计与实现一个从C 语言转换到VHDL 语言的编译器具有重要意义和很大的实用价值。
本文分析了C 与VHDL 的语言特征及各自的优缺点,提出了合理有效的转换方案,指出从C 向VHDL 转换时需重点注意的几个方面,并对设计方案进行了测试分析,得到较满意的结果。