$unit编译单元声明

$unit编译单元声明

SystemVerilog含有编译单元。
相比Verilog,SystemVerilog增加了编译单元的概念。编译单元是同时编译的所有源文件。编译单元为软件工具提供了一种对整个设计子块单独编译的方法。一个子块可能包含第一个或多个模块(module)。这下模块可能包含在一个或多个文件中。设计的子块可能还包含接口块和测试程序块。
编译单元域包含外部声明。
SystemVerilog允许在包、模块、接口和程序块的外部进行声明扩展Verilog的声明域。这些外部声明在“编译单元域”中,并且对所有同时编译的模块都是可见的。
编译单元域可以包含:
(1)时间单元和精度声明
(2)变量声明
(3)net声明
(4)常量声明
(5)用户定义数据类型,使用typedef、enum、或class
(6)任务和函数定义

编译单元域中的外部声明(不可综合)

///外部声明/
parameter VERSION = "1.2a";   //外部常量
reg  resetN = 1;  //外部变量(低有效)
typedef struct packes{  //外部用户定义类型reg [31:0] address;reg [31:0] data;reg [31:0] opcode;
}instruction_word_t;function automatic int log2 (input int n);//外部函数if (n <= 1) return (1);log2 = 0;while( n > 1)beginn = n/2;log2++;endreturn(log2);
endfunction/模块定义
//用外部声明定义端口类型
module register(output instruction_word_t q,input instruction_word_t d,input wire clock
);always @(posedge clock ,negedge resetN)if(!resetN)  q <= 0;//使用外部复位else            q <= d;
endmodule
注意:外部编译单元域声明不是全局的

编译单元域中的声明与全局声明不一样。真正的全局声明,如全局变量或函数,不管源文件是单独还是同时编译,都会被设计的所有模块共享。
SystemVerilog的编译单元域只作用于同时编译的源文件。每次编译源文件,就创建一个唯一仅针对此次编译的编译单元域。例如,如果模块CPU和模块controller都引用外部声明的变量regset,那么就可能存才两种假设:
(1)如果两个模块同时编译,将只要一个编译单元域。外部声明的reset变量将被这两个模块共用。
(2)如果两个模块分别编译,将会有两个编译单元域,可能有两个不同的reset变量。
在后一种假设下,包含外部reset声明的编译看上去没有问题。另一个文件在单独编译时会有自己唯一的$unit编译域,不会看到前一个编译中的reset声明。取决于reset使用的环境,第二个编译可能会由于未声明变量而失败,也可能使reset成为隐式net而编译成功。这种可能性是很危险的。如果第二个编译通过使reset成为隐式net而成功,那么现在就会有两个叫做reset的信号,每个编译中一个。这两个不同的reset信号用什么方式都不能连在一起.

$unit只能用于导入包
(1)不要在 $unit空间进行任何声明!所有的声明都要在命名包内进行。
(2)必要时可以将包导入到 $unit中。这在模块或接口的多个端口使用用户自定义类型,而这个类型定义又在包中时非常有用。
在 $unit编译单元域中直接声明对象会在文件单独编译时导致设计出错。如果声明分散在多个文件中,还会产生spaghetti代码,难以维护、重用或调试声明错位。(spaghetti代码指结构混乱、逻辑性差、难于调试的代码)

SystemVerilog标识符搜索规则
编译单元域中的声明可以在组成编译单元的模块的任何层次引用。
SystemVerilog定义了简单的搜索规则来引用标识符:
(1)搜索那些按IEEE 1364Verilog标准定义的局部声明
(2)搜索统配符导入到当前作用域的包中的声明
(3)搜索编译单元域中是声明
(4)搜索设计层次中的声明,遵循IEEE1364Verilog搜索规则

注意:数据标识符和类型标识符必须在引用前声明
未声明的标识符隐为net类型
外部声明必须在使用前定义

编译单元域中的变量和net
当使用外部声明时有一点需要着重考虑。Verilog支持隐式声明,即在特定环境下,为声明的标识符假定为net类型(通常为wire类型)。当从上下文不能推断出隐式类型或者希望使用默认net类型以外的类型时,Verilog要求在标识符引用之前要显式声明标识符类型。
隐式类型声明规则影响编译单元域中的变量和net声明。软件工具必须在标识符引用之前找到外部声明。否则,这个名称将被看做未声明的标识符并遵循Verilog隐式类型规则。

module parity_gen(input wire [63:0] data);assign parity = ^data;  //parity是一个隐式局部net
endmodulereg parity;//因为声明在被parity_gen引用之后出现,因此外部声明没被模块parity_gen使用module parity_check(input wire [63:0] dataoutput logic err);assign err = (^data != parity);//parity是$unit变量
endmodule

将包导入$unit的编码原则
SystemVerilog允许将模块端口声明为用户定义类型。

module ALU
(	input definitions::instruction_t IW,input logic clock,output logic[31:0]  result
);

当许多模块端口都是用户自定义类型时,像上面那样显式地引用包中就会显得繁琐了。一种可选择的风格是在模块声明之前将包导入到$unit编译单元域中。

//将包中特定子项导入到$unit中
import definitions::instruction_t;module ALU
(	input definitions::instruction_t IW,input logic clock,output logic[31:0]  result
);

包还可以通过通配符导入到$unit域中。注意通配符导入实际上不能导入包中所有子项。它只是将包加到SystemVerilog源路径中。

//将包中特定子项导入到$unit中
import definitions::*;module ALU
(	input definitions::instruction_t IW,input logic clock,output logic[31:0]  result
);

使用单独编译将包导入到$unit中

文件顺序编译依赖性
当子项从包中导入(包中特定子项导入或者是通配符导入)时,import语句必须出现在包中子项被引用之前。如果包导入语句与模块或接口不在同一文件中,而模块和接口文件又要引用包中子项,那么包含import文件必须在文件比编译顺序中首先列出来。如果文件顺序不正确,模块或接口的编译要么失败,要么因看不到包中子项而错误地指定为隐式net。

多文件编译与单文件编译
可以读入Verilog和SystemVerilog源代码的综合编译器、代码检测器、一些仿真器和其他可能的工具通常可以一次编译一个或多个文件。当多个文件同时进行编译时,只要一个$unit域。包导入(不管是包中特定子项导入或者是通配符导入)到 $unit域中使包中子项对导入语之后读入的所有模块和接口都可见。但是,如果这些文件单独编译,将会产生多个不同的 $unit编译单元。一个 $unit中导入的包对另一个 $unit是不可见的。

在每个文件中使用导入语句
对于将包中子项导入到 $unit编译单元域中出现的这两个问题,解决办法就是将import语句放到每个文件模块或接口定义之前。这个解决方法在每个文件单独编译时很奏效。但是,当多个文件同时进行编译时,还要当心。将同样的包中子项多次导入到同一 $unit域中是非法的。(这与在同一名称空间中两次声明同一变量一样是非法的)

用 $unit包导入的条件编译
可以使用C语言常用的编程技巧,使我们在单个文件编译和多个文件编译时都可以将包中子项导入到 $unit域中。这个技巧是利用条件编译,使第一次遇到导入语句时将其编译到 $unit中,而再次出现则不编译这些语句。为了说明导入语句在当前 $unit域中是否已经编译完,在导入语句第一次编译时设置`define标志。

带条件编译的包

`ifndef  DFFS_DONE  //如果已编译标志没设置`define DFFS_DONE  //设置该标志package definitions;paramter VERSION = "1.1";typedef enum{ADD,SUB,MUL} opcodes_t;typedef struct{logic [31:0] a,b;opcodes_t opcode;}instruction_t;function automatic [31:0] multiplier(input [31:0] a,b);//用户定义的32位乘法return a*b;  //抽象乘法(无错误检测)endfunction
endpackage
import  definitions::*; //将包导入到 $unit中`endif

每个需要包中定义的设计或测试平台都有应该将

`include "definitions.pkg"

放在文件的开始。当设计或测试平台文件被编译时,都会将包和导入语包含进去。definitions.pkg文件中的条件编译将保证如果包还没被编译和导入,就去完成这两个任务。如果包已经编译并导入到当前 $unit域中,该文件的编译将被忽略。

注意:对于这种编码风格,包文件应该用`include编译命令间接传递给软件工具编译器。

这种条件编译风格使用Verilog的`include命令把definitions.pkg文件当作其他文件的一部分进行编译。这样做时为了保证definitions.pkg文件末尾的导入语将包导入到设计或测试文件,编译正在使用的同一 $unit域中。如果definitions.pkg文件直接出现在软件工具编译器的命令行中,包和导入语句就会被编译到另一个 $unit空间,而不是设计或测试平台块正在使用 $unit域中。

//包含条件编译包文件的设计文件
`include "definitions.pkg"  //编译包文件module ALU
(	input definitions::instruction_t IW,input logic clock,output logic[31:0]  result
);
always_ff @(posedge clock)
begincase(IW.opcode)definitions::ADD  : result = IW.a + IW.b;definitions::SUB  : result = IW.a - IW.b;definitions::MUL  : result = definitions::multiplier(IW.a,IW.b);endcase
end
endmodule
//包含条件编译包文件的测试平台文件
`include "definitions.pkg"  //编译包文件module test;instruction_t test_word;logic [31:0] alu_out;logic  clock = 0;ALU dut (.IW(test_word),.clock(clock ),. result(alu_out));always #10 clock = ~clock;initial
begin@(posedge clock)test_word.a = 5;test_word.b =7;test_word.opcode = ADD;@(negedge clock)$display ("alu_out = %d (expected 12)", alu_out);$finish;
end
endmodule

`include对单文件和多文件编译
进行单文件编译时,包将被编译并导入到每个 $unit编译单元中。这就保证了每个 $unit都能看到相同的包中子项。由于每个 $unit都是唯一的,不会在多次编译包的过程中出现名称冲突。
进行多文件编译时,条件保证包只进行一次编译并导入到所有模块的公共 $unit编译域中。不管设计或测试平台文件那个先编译,都会导入包,保证包中子项对所有文件都是可见的

包中变量是共享变量(不可综合)
包中可以包含变量声明。包中变量为所有导入变量的设计块(和测试块)共享。包中变量的行为在单文件编译和多文件编译中截然不同。在多文件编译中,包被导入到同一 $unit编译域中。每个设计块或测试块将看到相同的包中变量。一个块写到包中变量的值将对其他所有块可见。在单文件编译中,每个 $unit域都有一个唯一的变量,它恰好与另一个不同的 $unit域中的变量同名。一个设计块或测试块对包中变量写入的值对其他设计或测试块不可见。

包中的静态任务和函数是不可综合
静态任务和函数或者含静态储存的自动任务和函数,也具有同样的潜在问题。在多文件编译中,只有一个 $unit域,它将导入任务和函数的一个实例。任务或函数中的静态储存对所有设计和验证块都是可见的。在单文件编译中,每一个独立的 $unit导入的任务或函数实例不同。任务或函数的静态储存不会在设计和测试块中共享。
这个关于条件编译导入语句到 $unit中的限制在可综合的模型中没有问题,因为综合不支持包中的变量声明、静态任务和函数。

使用包而不用 $unit是更好的编码风格
可在编译单元域(所有模块和接口定义的外部)中声明的可综合结构有
(1)typedef用户定义类型定义
(2)自动函数
(3)自动任务
(4)parameter和localparam常量
(5)包导入
虽然在编译单元域定义用户定义类型不是一种好的风格,但它可综合的。更好的风格是吧用户定义类型的定义放在有名称的包中,这可以降低出现spaghetti代码和文件顺序依懒性的风险。

外部任务和函数必须是自动的
在 $unit编译单元域中声明任务和函数也不是一种好的编码风格。但是,在 $unit中定义的任务和函数是可综合的。当模块引用编译单元域中定义的任务和函数时,综合将复制该任务或函数代码并把它看成在模块中定义的一样。为了综合,编译单元域中定义的任务和函数必须声明为automatic,并且不能包含静态变量。这还是因为自动任何和函数的储存区在每次调用时才会实际分配。因此,每个模块引用的自动任务或函数的引用的综合前仿真行为与综合后行为相同(综合后任务或函数的功能已经在模块内实现了)。
编译单元域中定义的parameter常量不能重新定义,因为它不是模块实例的一部分。综合会将编译单元域中声明的常量看作文本值。在 $unit域中声明参数不是一种好的建模风格,因为常量声明文件与模板文件分开编译时,这些常量对模块是不可见的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/243336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[学习] FPGA之基本原理(可能理解不对)

>> 什么是fpga FPGA是英文Field Programmable Gate Array的缩写&#xff0c;即现场可编程门阵列&#xff0c;它是在PAL、GAL、EPLD等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中 的一种半定制电路而出现的&#xff0c;既解决了定制电路的不足…

忧云:喻红艺术展观后

长征空间。喻红的个展《忧云 wondering clouds》&#xff0c;中文标题似过诗意&#xff0c;而英文可能更准确表达其意图。这幅连体大画至少有15米长&#xff0c;非常壮观&#xff0c;色彩变化&#xff0c;人物的形态&#xff0c;复杂而有序。既有写实也有表现&#xff0c;既有真…

故乡的路:十位少数民族摄影师联展

故乡的路&#xff1a;10位少数民族摄影师联展。映艺术中心。参展的有蒙古族、维吾尔族、回族、纳西族、傣族、白族、彝族、拉祜族、藏族等。民族是一个视点&#xff0c;故乡也是一个视点&#xff0c;两者的交叉&#xff0c;透过现代化的相机和镜头&#xff0c;获得了一种独特的…

使用GDI+保存图像为8bpp的灰度图像

使用GDI保存图像为8bpp的灰度图像&#xff0c;GDI真的有些特殊。。。。。 // Greyscale conversion #define GREY(r, g, b) (BYTE)(((WORD)r * 77 (WORD)g * 150 (WORD)b * 29) >> 8) // .299R .587G .114B //#define GREY(r, g, b) (BYTE)(((WORD)r * 169 (WORD)…

尺度空间(Scale space)理论

尺度空间方法的基本思想是&#xff1a;在视觉信息处理模型中引入一个被视为尺度的参数&#xff0c;通过连续变化尺度参数获得不同尺度下的视觉处理信息&#xff0c;然后综合这些信息以深入地挖掘图像的本质特征。尺度空间方法将传统的单尺度视觉信息处理技术纳入尺度不断变化的…

图像拉普拉斯金字塔融合(Laplacian Pyramid Blending)

转摘的&#xff0c;修改了下程序&#xff0c;图像融合看不太懂 。。。。http://blog.csdn.net/abcjennifer/article/details/7628655#comments // 转摘的别人的程序 // #include <stdio.h> #include <cv.h> #include <cxcore.h> #include <highgui.h>…

ASA 9.21 in Vmware Workstation 10

There is old post “ASA 8.02 in Vmware Workstation “ in this blog posted on Dec 2011. Anothe post “How to Make your own ASA 8.42 in VMware”. Here are all related posts in this blog: ASA 8.02 in Vmware WorkstationASA 8.42 in VMware WorkstationASA 9.21 i…

状态机在VHDL中的实现

状态机在VHDL中的实现 1、Moore状态机的VHDL描述 输出仅取决于所处的状态 LIBRARY IEEE; --库、程序包的说明调用 USE IEEE.STD_LOGIC_1164.ALL;ENTITY Moore IS PORT (RESET,CLOCK,DIN : IN STD_LOGIC;DOUT : OUT STD_LOGIC_VECTOR(2 DOWNTO 0) ); END;ARCHITECTURE Mo…

VHDL仿真

VHDL仿真 仿真(Simulation也称模拟),不接触具体的硬件系统利用计算机对电路设计的逻辑行为和运行功能进行模拟检测,较大规模的VHDL系统设计的最后完成必须经历多层次的仿真测试过程,包括针对系统的VHDL行为仿真、分模块的时序仿真和硬件仿真,直至最后系统级的硬件仿真测…

关于结构体的内容

关于结构体的内容 结构体使用类似于C语言的语法来定义 结构体使用struct关键字声明。结构体内的成员可以是任何数据类型&#xff0c;包括用户自定义类型和其他的结构体类型。 struct{int a,b; //32位变量opcode_t opcode;//用户定义类型logic [23:0] adress;//24位变量bit er…

Pushing Policy Failed because Checkpoint Firewall “Load on module failed – no memory”

One day when pushing firewall policy from Checkpoint management server to UTM 272 cluster gateways, it failed and I got error message “Load on module failed – no memory” on one of cluster members. “Network Security Policy ‘Montreal_DMZ’ was prepared …

Point-BERT:一种基于Transformer架构的点云深度网络

目录 1. 前言 2. Point Tokenization 3. Transformer Backbone 4. Masked Point Modeling 5. Experiments Reference 1. 前言 从PointNet [1] 开始&#xff0c;点云深度网络逐渐成为解决点云特征提取与语义分析的主要研究方向。尤其在OpenAI的GPT模型获得了突破性成果后&#…

GNS3 VoIP Lab (Cisco 3725 and CME 4.3)

Here is a simple VoIP Lab in GNS3 environment. It is only used for my lab test and recorded here for future reference. 1. Topology: GNS3 Topology:Logic Topology:xp(192.168.2.60)——–C3725 Router(192.168.2.10) 2. Enviroment: ESXi 5.5 (or Vmware Workstation…

关于数组的内容

关于数组的内容 Verilog数组声明的基本语法 <data_type><vector_size><array_name><array_dimension> 例如&#xff1a; reg[15:0] RAM [0:4095];//储存器数组SystemVerilog允许任何数据类型的非压缩数组 SystemVerilog将非压缩数组的声明进行了扩展…

BreadCrumb控件

BreadCrumb控件&#xff0c;如上图所示&#xff0c;即面包屑导航控件&#xff0c;类似于TreeCtrl&#xff0c;但不是一次显示所有的Item&#xff0c;VC 2010可以编译通过&#xff0c;稍微修改一下其他的也可以编译&#xff0c;源代码下载&#xff1a; http://download.csdn.net…

Android简介

最近Android很火&#xff0c;小弟也想了解一下它的结构。跟CE或者Mobile比起来&#xff0c;它的结构是有点凌乱&#xff0c;也难怪&#xff0c;毕竟是基于别人的内核在上层开发了一些应用 ---------------------------------------------------------------------------------…

说不尽的刘恒

认识刘恒快三十年了&#xff0c;作为曾经的同事和他小说的责任编辑&#xff0c;我只写过他一篇文章&#xff0c;还是在二十多年前。有时候特别熟悉的人反而不知道从何写起&#xff0c;因为一想起往事&#xff0c;各种记忆像开闸的水一样涌满眼前&#xff0c;让人很难落笔。1985…

外行看Flash的存储原理

突然在网上看到别人两年前写的一篇关于nor和nand的好文章&#xff0c;做为csdn的合法公民&#xff0c;有必要转 一、存储数据的原理 两种闪存都是用三端器件作为存储单元&#xff0c;分别为源极、漏极和栅极&#xff0c;与场效应管的工作原理相同&#xff0c;主要是利用电场的…

快速计算整数的二进制表示法中1的个数

快速计算整数的二进制表示法中1的个数 题目&#xff1a;给定一个无符号32位整数x&#xff0c;求x的二进制表示法中含1的个数&#xff1f; 第一种算法&#xff1a; int OneCount(unsigned int x){ for(int count0; x>0; count) x&x-1;//把最后面的1变0 return …

在C/C++代码中使用SSE等指令集的指令(1)介绍

http://blog.csdn.net/gengshenghong/article/details/7007100我们知道&#xff0c;在C/C代码中&#xff0c;可以插入汇编代码提高性能。现在的指令集有了很多的高级指令&#xff0c;如果我们希望使用这些高级指令来实现一些高效的算法&#xff0c;就可以在代码中嵌入汇编&…