文章目录
- 包定义
- SystemVerilog 数据类型
- 结构体
- SystemVerilog 过程块
- 可嵌套模块
- 接口
System Verilog 的优点
-
提高了硬件建模能力、编码效率和抽象能力;RTL 级、系统级行为描述;
-
增强了验证能力和为大规模复杂设计编写有效、无竞争测试程序的断言功能;
-
相比 Verilog,有助于编写可综合硬件模型的特点:
- 设计内部的封装通信和协议检查的接口;
- 支持数据类型
int
、用户自定义类型typedef
、枚举类型、类型转换; - 结构体、联合体、可共享的定义包
package
; ++
--
+=
赋值操作;- 显式过程块、
priority
、unique
修饰符; - 编程语句增强、通过引用传送到任务、函数和模块。
包定义
包 package ... endpackage
,独立的声明空间,多个模块共享用户定义类型。包中可包含的可综合的结构:
parameter
和localparam
常量定义;const
定义变量为常数;typedef
用户定义类型;automatic task
、function
定义;- 从其它包中
import
语句; - 操作符重载定义。
包定义示例:
package definitions;parameter Version="1.1";typedef enum{ADD, SUB, MUL} opcodes_t;typedef struct{logic[31:0] a,b;opcodes_t opcode;} instruction_t;function automatic[31:0] multiplier(input[31:0] a,b);return a*b;endfunction
endpackage
包可独立放在一个文件中,用 include "包名"
引入。
如何引用包的内容?
- 用范围解析操作符
::
直接引用;
module ALU
(input definitions::instruction_t IW,input logic clock,output logic[31:0] result);always_ff@(posedge clock)case(IW.opcode)definitions::ADD: result = IW.a + IW.b;definitions::SUB: result = IW.a - IW.b;definitions::MUL: result = definitions::multiplier(IW.a, IW.b);endcase
endmodule
- 将包中特定子项导入到模块或接口中;
module ALU
(input definitions::instruction_t IW,input logic clock,output logic[31:0] result);import definitions::ADD;
import definitions::SUB;
import definitions::MUL;
import definitions::multiplier;always_comb begincase(IW.opcode)ADD: result = IW.a + IW.b;SUB: result = IW.a - IW.b;MUL: result = multiplier(IW.a, IW.b);endcase
end
endmodule
- 用通配符
*
导入包中的子项到模块或接口中;
import definitions::*;
module tb_ALU;
instruction_t test_word;
logic[31:0] alu_out;
logic clock = 0;ALU dut(.IW(test_word), .result(alu_out), .clock(clock));
always #10 clock = ~clock;
initial begin@(negedge clock)test_word.a = 5;test_word.b = 7;test_word.opcode = ADD;@(negedge clock)$display("alu_out=%d(expected 12)", alu_out);$finish;
end
endmodule
- 将包中子项导入到
$unit
声明域中。
SystemVerilog 数据类型
- 增加 bit byte(8) int(32) shortint(16) longint(64) 变量类型;
logic
定义变量,代替reg
,四态0 1 Z X
;void
类型表示无存储;var
关键字表示对象是一个变量,比如var logic[7:0] a
;- 静态变量
static
,自动变量automatic
; - 用户自定义类型
typedef
; - 枚举数据类型
enum
以有限状态机为例说明枚举类型的使用:
module FSM(input logic clock, resetN, output logic[3:0] control);
enum logic[2:0] {WAITE=3'b001, LOAD=3'b010, READY=3'b100} State, Next;always@(posedge clock, negedge resetN)if(!resetN) State <= WAITE;else State <= Next;always_comb begin$display("\n Current state is %s(%b)", State.name, State);case(State)WAITE: Next = LOAD;LOAD; Next = READY;READY: Next = WAITE;endcase$display("\n Next state will be %s(%b)", Next.name, Next);
end
assign control = State;
endmodule
结构体
结构体 struct
、联合体 union
数据类型,一种变量集表示。
结构体 struct
可以包括任何数据类型,可以集合不同类型和大小的变量、常量、自定义等:
struct{int a,b;opcode_t opcode;logic[23:0] address;bit error;
} Instruction_Word /* 结构体名 */
引用结构体:<结构体名>.<变量名>
,如 Instruction_Word.address=32'h00ff00ff
SystemVerilog 过程块
always_comb
:组合逻辑过程块,不需要指明敏感表always_ff
:时序逻辑过程块always_latch
:锁存逻辑过程块unique case / if...else if...
:只有且必须有一个条件匹配,否则报告运行错误priority case / if...else if...
:至少有一个条件匹配,多个匹配则执行第一个匹配分支
module traffic_light(output logic green_light, yellow_light, red_light,input sensor, input[15:0] green_downcnt, yellow_downcnt, input clock, resetN);
enum {RED, GREEN, YELLOW} State, Next;/* 时序电路 */
always_ff@(posedge clock, negedge resetN)if(!resetN) State <= RED;else State <= Next;/* 组合电路 */
always_comb begin:set_next_stateNext = State;unique case(State)RED: if(sensor) Next = GREEN;GREEN: if(green_downcnt==0) Next = YELLOW;YELLOW: if(yellow_downcnt==0) Next = RED;endcase
end:set_next_state/* 组合电路 */
always_comb begin:set_outputs{green_light, yellow_light, red_light} = 3'b000;unique case(State)RED: red_light = 1'b1;GREEN: green_light = 1'b1;YELLOW: yellow_light = 1'b1;endcase
end:set_outputs
endmodule
可嵌套模块
只能在父模块中实例化:
module ip_core(input logic clock);sub u1(.*);sub u2(.*);module sub1(...)...endmodule:sub1module sub2(...)...endmodule:sub2
endmodule:ip_core
例:用 SystemVerilog 实现以下结构图(主模块名 chip
,地址位宽 32bits):
module chip(input_master_clock, master_reset);
logic[31:0] address, new_address, next_address;ROM u1(.address(address), .data(new_address), .clk(master_clock));program_count u2(.jump_address(new_address), .clock(master_clock), .reset_n(master_reset), .next_address(next_address));address_reg(.next_addr(next_address), .current_addr(address), .clk(master_clock), .rstN(master_reset));module ROM(output logic[31:0] data, input logic[31:0] address, input logic clk);
endmodule:ROMmodule program_count(...)
endmodule:program_countmodule address_reg(...)
endmodule:address_regendmodule:chip
接口
接口 interface ... endinterface
是一种功能强大的端口类型,可以简化复杂设计的建模和验证。可在 module
外单独定义。
支持多个信号组成一个端口,只需声明 1 次。接口中可以包括端口、任务 task
、函数 function
、过程块、程序块,也可参数化。
interface main_bus;logic[15:0] data;logic[15:0] address;logic[7:0] bus_request;
endinterfacemodule top()main_bus bus() /* 接口实例化 */slave slave1(.bus(bus));
endmodule