数组、结构体和联合结构体
结构体
结构体是对一些相关信号进行分组的最方便办法。
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的自变量不是自动宽度的数组,就可以综合
动态宽度的数组不可综合,只可用来验证和更高抽象级建模。