SystemVerilog 入门

文章目录

  • 包定义
  • SystemVerilog 数据类型
    • 结构体
  • SystemVerilog 过程块
  • 可嵌套模块
  • 接口

System Verilog 的优点

  • 提高了硬件建模能力、编码效率和抽象能力;RTL 级、系统级行为描述;

  • 增强了验证能力和为大规模复杂设计编写有效、无竞争测试程序的断言功能;

  • 相比 Verilog,有助于编写可综合硬件模型的特点:

    • 设计内部的封装通信和协议检查的接口;
    • 支持数据类型 int、用户自定义类型 typedef、枚举类型、类型转换;
    • 结构体、联合体、可共享的定义包 package
    • ++ -- += 赋值操作;
    • 显式过程块、priorityunique 修饰符;
    • 编程语句增强、通过引用传送到任务、函数和模块。

包定义

package ... endpackage,独立的声明空间,多个模块共享用户定义类型。包中可包含的可综合的结构:

  1. parameterlocalparam 常量定义;
  2. const 定义变量为常数;
  3. typedef 用户定义类型;
  4. automatic taskfunction 定义;
  5. 从其它包中 import 语句;
  6. 操作符重载定义。

包定义示例:

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 "包名" 引入。

如何引用包的内容?

  1. 用范围解析操作符 :: 直接引用;
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
  1. 将包中特定子项导入到模块或接口中;
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
  1. 用通配符 * 导入包中的子项到模块或接口中;
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
  1. 将包中子项导入到 $unit 声明域中。

SystemVerilog 数据类型

  1. 增加 bit byte(8) int(32) shortint(16) longint(64) 变量类型;
  2. logic 定义变量,代替 reg,四态 0 1 Z X
  3. void 类型表示无存储;
  4. var 关键字表示对象是一个变量,比如 var logic[7:0] a
  5. 静态变量 static,自动变量 automatic
  6. 用户自定义类型 typedef
  7. 枚举数据类型 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_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):

SystemVerilog 入门_第1张图片

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

你可能感兴趣的:(SoC设计,HDL,verilog,SoC)