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 begin
case(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
声明域中。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
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_state
Next = 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:sub1
module 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:ROM
module program_count(...)
endmodule:program_count
module address_reg(...)
endmodule:address_reg
endmodule:chip
接口 interface ... endinterface
是一种功能强大的端口类型,可以简化复杂设计的建模和验证。可在 module
外单独定义。
支持多个信号组成一个端口,只需声明 1 次。接口中可以包括端口、任务 task
、函数 function
、过程块、程序块,也可参数化。
interface main_bus;
logic[15:0] data;
logic[15:0] address;
logic[7:0] bus_request;
endinterface
module top()
main_bus bus() /* 接口实例化 */
slave slave1(.bus(bus));
endmodule