带有打包结构参数的 Verilog 任务

问题描述 投票:0回答:1

我对执行并行总线读写的 SystemVerilog 任务有疑问。它使用打包的 struct ref 参数。任务不编译。

我有一个包含总线所有信号的结构

typedef struct packed {
  logic clk;
  logic rst;
  logic [31:0] addr;
  logic read;
  logic write;
  logic [31:0] write_data;
  logic [31:0] read_data;
  logic read_data_valid;
} sv_lb_type

然后我想写一个程序/任务来写。像这样的东西:

task automatic lb_write(
    input [31:0]   writeAddr,
    input [31:0]   writeData,
    ref struct {
      logic clk;
      logic rst;
      logic [31:0] addr;
      logic read;
      logic write;
      logic [31:0] write_data;
      logic [31:0] read_data;
      logic read_data_valid;
    } lb
  );
    begin

      $display("Waiting for LB reset to be deasserted");
      while (lb.rst != 1'b0) begin
        @(posedge lb.clk);
      end
      
      @(posedge lb.clk);
      
      lb.read       = 1'b1;
      lb.write      = 1'b0;
      lb.addr       = writeAddr;
      lb.write_data = writeData;
      
      @(posedge lb.clk);
      
      lb.read       = 1'b0;
      lb.write      = 1'b0;
      lb.addr       = '0;
      lb.write_data = '0;
      
      @(posedge lb.clk);
    
    end
  endtask

非常简化的测试平台如下所示:


`timescale  1 ps / 1 ps
`include "svInterfaces.sv"

module tb ( );
  import simMainPackage::*;
  
  wire                               rfClk;
  wire                               rfRst;
  
  // Local bus interface
  wire sv_lb_type                    lb_ds;

  ////////////////////////////////////////////////////////////////////////////
  // Testbench clock and reset generation
  ////////////////////////////////////////////////////////////////////////////
  
  clock_gen #(
    .FREQ   (100000)
  ) rfClk_inst (
    .enable (1'b1),
    .clk    (rfClk),
    .rst    (rfRst)
  );

  assign lb_ds.clk = rfClk;
  assign lb_ds.rst = rfRst;
  

  ////////////////////////////////////////////////////////////////////////////
  // DUT
  ////////////////////////////////////////////////////////////////////////////
  
  model_runner # (
      .ADDRESS                    (0)
    ) dut_inst (
      .clk                        (rfClk),
      .rst                        (rfRst),

      // Local bus interface
      .lb_us                      (lb_ds)
    );

  ////////////////////////////////////////////////////////////////////////////
  // Driving Process
  ////////////////////////////////////////////////////////////////////////////
  
  task run();
    $display("Starting Simulation");
    
    #10
    
    @(posedge lb_ds.clk);
    
    $display("Configuring Interface");
    lb_write(32'h00000001, 1, lb_ds);
    
    #10
    
    $stop();
  endtask


endmodule

但是我找不到一种方法来编写那个不仅给我错误的任务。

task verilog system-verilog procedure
1个回答
0
投票

在这里,结构和任务位于基于 OP 的测试平台中。

有两个问题阻止了 OP 任务的编译;一个测试台,一个任务定义(除了缺失的模型和包)。

问题已更正并评论 **** issue **** inline below.
第二期是 OP 评论中提到的那个。

测试平台:

module tb ( );
  // def of packed struct
  typedef struct packed {
    logic clk;
    logic rst;
    logic [31:0] addr;
    logic read;
    logic write;
    logic [31:0] write_data;
    logic [31:0] read_data;
    logic read_data_valid;
  } sv_lb_type  ;
  
  // clk & reset
  bit rfClk;
  bit rfRst;
  
  // **** issue #1 remove 'wire' ****
  sv_lb_type lb_ds;
  
  // clk
  always #5 rfClk = ! rfClk;

  // task def
  task automatic lb_write(
    input [31:0]   writeAddr,
    input [31:0]   writeData,
    // **** issue #2 wrong syntax ****
    ref sv_lb_type lb);
    // task body
    while (lb.rst != 1'b0) begin
      @(posedge lb.clk);
      $display("Waiting for LB reset to be deasserted");
    end
    @(posedge lb.clk);
    lb.read       = 1'b1;
    lb.write      = 1'b0;
    lb.addr       = writeAddr;
    lb.write_data = writeData;
    @(posedge lb.clk);
    lb.read       = 1'b0;
    lb.write      = 1'b0;
    lb.addr       = '0;
    lb.write_data = '0;
    @(posedge lb.clk);
    $display("COmpleting task");
  endtask
  
  assign lb_ds.clk = rfClk;
  assign lb_ds.rst = rfRst;
  
  // control
  initial begin
    $monitor("time = %0t, lb_ds.addr = %h, lb_ds.write_data = %h, lb_ds.read = %h", 
      $time, lb_ds.addr, lb_ds.write_data, lb_ds.read);
    #20;
    lb_write(32'h00000001, 1, lb_ds);
    #20;
    $finish;
  end
  
  // reset 
  initial begin
    rfRst = 1;
    #30;
    rfRst = 0;
  end  

endmodule    

出品:

# run -all
# time = 0, lb_ds.addr = xxxxxxxx, lb_ds.write_data = xxxxxxxx, lb_ds.read = x
# Waiting for LB reset to be deasserted
# Waiting for LB reset to be deasserted
# time = 45, lb_ds.addr = 00000001, lb_ds.write_data = 00000001, lb_ds.read = 1
# time = 55, lb_ds.addr = 00000000, lb_ds.write_data = 00000000, lb_ds.read = 0
# COmpleting task
# ** Note: $finish    : testbench.sv(60)
© www.soinside.com 2019 - 2024. All rights reserved.