包与$unit
包的使用
package definitions;
parameter 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) ;
//TODO
return a*b;
endfunction
endpackage
module ALU(
input definitions:instruction_t 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 = defitions:: multiplier(IW.a,IW.b) ;
endcase
end
endmodule
module ALU(
input definitions:instruction_t IW ,
input logic clock ,
output logic [31:0] result
);
import definitions::ADD ;
import definitions::SUB ;
import definitions::MUL ;
import definitions:multiplier ;
//import definitions:: * ;
always_comb begin
case(IW.opcode)
ADD: result = IW.a + IW.b ;
SUB: result = IW.a - IW.b ;
MUL: result = multiplier(IW.a,IW.b) ;
endcase
end
endmodule
通过import definitions::*可实现通配符导入,只有实际使用的子项才会被真正导入。
另外always_ff是告诉工具要实现一个触发器,需要添加敏感列表。always_comb是告诉工具实现一个组合逻辑,不需要敏感列表,即使条件不完备,工具也会进行优化,防止出现latch。always_latch是告诉工具实现锁存器,不需要敏感列表。
包中定义的task与function必须声明为automatic,且不能包含静态变量。因为只有这样才能保证每次调用时分配存储区。如果声明为静态的,不同模块访问同一变量就会造成冲突。
外部编译单元
以下代码不可综合
/*************************** outside define **************************/
parameter VERSION = "1.2a" ;//外部常量
reg resetN = 1;//外部变量
typedef struct packed { //外部用户定义类型
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) begin
n = n/2 ;
log2 ++ ;
end
return(log2)
endfunction
/************************** module define ****************************/
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
SV的编译单元域只作用于同时编译的源文件。每次编译,创建一次编译单元域。如果分两次编译,那么就会存在两个编译单元域。
编码指导
不要在编译单元$unit空间进行任何声明,所有声明放入命名包内。
必要时可以将包导入$unit.
时间精度
systemverilog允许直接带时间单位,而不必使用`timesclae
forever #5ns clock = ~clock ;
timeunit/timeprecision
指定模块内的时间单位和精度信息
module chip(****);
timeunit 1ns;
timeprecision 10ps;
……
endmodule
局部声明优先于外部声明
timeunit 1ns ;//外部声明时间单位和精度
timeprecision 1ns ;
module my_chip(***);
timeprecision 1ps ;//局部声明精度
forever #2.5 clock = ~clock;//使用外部时间单位和局域精度
forever #2.5ns clk= ~clk ; //使用指定的单位
endmodule
`timescale指令指定的单位和精度优先于外部声明,低于局部声明。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】