$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;既有真…

阶乘和

#include <stdio.h>// __int64的范围是 [0, 2^64),即0~18446744073709551615(约1800亿亿) static unsigned __int64 sum_fac(int n);int main(void) {printf("test sum_fac function.\n\n");for(unsigned int k0; k<20; k){printf("k%dth e sum is: %l…

未命名语句块中的声明

未命名语句块中的声明 命名块中的局部变量 Verilog允许在命名的begin…end或fork…join块中声明局部变量。局部变量声明的通常用法是声明一个临时变量进行循环控制。局部变量避免了对同名但用途不同的模块模块级变量的无意访问。下面的代码段声明了两个都叫i的变量&#xff0c…

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

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

kitl协议包简述

英文版参照网址http://blogs.msdn.com/ce_base/archive/2006/06/27/648747.aspx 下面是翻译过来的&#xff0c;可能有错哦&#xff0c;呵呵 KITL概述 KITL——Kernel Independent Transport Layer&#xff0c;CE驱动调试的基本调试协议。KITL提供 1、 传输初始化 2、 数…

敏捷转型中的看板

Scrumban最初是一种从Scrum向精益看板转换的机制&#xff0c;现在它已经支持双方向的转换&#xff0c;并可以应用到项目和精简BAU(常规商业运营)工作流。能够实施Scrum和精益方法的相互转换自然是很好的。但当你的客户不具备实践这些方法的条件时&#xff0c;你如何去帮助他们实…

GDIPlus灰度化图像

将RGB彩色图像转为8位的索引颜色 先定义一个宏 // Greyscale conversion #define GREY(r, g, b) (BYTE)(((WORD)r * 77 (WORD)g * 150 (WORD)b * 29) >> 8 //#define GREY(r, g, b) (BYTE)(((WORD)r * 169 (WORD)g * 256 (WORD)b * 87) >> 9)// Grayscale, 将…

SystemVerilog文本值和数据类型

SystemVerilog文本值和数据类型 1、增强的文本值赋值 给一个向量赋予文本值 在Veirlog语言中&#xff0c;一个向量可以很容易地赋值为全00、全x&#xff08;不确定&#xff09;或全z&#xff08;高阻态&#xff09;。 parameter SIZE 64; reg [SIZE-1 :0] data; data 0;//…

从IC设计来看Trace32的用途

通常的芯片设计&#xff0c;在开发阶段都会先在一个包含硬IP核的FPGA上进行&#xff0c;通过使用硬件描述语言HDL来对FPGA进行编程&#xff0c;这样既能加快设计速度又能够节省成本&#xff0c;最重要的是可以在芯片开发阶段发现可能存在的HW问题。一般的设计思路是首先将各个外…

使用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)…

对象类型和数据类型

对象类型和数据类型 Verilog数据类型 Verilog语言具有针对硬件的变量类型和线网类型。这些类型具有特定的仿真和综合语义&#xff0c;表示芯片或系统中的实际连接行为。 &#xff08;1&#xff09;Verilog的reg、integer和time变量的每一位都有四种逻辑&#xff1a;0、1、Z、X…

尺度空间(Scale space)理论

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

[转] Windows CE 6.0 启动过程分析

看到这么好的文章&#xff0c;小郭觉得不转载就是天理不容&#xff0c;转了&#xff01;&#xff01;&#xff01;&#xff01; *************************************************************************************** 在Windows CE 6.0中&#xff0c;内核&#xff08;Ke…

数据类型规则的放宽

数据类型规则的放宽 SystemVreilog放宽了使用变量的限制 SystemVreilog放宽了变量的使用规则&#xff0c;大大简化了模型中数据类型的使用。在SystemVreilog中共&#xff0c;任何数据类型的变量都可以通过下列方式赋值&#xff0c;但只能采用其中的一种方式。 &#xff08;1&a…

真实,让文学回到原点:关于非虚构写作的思考

任何一种文学主张&#xff0c;其实都是先有实践&#xff0c;而后再有理论和命名。“非虚构写作”也是如此。如果大胆猜想&#xff0c;“非虚构写作”可能要追溯到远古的口传心记和结绳记事。当时的人类记录下身边发生的事情&#xff0c;应该就是非虚构&#xff0c;而口头讲述的…

4位16色灰度图像处理

定义几个辅助的宏&#xff0c;如下。 // 拆分合并BYTE #define HIBITS(w) ((BYTE)((((BYTE)(w)) >> 4) & 0xf)) #define LOBITS(w) ((BYTE)(((BYTE)(w)) & 0xf)) #define MAKEBITS(a, b) ((BYTE)(((BYTE)(((BYTE)(a)) & 0xf)) | ((…

[转] 常见WinCE启动失败原因分析

*********************************************** 一般情况下&#xff0c;为设计中的IC开发SW方案&#xff0c;难免会碰到Bootloader/EBoot/OS启动失败的情况&#xff0c;对于Bootloader和EBoot&#xff0c;由于源代码很少&#xff0c;直接使用Trace32调试是最佳方法&#xff…

树莓派安装mariadb redis

安装软件 sudo apt install mariadb-server mariadb-client sudo apt install redis 二. 配置 1, mariadb 配置 配置远程访问 maridb configuration: sudo mysql_secure_installation # 设置root密码 vim.tiny mariadb.conf.d/50-server.cnf # 设置去除本地绑定 #bind-addre…

Google云服务降价,整合持续集成工具,支持Windows和托管虚拟机

本周二&#xff0c;Google举行了云平台的现场活动&#xff08;点击查看视频记录&#xff09;&#xff0c;展示了一系列新特性、改进和全新定价模型。\u0026#xD;\n定价\u0026#xD;\nGoogle认为&#xff0c;云计算价格应该跟随硬件领域的摩尔定律&#xff0c;而且在过去数年间硬件…