【路科V0】systemVerilog基础2——自定义类型

news/2024/5/19 17:56:54 标签: 数字验证, systemVerilog

自定义类型 

通过用户自定义类型,以往Verilog的代码将可以通过更少的代码来表示更多的功能。
用户自定义类型使得代码的可读性更好。

自定义类型的方法:

  • 通过typedef来创建用户自定义类型。
  • 通过enum来创建枚举类型。
  • 通过struct来创建结构体类型。

typedef 

        Verilog语言无法提供方便的特性来使得用户扩展变量和线网类型。
        SV则提供了特性使得用户可以构建更高抽象层的数据类型。

       用户可以利用已有的数据类型来定义新的数据类型,一旦定义了新的数据类型,则可利用该类型声明变量。( 就同C语言一样)

typedef int unsigned uint;
...
uint a , b; //uint声明的2个变量

        为了使代码更易读和维护,通常我们都习惯添加“_t”的后缀用来表示它是一个自定义类型(type) 。

enum

        枚举类型(enum)可以描述变量的合法值范围,其每一个值都需要提供一个用户自定义的名字。

//举例:枚举类型RGB可以拥有red、 green和blue的三个数值:
enum { red ,green ,blue } RGB;

        Verilog语言不支持枚举类型,因此为了提供类似于枚举类型设计方式,我们不得不采用参数来表示可取的值范围,或者使用宏来定义各个合法值的宏名称。

举例说明枚举类型的便利:

Verilog代码 

`define FETCH 3 'h0
`define WRITE 3 'h1
`define ADD 3 'h2
`define SUB 3 'h3
`define MULT 3'h4
`define DRV 3 'h5
`define SHIET3 'h6
`define NOP 3 'h7
module controller (
output reg read, write ,
input wire [2:0]instruction ,
input wire clock, resetN) ;//instruction依赖于宏定义

parameter WAITE =o ,
          LOAD = 1,
          STORE= 2;
reg [1∶0] State ,NextState ;//赋值依赖于参数

always @(posedge clock , negedge resetN)
    if ( !resetN) state <= WAITE;
    else state <=NextState ;
always @ (State) begin
    case (State)
        WAITE:NextState = LOAD;
        LOAD: NextState = STORE;
        STORE: NextState = WAITE;
    endcase
end

always @ (State, instruction) begin
    read = 0 ; write = 0 ;
    if (State == LOAD && instruction == `FETCH)
    read = 1;
else if (State == STORE && instruction ==`WRITE)
    write = 1 ;
end
endmodule

使用SV,代码更加明了,易于维护.

package chip_types;
    typedef enum {FETCH,WRITE,ADD,SUB ,MULT,DIV,SHIFT,NOP } instr_t;
Endpackage

import chip_types : :* ; //将包的定义导入到$unit里
module controller (output logic read, write ,input instr_t instruction,input wire clock , resetN) ;#自定义类型instr_t instruction
    enum {WAITE,LOAD,STORE} State, Nextstate ;
    always_ff @(posedge clock , negedge resetN)
    if ( !resetN) State <= WAITE;
    else state <= NextState ;
    always_comb begin
        case (State)
                WAITE:Nextstate = LOAD ;
                LOAD: Nextstate = STORE;
                STORE: NextState = WAITE;
        endcase
    end
always_comb begin
    read = 0 ; write = 0 ;
    if (State == LOAD && instruction == FETCH) read = 1;
    else if (State == STORE && instruction == WRITE) write = 1;
    end
endmodule

        默认的枚举类型是int,即32位的二值逻辑数据类型。为了更准确地描述变量,SV允许指明其数据类型,例如:

enum bit {TRUE,FALSE} Boolean ;
enum logic [1:0] {WAITE,LOAD,READY} state ;

        如果枚举类型变量被赋值,那么所赋的值应在其数值范围。

enum logic [2:0] {WAITE= 3’ b001, LOAD = 3' b010, READY =3' b100} state ;

         如果枚举变量是四值逻辑,那么将其值赋为X或者Z也是合法的。

enum logic {ON=1'b1,OFF=1'bz} out;

枚举类型:

  • 匿名枚举类型(anonymous enumerated type:枚举类型并没有伴随着typedef
  • 枚举类型也可以声明为自定义类型,这就使得可以用同一个枚举类型来声明多个变量或者线网。
typedef enum {WAITE,LOAD,READY} states_t;
states_t state, next_state ;

枚举类型赋值:
        Verilog或者SV可以在不同的数据类型之间通过隐性转换,进行直接赋值,因此Verilog/SV的数据类型转换是宽松的。
        枚举类型赋值时则相对严格。

        例如下面的例子中,赋值操作符“=”的左右两侧应该尽量为相同的枚举类型。

typedef enum {WAITE,LOAD,READY] states_t;
states_t; state, next state ;
int foo;
state = next state; //合法操作
foo = state +1; //合法操作
state = foo + 1; //非法赋值
state = states_t'(foo + 1)//合法赋值
state = state +1; l/非法赋值
state = states _t'(state + 1)//合法赋值
state++; //非法赋值
next state +=state; //非法赋值

struct 

为什么要用结构体: 

        设计或者验证的数据经常会有逻辑相关的数据信号组,例如一个总线协议的所有控制信号,或者在一个状态控制器中用到的所有的信号。

        Verilog语言没有方便的特性可以将相关的信号收集整理到一个信号组中。 SV添加了同C一样的结构体struct。

        结构体的成员可以是任何变量类型,包括首定义类型或者其它常量类型。

struct {
int a, b; //32位变量
opcode_t opcode; //用户自定义类型
logic [23:0] address; // 24位变量
bit error; //1位变量
} Instruction_word;

        正是由于结构体是变量的合集,因此结构体类型的变量也可以用来索引到其内部的变量,索引方式同C语言一致: 

<structure_name>.<variable_name>
Instruction_word .address = 32' hFo00001E ;

        结构体类型默认也是变量类型,用户也可以显式声明其为var或者wire类型。
        类似于枚举类型,结构体类型也可以伴随着typedef来实现自定义结构体类型。

//自定义结构体
typedef struct { 
logic [31:0] a, b;
logic [ 7:0] opcode ;
logic [23:0] address;} instruction_word_t;

instruction_word_t Iw; 1/结构体变量声明

结构体变量可以通过索引其各个成员做依次的成员赋值:

always (posedge clock, negedge resetN) begin
if ( !resetN) begin
            Iw.a = 100; //reference structure member
            Iw.b = 5;
            Iw.opcode = 8' hFF;
            Iw.address = 0 ;
        end
        else begin
        ...
        end
end

也可以通过分号’和花括号{}来实现整体赋初值:

Iw =' {100, 3,8" hFE, 0};
Iw = " {address: 0, opcode : 8* hFF, a:100, b:5};


http://www.niftyadmin.cn/n/586977.html

相关文章

python3 urllib调用spring cloud服务报urllib.error.HTTPError: HTTP Error 400: Bad Request排查

背景 使用python3的urllib调用spring cloud服务接口&#xff0c;一直报错 File "E:\github\workspace\dbfree\src\test\common\test_paas_api_base.py", line 49, in test_zjkresp urllib.request.urlopen(req, timeout5)File "C:\Users\zhangjikuan\AppData\…

JavaScript学习一(alert console prompt ,数据类型)

1.alert(“”)&#xff1b;弹出输入框 2.console.log(“”)&#xff0c;向浏览器的控制台输出一句话&#xff0c;在审查元素的console中显示内容&#xff0c;&#xff0c;&#xff0c;用来调试程序 3.prompt(“”) 弹出输入框&#xff0c;用来给用户提供输入信息的位置 二.直接…

k8s基本命令

kubectl命令 kubectl certificate 证书管理kubectl cluster-info 查看k8s集群信息get -h帮助 -n指定namespace -o wide/json/yml 显示更多/json格式信息 kubectl get all 查看所有资源信息kubectl get componentstatuses 查看组件信息&#xff0c;可用-s http://localhost:808…

Java创建对象有几种方式

以下都是Java的基础面试题&#xff0c;相信大家都会有种及眼熟又陌生的感觉、看过可能在短暂的面试后又马上忘记了。JavaPub在这里整理这些容易忘记的重点知识及解答&#xff0c;建议收藏&#xff0c;经常温习查阅。 文章目录Java创建对象有几种方式10道不得不会的Java基础面试…

JavaScript学习二(Math对象, 逻辑,比较(关系),赋值,逗号运算符)

1.Math对象的常用方法 以上的方法中&#xff0c;random以上的最常用。 2. 逻辑运算符 与或非 与&#xff1a; && 相同为true &#xff0c;一错全错 或&#xff1a; || 一对为对&#xff0c;&#xff0c;都错为错 非: &#xff01; &#xff08;取反&#xff09…

Mac 平台 MySQL连接工具 Sequel Pro 使用经验之谈

刚刚转到 Mac 开发平台&#xff0c;还在恋恋不舍地使用着之前的最爱 dbeaver&#xff0c;但是查询速度确实慢&#xff0c;看到同事都是使用 sequel pro。大致查找学习网络教程&#xff0c;总结如下&#xff1a; 据说这款工具是苹果公司为了吸引Web开发者进入Mac平台而投资的项目…

spring无侵入自动生成接口文档

背景 spring cloud多个微服务开发了很多接口&#xff0c;紧急对接前端&#xff0c;需要快速提供一批接口的文档&#xff0c;且不同微服务的接口由多位同事开发且注释非常的少各有不同&#xff0c;现在需要不修改代码不添加注释的情况下能自动的扫描接口并生成文档。本文将详细介…

谈谈NIO和BIO区别

以下都是Java的基础面试题&#xff0c;相信大家都会有种及眼熟又陌生的感觉、看过可能在短暂的面试后又马上忘记了。JavaPub在这里整理这些容易忘记的重点知识及解答&#xff0c;建议收藏&#xff0c;经常温习查阅。 文章目录谈谈NIO和BIO区别10道不得不会的Java基础面试题谈谈…