数字硬件建模SystemVerilog-使用结构体和联合体的例子
使用结构体和联合体的例子
结构体和联合体可以包括压缩或非压缩数组,压缩结构体或联合体只能包括压缩数组。
压缩和非压缩的数组可以将结构体和联合体作为元素包含在数组中。在压缩数组中,结构体或联合体也必须是压缩的。
数组可以包含自定义结构体和自定义联合体。综合支持数组中的压缩或非压缩结构体。
示例4-8说明了如何使用结构体数组,该示例是一个指令寄存器模型,其中包含32条指令的非压缩数组,每条指令是一个复合值,表示为压缩结构体。指令中的操作数可以是有符号的或无符号的,表示为两种类型的联合体。
该指令寄存器的输入包括单独的操作数、一个操作码和一个指示操作数是有符号的还是无符号的标志。该模型将这些单独的输入值加载到指令寄存器阵列中。一种写入指针输入控件,用于加载数据。该模型的输出是单个指令结构体,使用读指针输入从指令寄存器中选择。
本例使用了前面示例4-6中所示的相同包项。
示例4-6:包含结构体和联合体定义的包
// //Packagewithunionandstructuredefinitions // //`begin_keywords"1800-2012"//useSystemVerilog-2012keywords `define_4bit//use4-bitdatafortestingsynthesis //`define_32bit//use32-bitdatawordsize //`define_64bit//use64-bitdatawordsize packagedefinitions_pkg; `ifdef_4bit typedeflogic[3:0]uword_t; typedeflogicsigned[3:0]sword_t; `elsif_64bit typedeflogic[63:0]uword_t; typedeflogicsigned[63:0]sword_t; `else//defaultis32-bitvectors typedeflogic[31:0]uword_t; typedeflogicsigned[31:0]sword_t; `endif typedefenumlogic[2:0]{ADD,SUB,MULT,DIV}op_t; typedefenumlogic{UNSIGNED,SIGNED}operand_type_t; //Packedunionrepresentsavariablethatcanstore //differenttypes typedefunionpacked{ uword_tu_data; sword_ts_data; }data_t; //Packedstructurerepresentsacollectionofvariables //thatcanreferencedandpassedthroughportsasagroup typedefstructpacked{ op_topcode; operand_type_top_type; data_top_a; data_top_b; }instruction_t; endpackage:definitions_pkg //`end_keywords示例4-8:使用结构体数组对指令寄存器建模
//`begin_keywords"1800-2012"//useSystemVerilog-2012keywords moduleinstruction_register importdefinitions_pkg::*;//wildcardimportthepackage (inputlogicclk,rstN,load_en, inputdata_top_a, inputdata_top_b, inputoperand_type_top_type, inputop_topcode, inputlogic[4:0]write_pointer, inputlogic[4:0]read_pointer, outputinstruction_tiw ); timeunit1ns;timeprecision1ns; instruction_tiw_reg[0:31];//arrayofstructures //writetotheregisterarray always_ff@(posedgeclkornegedgerstN)//asyncreset if(!rstN)begin//active-lowreset foreach(iw_reg[i]) iw_reg[i]<= '{opcode:ADD,default:0}; // reset values end else if (load_en) begin case (op_type) SIGNED: iw_reg[write_pointer] <= '{opcode,op_type,op_a.s_data,op_b.s_data}; UNSIGNED: iw_reg[write_pointer] <= '{opcode,op_type,op_a.u_data,op_b.u_data}; endcase end // read from the register array assign iw = iw_reg[read_pointer]; endmodule: instruction_register //`end_keywords
图4-5显示了综合该示例的结果。说明了如何使用结构体和联合体、数组来建模大量设计功能,只需很少的代码。示意图右上角的矩形符号是综合编译器选择报告的通用RAM的实例(在RTL模型中数组的存储。)综合编译器将在综合的最后一步将该通用RAM作为一个或多个同步存储设备来实现,其中通用门级功能映射到特定的ASIC或FPGA设备。
图4-5:示例4-8的综合结果:带结构体的指令寄存器
附录-TestBench
//`begin_keywords"1800-2012" moduletest importdefinitions_pkg::*; (inputlogictest_clk, outputlogicload_en, outputlogicrstN, outputdata_top_a, outputdata_top_b, outputop_topcode, outputoperand_type_top_type, outputlogic[4:0]write_pointer, outputlogic[4:0]read_pointer, inputinstruction_tiw ); timeunit1ns;timeprecision1ns; intseed=555; initialbegin $display(" Resetingtheinstructionregister..."); write_pointer=5'h00;//initializewritepointer read_pointer=5'h1F;//initializereadpointer load_en=1'b0;//initializeloadcontrolline rstN<= 1'b0; // assert rstN (active low) repeat (2) @(posedge test_clk) ; // hold in reset for 2 clk cycles rstN = 1'b1; // deassert reset_n (active low) $display(" Writing values to register stack..."); op_type = SIGNED; op_a.s_data = 3; op_b.s_data = -5; opcode = ADD; load_en = 1'b1; // enable writing to register @(posedge test_clk) ; for (int i=0; i<=2; i++) begin write_pointer = i; $display("Writing to register location %0d: ", write_pointer); $display(" opcode = %0d (%s)", opcode, opcode.name); $display(" op_type = %0d (%s)", op_type, op_type.name); if (op_type == SIGNED) begin $display(" op_a.s_data = %0d", op_a.s_data); $display(" op_b.s_data = %0d ", op_b.s_data); end else begin $display(" op_a.s_data = %0d", op_a.u_data); $display(" op_b.s_data = %0d ", op_b.u_data); end @(negedge test_clk) ; op_a++; op_b--; opcode = op_t'(opcode + 1); op_type = op_type.next; end load_en = 1'b0; // turn-off writing to register // read back and display same three register locations $display(" Reading back the same register locations written..."); for (int i=0; i<=2; i++) begin @(posedge test_clk) read_pointer = i; @(negedge test_clk) ; $display("Read from register location %0d: ", read_pointer); $display(" iw.opcode = %0d (%s)", iw.opcode, iw.opcode.name); $display(" iw.op_type = %0d (%s)", iw.op_type, iw.op_type.name); if (iw.op_type == SIGNED) begin $display(" iw.op_a.s_data = %0d", iw.op_a.s_data); $display(" iw.op_b.s_data = %0d ", iw.op_b.s_data); end else begin $display(" iw.op_a.s_data = %0d", iw.op_a.u_data); $display(" iw.op_b.s_data = %0d ", iw.op_b.u_data); end end @(posedge test_clk) $finish; end endmodule: test module top; timeunit 1ns; timeprecision 1ns; import definitions_pkg::*; logic clk; logic test_clk; logic rstN; logic load_en; logic reset_n; op_t opcode; operand_type_t op_type; data_t op_a, op_b; logic [4:0] write_pointer, read_pointer; instruction_t iw; test test (.*); instruction_register dut (.*); initial begin clk <= 0; forever #5 clk = ~clk; end initial begin test_clk <=0; // offset test_clk edges from clk to prevent races between // the testbench and the design #4 forever begin #2ns test_clk = 1'b1; #8ns test_clk = 1'b0; end end endmodule: top //`end_keywords
SystemVerilog-联合体(union)
SystemVerilog-结构体(二)
原文标题:SystemVerilog-使用结构体和联合体的例子
文章出处:【微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。
-
寄存器
+关注
关注
31文章
5343浏览量
120368 -
数据
+关注
关注
8文章
7030浏览量
89035 -
硬件
+关注
关注
11文章
3328浏览量
66223
原文标题:SystemVerilog-使用结构体和联合体的例子
文章出处:【微信号:Open_FPGA,微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论