加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 动机
    • 失败原因
    • 解决办法
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

通过字符串访问generate模块内部的变量

2020/12/02
275
阅读需 2 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

动机

今天一个朋友问了这样一个问题

失败原因

首先介绍一下generate的用法,generate用于减少 verilog 的重复语句,批量进行操作。

虽然 0202 年了,综合工具对于for的支持已经很好了,但是使用generate进行 for 循环,不仅可以实现普通的变量赋值,还可以批量生成assign或者always语句,它的作用实际上和宏定义是一样的,直接将代码展开。

举个例子,我有两个数组reg [7:0] a [7:0]reg [7:0] b [7:0],我需要把他们对应元素相乘,那么可以这么做

genvar i;

reg [ 7:0] a [7:0];
reg [ 7:0] b [7:0];
wire [15:0] c [7:0];

generate
  for(i;i<8;i++) begin
    assign c[i] = a[i]*b[i];
  end
endgenerate

这种写法是完全等价于下面这种写法的

genvar i;

reg [ 7:0] a [7:0];
reg [ 7:0] b [7:0];
wire [15:0] c [7:0];

assign c[0] = a[0]*b[0];
assign c[1] = a[1]*b[1];
assign c[2] = a[2]*b[2];
assign c[3] = a[3]*b[3];
assign c[4] = a[4]*b[4];
assign c[5] = a[5]*b[5];
assign c[6] = a[6]*b[6];
assign c[7] = a[7]*b[7];

如果在代码并不多的情况下,利用插件,例如sublimeinsert num,也可以快速实现

sublime

同样的,generate也可以批量进行例化,例如

module adder(
  input clk,rst_n,
  input  [2:0] a,b,
  output [3:0] c
);

  logic [3:0] c_f,c_ff;

  always_ff @(posedge clk or negedge rst_n) begin : proc_adder
    if(~rst_n) begin
      c_f   <= '0;
      c_ff  <= '0;
    end else begin
      c_f   <= a+b;
      c_ff  <= c_f;
    end
  end

  assign c=c_ff;


endmodule


module test (
  input clk,    // Clock
  input rst_n,  // Asynchronous reset active low
  input  [2:0] a [3:0],
  input  [2:0] b [3:0],
  output [3:0] c [3:0]
);

genvar i;

generate

  for (i = 0; i < 4; i++) begin
  adder i_adder (.clk(clk), .rst_n(rst_n), .a(a[i]), .b(b[i]), .c(c[i]));
  end

endgenerate

endmodule

如果在仿真器中查看模块名,模块会被自动进行编号

通过路径i_test.genblk1[3].i_adder.c_f就能访问到对应的变量

//  Module: tb
//
module tb();

  
  logic clk,rst_n;
  logic [2:0] a [3:0];
  logic [2:0] b [3:0];
  logic [3:0] c [3:0];

  test i_test (.clk(clk), .rst_n(rst_n), .a(a), .b(b), .c(c));
  
  initial begin
    clk <= '0;
    forever begin
      #5 clk <= ~clk;
    end
  end

  initial begin
    rst_n <= '0;
    repeat(5) @(posedge clk);
    rst_n <= '1;
  end

  initial begin
    a <= '{4{'0}};
    b <= '{4{'0}};
    @(posedge clk iff rst_n);
    for (int i = 0; i<4 ; i++ ) begin
      a[i] <= i;
      b[i] <= i;
    end
    repeat(5) @(posedge clk);
    $display("c_f[3]:%h",i_test.genblk1[3].i_adder.c_f);
    @(posedge clk);
    $stop();
  end

endmodule: tb

可以看到访问成功

如果通过文章开头说的方式,就会出现错误

    for (int i = 0; i<4 ; i++ ) begin
      $display("c_f[%0d]:%h",i_test.genblk1[i].i_adder.c_f);
    end

其实主要原因是,这个genblk1根本就不是一个数组,也就无法通过这种索引的方法访问到对应变量

解决办法

目前我能想到的方法就是通过uvm提供的函数uvm_hdl_read实现,他在底层通过dpi从外部访问变量,因此可以通过字符串访问到对应的变量。

uvm_hdl_read的原型是

import "DPI-C" context function int uvm_hdl_read(
   		string 	path,
   	output 	uvm_hdl_data_t 	value
)

返回的uvm_hdl_data_t在 uvm 中的定义是

parameter int UVM_HDL_MAX_WIDTH = `UVM_HDL_MAX_WIDTH;

typedef  logic [UVM_HDL_MAX_WIDTH-1:0] uvm_hdl_data_t;

因此,我们可以通过下面的代码访问genblk1中的变量

    for (int i = 0; i<4 ; i++ ) begin
      uvm_hdl_read($sformatf("tb.i_test.genblk1[%0d].i_adder.c_f",i),temp)
      $display("c_f[%0d]:%2h",i,temp);
    end

有几个注意事项

  1. 在描述路径时,要传入绝对路径,不能使用相对路径在描述路径时,使用%0d,否则字符串会与真实路径不匹配

可以看到访问成功

uvm 读取

下面给出完整代码

//  Module: tb
//
module tb();
  import uvm_pkg::*;
  `include "uvm_macros.svh"
  
  logic clk,rst_n;
  logic [2:0] a [3:0];
  logic [2:0] b [3:0];
  logic [3:0] c [3:0];

  test i_test (.clk(clk), .rst_n(rst_n), .a(a), .b(b), .c(c));
  
  initial begin
    clk <= '0;
    forever begin
      #5 clk <= ~clk;
    end
  end

  initial begin
    rst_n <= '0;
    repeat(5) @(posedge clk);
    rst_n <= '1;
  end

  initial begin
    uvm_hdl_data_t temp;
    a <= '{4{'0}};
    b <= '{4{'0}};
    @(posedge clk iff rst_n);
    for (int i = 0; i<4 ; i++ ) begin
      a[i] <= i;
      b[i] <= i;
    end
    repeat(5) @(posedge clk);
    $display("c_f[3]:%h",i_test.genblk1[3].i_adder.c_f);
    for (int i = 0; i<4 ; i++ ) begin
      uvm_hdl_read($sformatf("tb.i_test.genblk1[%0d].i_adder.c_f",i),temp)
      $display("c_f[%0d]:%2h",i,temp);
    end
    @(posedge clk);
    $stop();
  end

endmodule: tb

当然,uvm 不仅提供了读取,还提供了全家桶服务,force deposit一应俱全

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
XC2C384-10FTG256I 1 AMD Xilinx Flash PLD, 10ns, 384-Cell, CMOS, PBGA256, 17 X 17 MM, 1 MM PITCH, LEAD FREE, FTBGA-256
$596.21 查看
10M50DAF256I7G 1 Intel Corporation Field Programmable Gate Array, 50000-Cell, CMOS, PBGA256, 17 X 17 MM, 1 MM PITCH, ROHS COMPLIANT, FBGA-256

ECAD模型

下载ECAD模型
$166.08 查看
5CSTFD6D5F31I7N 1 Altera Corporation Field Programmable Gate Array, 110000-Cell, CMOS, PBGA896, ROHS COMPLIANT, FBGA-896

ECAD模型

下载ECAD模型
$2992.14 查看

相关推荐

电子产业图谱