数组、结构体和联合结构体

数组、结构体和联合结构体

结构体

结构体是对一些相关信号进行分组的最方便办法。

struct{
	int	a,b	;
	opcode_t opcode	;
	logic [23:0] address	;
	bit	error	;
}instruction_word;
assign instruction_word.address = 32'hF000001E	;

结构体是不同类型和尺寸的变量和常量的集合,通过成员名称引用。

var struct{		//结构体变量
	logic [31:0]a,b;
	logic [7:0] opcode;
	logic [23:0] address;
}instruction_word_var	;

wire struct{		//结构体线网
	logic [31:0] a,b ;
	logic [7:0] opcode ;
	logic [23:0] address;
}instruction_word_net;

默认情况下,结构体被认为是变量。

typedef struct{		
	logic [31:0]a,b;
	logic [7:0] opcode;
	logic [23:0] address;
}instruction_word_t	;
	instruction_word_t IW=`{100,3,8'hFF,0};

注意结构体初始化时{}前边跟一个`

typedef struct{		
	logic [31:0]a,b;
	logic [7:0] opcode;
	logic [23:0] address;
}instr_t	;
	instr_t IW;
	always @(posedge clock,negedge resetN)
		if(!resetN) begin
			IW.a = 100 ;//引用结构体成员赋值
			IW.b = 5	;
			IW.opcode = 8'hff	;
			IW.address = 0;
            // IW = `{address:0,opcode:8'hFF,a:100,b:4};
            // IW = `{default:0};
	end
endmodule

可使用packed关键字显式声明一个压缩结构体,压缩结构体按照指定的顺序以相邻位来存储结构体成员。

struct packed{
	logic	valid ;
	logic [7:0] tag ;
	logic [31:0] data;
}data_word;
	data_word.tag = 8'hf0;
//data_word[39:32] = 8'hf0; 等价写法

数组、结构体和联合结构体

注意:压缩结构体所有成员必须是整数值,可以当作向量处理。且压缩结构体作为向量使用是可以有符号或者无符号的。

通过typedef将struct写成自定义数据类型,也可以作为端口数据类型进行使用。

非压缩和压缩结构体都是可综合的

联合体

结构体可以存储很多值,是一个名称下的变量集合。而联合体只存储一个元素,这个元素可以有多种表示方法,每种甚至可以是不同的数据类型,但每次只使用一种类型。

union {
	int i;
	int unsigned u;
}data;
	data.i = -5 ;
	$display("data is %d",data.i);
	data,u = -5 ;
	$display("now data is %d",data.u);

非压缩联合体可以存储任何数据类型,因此不可综合。

压缩联合体要求每个联合体成员的位数相同,保证压缩联合体使用同样的位数进行存储,因此可以综合。

数组、结构体和联合结构体

压缩联合体支持以一种格式写入,以另一种格式读出。

数组

非压缩数组

reg[7;0]LUT[0:255]//256个8位变量的一维非压缩数组
wire n[0:1023] //1024个1位线网的一维非压缩数组
int d1[0:1][0:3] = `{`{7,3,0,5},`{2,0,1,6}} ;

非压缩数组把位宽声明放在变量名后边

压缩数组

logic[3:0][7:0]data  ;//2维压缩数组

数组、结构体和联合结构体

只有位形式的数据类型才可以被压缩

typedef struct packed{
	logic [7:0] crc ;
	logic [63:0] data;
}data_word;
	data_word[7:0] array ;//由压缩结构体构成的一维压缩数组

压缩数组和非压缩数组都是可综合的,注意由联合体构成的数组也是可综合的,但要求联合体是压缩联合体。且用结构体和联合体定义数组时必须使用typedef关键字、

练习示例

结构体和联合结构体

package definitions ;
    typedef enum{ADD,SUB,MULT,DIV,SL,SR} opcode_t   ;
    typedef enum{UNSIGNED,SIGNED}operand_type_t     ;
    typedef union packed{
        logic   [31:0]  u_data  ;
        logic   signed [31:0] s_data    ;
    } data_t ;

    typedef struct packed{
        opcode_t            opc     ;
        operand_type_t      op_type ;
        data_t              op_a    ;
        data_t              op_b    ;
        } instr_t ;
endpackage

import definitions::* ;

module alu(
    input   instr_t IW  ,
    output  data_t alu_out
);
    always @(IW) begin
        if(IW.op_type == SIGNED) begin
            case(IW.opc)
                ADD : alu_out.s_data = IW.op_a.s_data + IW.op_b.s_data ;
                SUB : alu_out.s_data = IW.op_a.s_data - IW.op_b.s_data ;
                MULT: alu_out.s_data = IW.op_a.s_data * IW.op_b.s_data ;
                DIV : alu_out.s_data = IW.op_a.s_data / IW.op_b.s_data ;
                SL  : alu_out.s_data = IW.op_a.s_data <<< 2            ;
                SR  : alu_out.s_data = IW.op_a.s_data >>> 2            ;
            endcase
        else begin
            case(IW.opc)
                ADD : alu_out.u_data = IW.op_a.u_data + IW.op_b.u_data ;
                SUB : alu_out.u_data = IW.op_a.u_data - IW.op_b.u_data ;
                MULT: alu_out.u_data = IW.op_a.u_data * IW.op_b.u_data ;
                DIV : alu_out.u_data = IW.op_a.u_data / IW.op_b.u_data ;
                SL  : alu_out.u_data = IW.op_a.u_data <<< 2            ;
                SR  : alu_out.u_data = IW.op_a.u_data >>> 2            ;
            endcase
        end
    end
endmodule

使用结构体构成的数组对指令寄存器建模

package definitions ;
    typedef enum{ADD,SUB,MULT,DIV,SL,SR} opcode_t ;
    typedef enum{UNSIGNED,SIGNED} operand_type_t    ;
    typedef union packed{
        logic[31:0] u_data  ;
        logic signed [31:0] s_data ;
    } data_t ;

    typedef struct packed{
        opcode_t        opc     ;
        operand_type_t  op_type ;
        data_t          op_a    ;
        data_t          op_b    ;
    } instr_t ;
endpackage

import  definitions::*  ;
module  instruction_register(
    output instr_t[0:31] instr_reg  ,
    input   data_t       operand_a  ,
    input   data_t       operand_b  ,
    input   operand_type_t  op_type ,
    input   opcode_t     opcode     ,
    input   logic[4:0]   write_pointer
);
    always @(write_pointer) begin
        instr_reg[write_pointer].op_type = op_type  ;
        instr_reg[write_pointer].opc    = opcode    ;
        if(op_type == SIGNED) begin
            insrt_reg[write_pointer].op_a.s_data = operand_a.s_data;
            insrt_reg[write_pointer].op_b.s_data = operand_b.s_data;
        end
        else begin
            insrt_reg[write_pointer].op_a.u_data = operand_a.u_data;
            insrt_reg[write_pointer].op_b.u_data = operand_b.u_data;
        end
    end
endmodule

把所有信息放入对应的指令结构体,多个指令结构体构成数组。

指令结构体构成的数组可抽象为指令寄存器。

遍历数组

int sum[1:8][1:3] ;
foreach (sum(i,j))
	sum[i][j] = i + j ;

数组对应系统函数

$dimensions(数组名)//返回数组维数,若不是数组则返回0.
$left(数组名,维度)//返回指定维度的最高有效位数
$right(数组名,维度)//返回指定维度的最低位数
$high(数组名,维度)//返回维度的最高位数
$size(数组名,维度)//返回指定维度元素的总个数
$increment(数组名,维度)//对于指定维度,若$left大于$right,则返回1,若小于则返回-1

数组、结构体和联合结构体

$bits

$bits(表达式)//返回任意表达式的位数

只要给$bits的自变量不是自动宽度的数组,就可以综合

动态宽度的数组不可综合,只可用来验证和更高抽象级建模。

上一篇:2021-2027年中国铪市场调研与发展趋势分析报告


下一篇:2022-2028全球浪涌抑制集成电路行业调研及趋势分析报告