[system verilog] 一个简单memory的验证

前言:刚开始接触sv时,由于有些参考的sv example中没有提供编译和仿真命令,为了更清晰地知道运行结果,故写了此博客

一、框架图如下所示

二、文档如下所示

2.1 memory.sv

module memory(
address,
data_in,
data_out,
read_write,
chip_en
);

  input wire [7:0] address, data_in;
  output reg [7:0] data_out;
  input wire read_write, chip_en;

  reg [7:0] mem [0:255];

  always @ (address or data_in or read_write or chip_en)
  if (read_write == 1 && chip_en == 1) begin
    mem[address] = data_in;
  end

  always @ (read_write or chip_en or address)
  if (read_write == 0 && chip_en) 
    data_out = mem[address];
  else
    data_out = 0;

endmodule

2.2、mem_ports.sv

interface mem_ports(
 input  wire  clock,
 output logic [7:0] address,
 output logic chip_en,
 output logic read_write,
 output logic [7:0] data_in,
 input logic [7:0] data_out
);
endinterface

2.3、mem_base_object.sv

class mem_base_object;
  bit [7:0] addr;
  bit [7:0] data;
  // Read = 0, Write = 1
  bit rd_wr;
endclass

2.4、mem_txgen.sv

class mem_txgen;
  mem_base_object  mem_object;
  mem_driver  mem_driver;
  
  integer num_cmds;

function new(virtual mem_ports ports);
  begin
    num_cmds = 3;
    mem_driver = new(ports);
  end
endfunction


task gen_cmds();
  begin
    integer i = 0;
    for (i=0; i < num_cmds; i ++ ) begin
      mem_object = new();
      mem_object.addr = $random();
      mem_object.data = $random();
      mem_object.rd_wr = 1;
      mem_driver.drive_mem(mem_object);
      mem_object.rd_wr = 0;
      mem_driver.drive_mem(mem_object);
    end
  end
endtask

endclass

2.5、mem_driver.sv

class mem_driver;
  virtual mem_ports ports;

function new(virtual mem_ports ports);
  begin
    this.ports = ports;
    ports.address    = 0;
    ports.chip_en    = 0;
    ports.read_write = 0;
    ports.data_in    = 0;
  end
endfunction

task drive_mem (mem_base_object object);
  begin
    @ (posedge ports.clock);
    ports.address    = object.addr;
    ports.chip_en    = 1;
    ports.read_write = object.rd_wr;
    ports.data_in    = (object.rd_wr) ? object.data : 0;
    if (object.rd_wr) begin
      $display("Driver : Memory write access-> Address : %x Data : %x\n", 
        object.addr,object.data);
    end else begin
      $display("Driver : Memory read  access-> Address : %x\n", 
        object.addr);
    end
    @ (posedge ports.clock);
    ports.address    = 0;
    ports.chip_en    = 0;
    ports.read_write = 0;
    ports.data_in    = 0;
 end
endtask

endclass

2.6、mem_ip_monitor.sv

class mem_ip_monitor;
  mem_base_object mem_object;
  mem_scoreboard  sb;
  virtual mem_ports       ports;

function new (mem_scoreboard sb,virtual mem_ports ports);
  begin  
    this.sb    = sb;
    this.ports = ports;
  end
endfunction


task input_monitor();
  begin
    while (1) begin
      @ (posedge ports.clock);
      if ((ports.chip_en == 1) && (ports.read_write == 1)) begin
         mem_object = new();
         $display("input_monitor : Memory wr access-> Address : %x Data : %x", 
            ports.address,ports.data_in);
	 mem_object.addr = ports.address;
	 mem_object.data = ports.data_in;
         sb.post_input(mem_object);
      end
    end
  end
endtask

endclass

2.7、mem_op_monitor.sv

class mem_op_monitor;
  mem_base_object mem_object;
  mem_scoreboard sb;
  virtual mem_ports       ports;

function new (mem_scoreboard sb,virtual mem_ports ports);
  begin
    this.sb    = sb;
    this.ports = ports;
  end
endfunction
  

task output_monitor();
  begin
    while (1) begin
      @ (negedge ports.clock);
      if ((ports.chip_en == 1) && (ports.read_write == 0)) begin
        mem_object = new();
        $display("Output_monitor : Memory rd access-> Address : %x Data : %x", 
          ports.address,ports.data_out);
        mem_object.addr = ports.address;
        mem_object.data = ports.data_out;
        sb.post_output(mem_object);
      end
    end
  end
endtask


endclass

2.8、mem_scoreboard.sv

class mem_scoreboard;
  // Create a keyed list to store the written data
  // Key to the list is address of write access
  mem_base_object mem_object [*];

  // post_input method is used for storing write data
  // at write address
task post_input (mem_base_object  input_object);
  begin
    mem_object[input_object.addr] = input_object;
  end
endtask
  // post_output method is used by the output monitor to 
  // compare the output of memory with expected data
task post_output (mem_base_object  output_object);
  begin
   // Check if address exists in scoreboard  
   if (mem_object[output_object.addr] != null) begin 
      mem_base_object  in_mem = mem_object[output_object.addr];
      $display("scoreboard : Found Address %x in list",output_object.addr);
      if (output_object.data != in_mem.data)  begin
        $display ("Scoreboard : Error : Exp data and Got data don't match");
        $display("             Expected -> %x",
          in_mem.data);
        $display("             Got      -> %x",
          output_object.data);
      end else begin
        $display("Scoreboard : Exp data and Got data match");
      end
   end 
  end 
endtask

endclass

2.9、test.sv


`include "mem_ports.sv"

program memory_top(mem_ports ports);
`include "mem_base_object.sv"
`include "mem_driver.sv"
`include "mem_txgen.sv"
`include "mem_scoreboard.sv"
`include "mem_ip_monitor.sv"
`include "mem_op_monitor.sv"
  mem_txgen txgen;
  mem_scoreboard sb;
  mem_ip_monitor ipm;
  mem_op_monitor opm;

initial begin
  sb    = new();
  ipm   = new (sb, ports);
  opm   = new (sb, ports);
  txgen = new(ports);
  fork
    ipm.input_monitor();
    opm.output_monitor();
  join_none
  txgen.gen_cmds();
  repeat (20) @ (posedge ports.clock);
end

endprogram

2.10、top.sv

`include "memory.sv"

module memory_tb();

wire [7:0] address, data_in;
wire [7:0] data_out;
wire  read_write, chip_en;
reg clk;

// Connect the interface
mem_ports ports(
 .clock       (clk),
 .address     (address),
 .chip_en     (chip_en),
 .read_write  (read_write),
 .data_in     (data_in),
 .data_out    (data_out)
);

// Connect the program
memory_top top (ports);

initial begin
  clk = 0;
end	

always #1 clk = ~clk;

memory U_memory(
.address             (address),
.data_in             (data_in),
.data_out            (data_out),
.read_write          (read_write),
.chip_en             (chip_en)
);
endmodule

二、用vcs跑

首先输入

然后输入

可以看到运行结果

三、参考

Welcome To SystemVerilog Central

如有不正,欢迎指正

  • 19
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值