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

自定义类型 

通过用户自定义类型,以往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};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值