4

我正在使用 active-hdl 来模拟我的 FPGA 设计,我想知道是否可以使用动态生成的字符串来表示我在模拟器中的信号。例如,假设我有一个包含操作码的 4 位 std_logic_vector,我希望模拟器显示操作码字符串“nop”、“add”、“sub”等,而不是向量值。

起初我尝试声明自定义枚举类型,但很快发现您无法选择单个元素的值。我的下一个解决方案是仅将枚举用于模拟显示并使用翻译函数进行转换:

type op_code_type is (nop, add, sub, unknown); -- not in order
signal op_code_str: op_code_type;
signal op_code: std_logic_vector(3 downto 0);

function to_string(op_code : std_logic_vector(3 downto 0))
return op_code_type is
begin
    case op_code is
        when "0000" => return nop;
        when "0010" => return add;
        when "0011" => return sub;
        when others => return unknown;
    end case;
end to_string;

begin

    ----- testbench -----
    process 
    begin
        op_code <= "0000";
        wait for 1ns;
        op_code <= "0001";
        wait for 1ns;
        op_code <= "0010";
        wait for 1ns;
        op_code <= "0011";
        wait for 1ns;
    end process;

    op_code_str <= to_string(op_code);

end architecture;

这实际上效果很好,并且对于我想做的大多数事情来说可能已经足够了:

在此处输入图像描述

但主要问题是我被字符串常量困住了,所以对于更复杂的东西mov acc,x以及现实世界设计中的所有其他变体来说,这太不切实际了。

有没有办法像这样构造动态模拟标识符?还是它是 HDL 的基本限制?

4

2 回答 2

0

在 Modelsim 中,您可以使用虚拟类型和函数。例如,考虑以下向量:

signal opcode : std_logic_vector(2 downto 0);

然后您可以在 Modelsim 命令行中定义一个虚拟类型,例如:

virtual type {{0 nop} {1 load} {2 store} {3 invalid}} opcode_type

这是一种只有模拟器知道的类型。然后可以根据这个类型创建一个虚拟信号来转换向量,比如:

virtual function {(opcode_type)opcode} opcode_str

然后 wave opcode_str,它会给你一个自定义格式的字符串..

我不知道你是否可以用 Active-HDL 做同样的事情。

现在,对于动态执行,唯一的可能是返回的字符串是由 TCL 函数定义的,例如:

# TCL code to read a file, or otherwise dynamically generate opcodes
# returning the appropriately formatted virtual type
proc generate_opcode_type {} {
  ...
}

virtual type [generate_opcode_type] opcode_type
virtual function {(opcode_type)opcode} opcode_str

然后挥手opcode_str

于 2019-06-18T15:50:54.907 回答
0

为了后代,并应@B的要求。去吧,这是我之前的回答:

@Paebbels 有它。我们经常使用它,尤其是在进行布局布线后模拟以将状态代码转换为等效的枚举类型时。因此,为了完整起见,我将向您展示我们是如何做到的。下面的示例考虑了使用二进制编码的情况。如果尝试从灰色或单热转换,情况会有所不同。对于 one-hot,我倾向于使用一个函数。

考虑一个具有关联名称的 3 位向量:

|-----------|----------|
| 000       |  Idle    |
| 001       |  Start   |
| 010       |  Running |
| 011       |  Paused  |
| 100       |  Done    |
| 101 - 111 | Invalid  |
|-----------|----------|

因此,如果您有信号,例如:

signal opcode : std_logic_vector(2 downto 0);

然后你想转换为枚举类型,它会清晰地显示在你的波形查看器中。首先,创建枚举类型和关联信号:

type opcode_names is (idle, start, running, paused, done, invalid);
signal opcode_name : opcode_names;

然后很简单with/select

with to_integer(unsigned(opcode)) select
  opcode_name <= idle when 0,
                 start when 1,
                 running when 2,
                 paused when 3,
                 done when 4,
                 invalid when others;

虽然如果你有一套完整的,它会更简单一些。考虑一个名称为“空闲、启动、运行、完成”的 2 位向量。

    type opcode_names is (idle, start, running, done);
    signal opcode_name : opcode_names;

    ...

    opcode_name <= opcode_names'image(to_integer(unsigned(opcode));

对于具有不寻常的、不连续的值的更复杂的向量,我通常使用一个函数,例如:

signal opcode : std_logic_vector(31 downto 0);

type opcode_names is (idle, start, running1, running2, paused, done, invalid);
signal opcode_name : opcode_names;

function get_opcode_name(opcode : in std_logic_vector) return opcode_names is
  variable ret : opcode_names;
begin
  case to_integer(unsigned(opcode)) is
    when 0 =>
      ret := idle;
    when 13 =>
      ret := start;
    when 87 =>
      ret := running1;
    when 131 =>
      ret := running2;
    when 761 =>
      ret := paused;
    when 3213 =>
      ret := done;
    when others =>
      ret := invalid;
  end case;

  return ret;
end function get_opcode_name;

...

opcode_name <= get_opcode_name(opcode);
于 2019-06-19T04:36:09.547 回答