包与$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指令指定的单位和精度优先于外部声明,低于局部声明。

posted @   骑猪上树的少年  阅读(101)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
回到顶部
点击右上角即可分享
微信分享提示

目录导航