SystemVerilog语法基础——7高级语法(1):typedef、struct、enum、union

高级语法(1):typedef、struct、enum、union

前言

视频语法学习:B站链接
笔记原地址:https://github.com/Tan-YiFan/DigitalLogic-Autumn2020/tree/syntax/syntax网络不好,可能打不开。

数字电路中,万物皆为二进制。

类型统一为logic,符合这一规律。但这对程序员,可能不太友好。

  1. 需要管理变量的位数
  2. 同一位数的信号,可能意义完全不同(1010可能是格雷码/正常数值)

对此,引入自定义类型语法typedef。

1 typedef基础

基本格式为:typedef 已有类型 新类型;
一般自定义类型后面添加一个_t,方便区分。

typedef logic[31:0] word_t;//32位的数声明成一个字
typedef logic[5:0] entry_t;//表项是一个类型
typedef entry_t[31:0] table_t;//32位的表项组成一个table,table(是关键字)是已有自定义的类型生成的一个自定义的类型

声明与使用变量的语法:

word_t a, b;//a, b均为32位
assign b = {a[15:0], a[31:16]};

table_t table1; //table1与table_t是一致滴//table1是 logic [31:0][5:0]32个6位的向量
assign table1[1] = '0;// table1[1]是一个6位的向量
assign table1[0][1] = '0;// table1[0][1]可以2级索引

用途举例:变量名的含义,用类型去判断变量的实际意义

//四——十六译码器
typedef logic[3:0] code_t;//输入是编码
typedef logic[15:0] info_t;//输出是信息

typedef logic[31:0] paddr_t; // physical address
typedef logic[31:0] vaddr_t; // virtual address

2 struct

结构体struct可以描述一组相关的数据。

以译码器为例,按以前的写法,可能需要这样写:

logic [3:0] alufunc;
//alufunc_t alufunc;//或者用自定义类型
logic mem_read;
logic mem_write;
logic regwrite;

logic [6:0] control;
assign control = {alufunc, mem_read, mem_write, regwrite};//要把control的位数算出来,多的数据的时候,计算control很麻烦

结构体类型相关的语法如下:

// type definition
//该句中可以把struct看作已有类型名,control_t是新类型名
typedef struct packed {    //{}中是信号声明语句,分号结尾
    logic [3:0] alufunc;
    logic mem_read;
    logic mem_write;
    logic regwrite;
    logic [3:0] reg_addr;//可以任意添加信号,不用修改control_t的位数
} control_t;//control_t是类型名

// variable declaration变量声明
control_t control;//结构体声明变量,control会计算有多少位,存储从高位到低位存储,算出来7位

logic regwrite;
assign regwrite = control.regwrite;//使用的时候:变量.成员
//或者用assign regwrite = control[0];//按位索引也一样;从低位索引

// using structs without typedef匿名类型
struct packed {//类型名+变量名去声明
    logic [3:0] alufunc;
    logic mem_read;
    logic mem_write;
    logic regwrite;
} control_without_typedef;//control_without_typedef是一个结构体

struct语法有很多好处,用途也很广。

//流水线寄存器
typedef struct packed {
    //省略元素
} pipeline_decode_t;

pipeline_decode_t p, p_nxt;//声明变量
always_ff @(posedge clk) begin
    p <= p_nxt;
end

3 enum

枚举类型,要求每一个变量的数据位是一样长
枚举的语法形式为:

typedef enum <datatype> {//<datatype>是已有数据类型,一般是指定位数
    IDEN_1, IDEN_2//是常量,可以看作宏,仿真器从低到高,会认为IDEN_1是0, IDEN_2是1
} typename;//typename是自己的命名

举例:

typedef enum logic [3:0] {
    ALU_ADD, ALU_AND, ALU_SUB
} alufunc_t;

alufunc_t alufunc;//声明变量

enum logic [3:0] {
    ALU_ADD, ALU_AND, ALU_SUB
} alufunc_without_typedef;

enum语法常用于编码(包括状态机的编码)。

enum类型的变量,在Vivado仿真里会显示枚举项,如:显示ALU_ADD, ALU_AND, ALU_SUB,而不是0、1、2。(参考我的视频《编码和译码的应用》)

枚举项被视为常量,各枚举类型的枚举项名字不能冲突。

enum类型的变量,赋值时只能用枚举项。

//状态机
typedef enum logic [1:0] {
    STATE_0, STATE_1, STATE_2
} state_t;

state_t state, state_nxt;
always_ff @(posedge clk) begin
    if (~resetn) begin
        // state <= '0;//此处是枚举类型,会出错
        state <= state_t'(0);//state_t'(0)此处是0号状态,即STATE_0
    end else begin
        state <= state_nxt;
    end
end

4 union

联合类型的语法:

typedef union packed {
    struct packed {
        logic zero;
        logic [31:0] aluout;
    } alu;
    struct packed {
        logic branch_taken;
        logic [31:0] pcbranch;
    } branch;
    struct packed {
        logic [31:0] addr;
        logic mem_read;
    } memory;
} result_t;

result_t res;

logic [31:0] addr, aluout;
assign addr = res.memory.addr; // assign addr = res[32:1]//重高到低
assign aluout = res.alu.aluout; // assign aluout = res[31:0]

assign res.alu.aluout = '1;//相当于alu低32位([31:0])全是1,已经有驱动啦,不能在对pcbranch和mem_read在赋值;
//如果再次赋值,则是多驱动了,同一个信号,只能有一个驱动

对union类型的变量进行赋值时,要注意多驱动。
union类型比较占空间

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值