您当前的位置: 首页 > 

lu-ming.xyz

暂无认证

  • 0浏览

    0关注

    115博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【SystemVerilog学习笔记】2-SystemVerilog 声明的位置

lu-ming.xyz 发布时间:2021-04-20 18:36:53 ,浏览量:0

目录
  • 2.1 包 Package
    • 2.1.1 Package的定义
    • 2.1.2 Package的引用
    • 2.1.3 synthesis指导
  • 2.2 $unit 编译单元声明
    • 2.2.1 编码建议
    • 2.2.2 SystemVerilog标识符搜索优先级
    • 2.2.3 源代码顺序
    • 2.2.4 将package导入$unit的编码原则
    • 2.2.5 综合指导
  • 2.3 未命名语句块中的声明
  • 2.4 仿真时间和精度
SystemVerilog:

  • 拓展了Verilog的声明空间
  • 增强了定义仿真时间单位的能力
2.1 包 Package

 Verilog要求局部声明,但是SystemVerilog中的typedef的用户类型希望在多个模块使用。

2.1.1 Package的定义

 功能:主要是为了使多个模块共享 typedef 定义的用户类型。  格式:

package PACKAGE_NAME
	//可综合的结构
	//1 parameter、localparam
	//2 const
	//3 typedef
	//4 task  function
	//5 import
	//6 操作符定义重载
	//不可综合的结构
	//全局变量声明、静态task、静态function
endpackage

 按照上面的格式定义一个名为definitions的package:

//example_2_3
package definitions;
	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);
​    return a * b;
endfunction
endpackage

 注意:package中的parameter不能重新定义。因为它不是模块实例的一部分。

2.1.2 Package的引用

 方法:以引用example_2_3中的package definitions为例。

  1. 作用域解析操作符“::”直接引用
module ALU (
  	input definitions::instruction_t I_IW,
  	input logic clock,
  	output logic [31:0] result
);
always_ff @( posedge clock ) 
begin
  	case (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);
​    default: ;
  	endcase
end
endmodule
  1. 将特定子项导入
module ALU (
  	input definitions::instruction_t I_IW,
  	input logic clock,
  	output logic [31:0] result
);
import definitions::ADD;
import definitions::SUB;
import definitions::MUL;
import definitions::multiplier;
always_ff @( posedge clock ) 
begin
  	case (IW.opcode)
​    	ADD : result = IW.a + IW.b;
​    	SUB : result = IW.a - IW.b;
​    	MUL : result = definitions::multiplier(IW.a, IW.b);
​    default: ;
  	endcase
end
endmodule

 注意:只导入枚举类型的定义(opcodes_t)并不会导入该定义使用的元素(ADD、SUB与MUL)。

  1. 用通配符将特定子项导入
module ALU (
  	input definitions::instruction_t I_IW,
  	input logic clock,
  	output logic [31:0] result
);
import definitions::*;
always_ff @( posedge clock ) 
begin
  	case (IW.opcode)
​    	ADD : result = IW.a + IW.b;
​    	SUB : result = IW.a - IW.b;
​    	MUL : result = definitions::multiplier(IW.a, IW.b);
​    default: ;
  	endcase
end
endmodule

 注意:使用通配符(*)时,只有实际使用的子项(ADD、SUB与MUL)才会被真正导入。

  1. 将子项导入$unit声明域中
2.1.3 synthesis指导
  • 为了能够综合,包中定义的task和function必须声明为 automatic ,并且不能包好static变量。
  • 综合不支持包中的变量声明。  说明:自动任务和函数每次调用时才会分配独立的副本,其他如变量等则为所有模块共享,这种不通过端口传递数据的模块间通信是不可综合的。
2.2 $unit 编译单元声明

 编译单元(unit):同时编译的所有文件。  编译单元域($unit 域):编译单元在package、module、接口和程序块的外部的声明域。  编译单元域可以包含:

  1. 时间单位和精度声明
  2. 变量声明
  3. net声明
  4. 常量声明
  5. 用户定义类型数据声明
  6. 任务和函数定义  注意:$unit域的声明不是全局的。全局声明无论源文件单独还是同时编译,都会被所有模块共享;$unit域的声明只作用于同时编译的源文件.
2.2.1 编码建议
  1. 不要再$unit中进行任何声明,而应在package内。
  2. 必要时可以将package导入到$unit中。
2.2.2 SystemVerilog标识符搜索优先级
  1. Verilog标准定义的局部声明。
  2. 通配符导入的包中的声明。
  3. $unit中的声明。
  4. 设计层次中的声明。
2.2.3 源代码顺序

 注意:数据标识符和类型标识符必须在引用前声明,否则为声明的标识符将被隐式声明为net类型(通常为wire)。

2.2.4 将package导入$unit的编码原则

 可在模块声明之前将包导入到$unit域中,比如“2.1.2 Package的引用”中import语句位置换到module外。  注意:

  • 按照搜索优先级,import语句必须出现在包中子项被引用之前。
  • 多个文件同时编译只有一个 u n i t 域 , 多 个 文 件 单 独 编 译 有 多 个 不 同 的 unit域,多个文件单独编译有多个不同的 unit域,多个文件单独编译有多个不同的unit域,导入的包对其他$unit域不可见。
  • 将同样的包导入同一$unit域是非法,在包中利用条件编译避免重复导入。包文件用`include编译命令间接传递。
`ifndef DFFS_DONE
  	`define DFFS_DONE
package definitions;
  	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);
​    	return a * b;
  	endfunction
endpackage
import definitions::*;
`endif

 design file:xxx.v

`include "definitions.pkg"

 注意:包中的变量被所有导入变量的设计块或测试块共享。包中的变量、静态任务和函数都不可综合。

2.2.5 综合指导

 编译单元域中声明的可综合结构:

  1. typedef用户定义类型
  2. automatic function
  3. automatic task
  4. parameter、localparam常量
  5. package导入  注意:最好不要在$unit声明任务、函数和参数,当分开编译时,这些内容对模块不可见。  说明:自动任务和函数的存储区再每次调用时才会实际分配,存储区独立才能保证综合前仿真行为和综合后行为相同。
2.3 未命名语句块中的声明

 verilog允许在命名的begin…end或fork…join块中声明局部变量,并且可以用包含块名的层次路径引用局部变量。  SystemVerilog还允许在未命名块中声明局部变量,由于没有层次路径,局部变量不能在局部范围以外的任何地方引用。

2.4 仿真时间和精度

 与verilog一样,在遇到`timescale后,指定的时间单位和精度一直保持有效到下一条`timescale语句。  SystemVerilog可以直接给时间值指定时间单位:

forever #5ns clock = ~clock;

 注意:时间值和时间单位之间不允许有空格。  SystemVerilog增加关键字timeunit和timeprecision使时间单位和精度作为模块定义的一部分。

module chip (
...
);
 timeunit 1ns;
 timeprecision 10ps;
 ... 
endmodule

 说明:timeunit和timeprecision可以在$unit声明,但是必须先于其他任何声明。  时间单位和精度搜索优先级:

  1. 时间值自带的单位。
  2. 模块、接口和程序块内部指定的时间单位和精度。
  3. 父级模块或者接口的时间精度和单位。
  4. 模块编译时有效的`timescale定义的时间单位和精度。
  5. $unit中定义的时间单位和精度。
  6. 仿真器默认的时间单位和精度。
关注
打赏
1655639048
查看更多评论
立即登录/注册

微信扫码登录

0.0366s