小舍YZ 发表于 2017-7-6 14:38:50

导入外部的HDL程序模块

ystem Generator的高级应用

导入外部的HDL程序模块

基于HDL的设计已经盛行了多年,现已积累了有大量的HDL代码资源和丰富的IP核,因此在各种FPGA设计中,不可避免地要导入一些HDL代码,以达到最优设计。System generator支持导入HDL设计,能以黑盒子(Black Box)的方式导入VHDL、Verilog HDL以及EDIF设计文件。在模型设计中,黑盒子模块和普通的System generator一样,能实现模块间的互相连接、参与仿真以及被编译成硬件电路。

1.黑盒子HDL代码的要求

黑盒子模块队导入的HDL代码格式有一定的限制,其具体要求如下:
•       HDL实体的名字不能和设计中已有的模块名字重复;
•        顶层黑盒子实体中不能出现双向端口;
•        对于Verilog黑盒子,其模块和端口名必须小写,且命名要规范;
•        HDL模块的时钟信号以及时钟使能信号都必须是标准逻辑类型,即不能使用矢量输入信号,如:
input clk1, clk2;是合法的
input clk; 是不合法的
•        黑盒子代码的时钟和时钟使能信号必须成对出现,即出现一个时钟信号,则必须有一个时钟使能信号。且时钟信号的名字中必须包含字符串clk,时钟使能信号的名字必须包含字符串ce,一对时钟信号和时钟使能信号的名字只能有clk和ce不同,如my_clk_1和my_ce_1。
2.黑盒子配置向导

System Generator提供了由HDL代码到黑盒子模块转化的可配置向导,用于简化整个流程。可配置向导首先检查VHDL、Verilog代码的语法检查,然后根据语义分析的结果将其转换成.m函数,最后再将.m函数和黑盒子模块关联起来。生成的可配置.m函数是否可用取决于导入的HDL代码的复杂度。将在5.5.1节给出说明,指出在哪些细节下,必须对其生成的代码进行手工修改以修正可配置向导的不足。

1) 启动可配置向导

当在设计中添加一个黑盒子模块时,配置向导会自动启动。注意:在添加黑盒子之前,要将导入的HDL文件放在设计模型的文件夹中。可配置向导只在设计文件.mdl所在的文件中寻找.v和.vhd文件,如果没有找到相关文件,则会弹出警告提示对话框,如图7-47所示。

图7-47 警告提示对话框

小舍YZ 发表于 2017-7-6 14:39:39

当找到.v或者.vhd文件后,可配置向导会弹出一个新的对话框,并列出所有HDL文件,如图7-48所示。然后选中要导入的文件,点击“Open”按钮即可完成整个流程。自动生成的.m文件的名字为 “<module>_config.m”,且存放在设计文件夹中。<module>就是导入的HDL文件的名字。

图7-48 列出的HDL文件

小舍YZ 发表于 2017-7-6 14:40:27

2) 可配置向导的一些细节

可配置向导在运行过程中会自动提取大量的信息,并执行相应的转换,但是有些细节必须通过手动修改才能完成,如表7-12所示。另外,可配置向导会在.m函数相应的地方添加注释以提示设计人员。

表7-12 向导细节描述列表

小舍YZ 发表于 2017-7-6 14:41:23

3.可配置.m函数

导入的HDL文件都是以黑盒子模块来描述的,因此原HDL文件所有的信息都通过可配置.m函数加载到黑盒子中。可配置.m函数不仅定义了接口、物理实现以及仿真行为等信息,还包括以下配置信息:顶层模块的实体名字、VHDL或Verilog语言选择标志、端口描述、模块的一般性需求、时钟和采样速率、和模块有关的所有文件信息以及模块中是否含有组合逻辑路径。

黑盒子和可配置.m函数的关联性在其属性对话框中设定,如图7-49所示。可配置.m函数采用面向对象的接口来说明黑盒子模块的信息,主要由模块描述符对象SysgenBlockDescriptor和端口描述符对象SysgenPortDescriptor这两个对象来完成。当System generator调用一个可配置.m函数时,就向相应的.m函数传递一个模块描述符:

function sample_block_config(this_block)

该模块描述符对象提供了说明黑盒子信息的方法,而相应的端口信息则由端口描述符对象独立定义。

图7-49 设定关联性的对话框

小舍YZ 发表于 2017-7-6 14:42:29

1) 设置顶层实体

配置向导会自动添加该属性的说明。SysgenBlockDescriptor对象提供的设计方法为setEntityName,其设置顶层实体的语法为:
this_block.setEntityName('foo');

2) 语言选择

黑盒子模块的SysgenBlockDescriptor对象提供了设置顶层模块语言类型的函数,该方法只能在可配置.m函数中调用一次,下面给出设置VHDL以及Verilog模块的语法。在操作中,向导会在.m函数自动添加相应的代码。

VHDL Module:
         tis_block.setTopLevelLanguage('VHDL');
Verilog Module:
         tis_block.setTopLevelLanguage('Verilog');

3) 端口定义

黑盒子模块的端口定义也是由可配置.m函数通过调用端口描述符来定义的,端口描述符提供了配置端口属性、位宽、数据类型以及采样速率的方法,主要的操作包括添加新的端口、获取端口对象、配置端口类型、设置端口采样率以及动态输出端口。

(1) 添加端口

在模型设计中,黑盒子输入、输出端口的添加由模块描述符对象的addSimulinkInport函数和addSimulinkOutport函数完成,其语法为:

添加输入端口:
          t is_block.addSimulinkInport('din');
添加输出端口:
          tis_block.addSimulinkOutport('dout');

其中的字符参数就是端口名字,必须小写,且要和导入的HDL模块中的名字一致,否则会出错。也可以通过调用setSimulinkPorts()函数来实现输入、输出端口的添加,该函数有两个输入参数,第一个参数是输入端口组成的胞元数组,第二个参数是由输出端口组成的胞元数组。
(2) 获取端口对象

定义了端口之后需要配置其属性,但是在配置属性之前必须先获得相应端口的描述符对象,然后才能对其进行操作。SysgenBlockDescriptor对象提供了port()函数来获取对象,其使用语法为:

din = this_block.port('din');

这便创建一个“din”的对象,再将其赋值给描述符变量。此外,还有两个函数inport()和outport()用来返回对象的端口下标,其类型为1到所有输入、输出端口总数之间的一个整数,方便了对模块端口的反复性操作。

(3) 配置端口类型

SysgenPortDescriptor提供了完备的端口类型的配置方法,如一个名为“dout”、位宽为12以及位置下标为8的无符号端口的定义语法为:
dout = this_block.port('dout');
dout.setWidth(12);
dout.setBinPt(8);
dout.makeUnsigned();
也可以通过下面的语句完成相同的功能:
dout = this_block.port('dout');
dout.setType('Ufix_12_8');
黑盒子支持具有单比特端口(如:std_logic)或向量端口(如:std_logic_vector(0 downto 0))的HDL代码,但对于二者的处理略有不同。System Generator默认端口为向量端口,因此当端口为单比特时,需要通过方法useHDLVector()来修改其默认配置,当其参数为真时,意味着向量端口;否则为单比特端口,其语法为:
dout.useHDLVector(true); % std_logic_vector
dout.useHDLVector(true); % std_logic
(4) 设置端口采样率

可以通过黑盒子设置不同的采样速率,在默认情况下,输出端口的采样速率和输入端口是一样的,但在多速率系统中,输出端口的速率和输入端口的速率是不一样的,另外在通常情况下,各个输入端口的速率也是不一样的,这就需要为各个端口独立设置采样率。SysgenPortDescriptor类提供了setrate()的方法,用于独立设置端口速率,其语法为:

dout.setRate(N);

其中,N为正整数,意味着采样周期包含N个系统周期,也就是说其采样速率为系统时钟的1/N。如果系统周期为2s,则dout.setRate(3);就表示采样周期为 。如果端口的采样频率不是一个常数,是变化的,可通过SysgenPortDescriptor类的setConstant()方法来实现。

(5) 动态输出端口

黑盒子最有用的一个特征就是输出端口的类型和采样速率可以动态配置。例如,根据输入端口的位宽来动态调整输出端口位宽就是实际工程中所需要的。SysgenPortDescriptor提供了设定端口动态可配置的成员变量,通过监测输入端口动态修改成员变量来达到目的。 首先,通过.port()函数获得输入端口的位宽和速率:
input_width = this_block.port('din').width;
input_rate = this_block.port('din').rate;
其次,SysgenBlockDescriptor对象提供了布尔型成员变量inputTypesKnown和inputRatesKnown,来判断端口类型和位宽配置信息是否被传递到模块。

最后,在成员变量inputTypesKnown和inputRatesKnown的判断条件语句中嵌套对输出端口的配置来达到动态输出端口的目的。动态设置输入端口位宽的语句如下:
if (this_block.inputTypesKnown)
       dout.setWidth(this_block.port('din').width);
end
动态设置输入端口采样速率的语句与上类似,其语法为:
if (this_block.inputRatesKnown)
      dout.setRate(this_block.port('din').rate*2);
end
4) 黑盒子时钟

对于导入的多速率代码,必须在可配置.m函数中对系统时钟进行相应说明。无论是单速率系统和多速率系统,System Generator要求时钟和时钟使能信号必须成对出现。SysgenBlockDescriptor对象提供了.addClkCEPair()函数,用于定义黑盒子的时钟和时钟使能信号。该函数有3个参数,第1个参数是HDL代码中的时钟信号名字,第2个参数是HDL代码中的时钟使能信号,第3个参数定义时钟信号和时钟使能信号之间的速率关系。其中时钟端口信号必须包含字符串“clk”,时钟使能信号必须包含字符串“ce”,除了“clk”和“ce”外,二者其余部分必须相同。速率参数不是Simulnk模块的采样速率(?????),它为一正整数,代表了系统时钟速率和相应的时钟使能速率的比值。

例如,假设系统时钟使能信号为ce_3,时钟信号为clk_3,且ce_3的周期是clk_3周期的3倍,则可以通过下面的语句完成说明:
addClkCEPair('clk_3','ce_3',3);
当System Generator将黑盒子编译成硬件电路时,能根据.m函数生成合适的时钟有效信号,并自动将其连到相应的驱动端口上。

5) 模块中是否含有组合逻辑路径

由于输入端口的任何改变都会导致无时钟驱动的输出端口发生变化,因此如果导入的模型含有组合路径,则必须通过tagAsCombinationa方法在.m函数中进行说明,其语法为:
this_block.tagAsCombinational;
页: [1]
查看完整版本: 导入外部的HDL程序模块