【问题标题】:Converting VHDL logic vectors to user-defined strings for simulation将 VHDL 逻辑向量转换为用户定义的字符串以进行仿真
【发布时间】:2018-08-11 09:04:12
【问题描述】:

我正在使用 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 的基本限制?

【问题讨论】:

  • 有可能。您当前的思维方式的问题是,您所说的“字符串”不是字符串,而是枚举类型。此类型仅限于定义的值。您可以尝试使用多个函数构造一个(连接的)字符串。但是,您应该记住 vhdl 不支持具有动态长度的数组对象。
  • Active-HDL 将通过枚举文字(例如nop)显示枚举类型的对象(例如信号)。您可以使用属性'val'pos 将枚举文字转换为整数,反之亦然。您还可以使用'image'value 将这些文字转换为字符串,反之亦然。一般来说,您应该将操作码建模为枚举而不是 std_logic_vector。
  • GTKWave 可以使用翻译过滤器、文件中的表格或外部进程(对反汇编程序有用)。用编程语言解决仪表问题。在 VHDL 中获取可变长度字符串的方法是使用访问类型和分配器(例如 textio),并且不会通过没有固定长度字符串对象(静态声明)的波形转储文件传达字符串值。
  • 枚举类型 'LEFT 的标量位置值为 0。为标量值的二进制范围提供所有枚举是确定性的。 type op_code_type is (nop, unk1, add, sub, unk4, unk5, unk6, unk7, unk8, unk9, unk10, unk11, unk12, unk13, unk14, unk15); op_code_type'IMAGE(op_code_type'VAL(to_integer(unsigned(op_code)))) 访问的字符串值。注意有三种不同的字符串长度。
  • 我不确定是否使用 SignalTap,但是在定义类型时使用 ModelSim,例如枚举 CPU 正在经历的状态(即 FETCH、DECODE...),是能够向您显示状态的名称,而不是符合状态的位。

标签: vhdl fpga lattice-diamond active-hdl


【解决方案1】:

在 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

然后挥动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

【讨论】:

  • 感谢您的回答,但除非我遗漏了什么,否则这基本上与我在问题中发布的内容相同?您只是先转换为 int 并在 case 语句中使用它。我的问题是是否有任何方法可以动态控制信号或总线在模拟器中的显示方式......可能有数千种操作代码变体,因此对每一个都进行硬编码不是一种选择。跨度>
  • 你是对的。我快速通读了一遍,然后阅读了下面的 cmets。对不起。我可以删除这个答案。在 Modelsim 中,您可以自定义显示类型。我无法访问 Active-HDL,所以我不能在那里告诉你。如果你喜欢,我可以以 Modelsim 为例。虽然您无法选择单个元素的值,但位置是可预测的。所以在我的例子中,opcode_names'pos(x) 是可以预测的。
  • 请不要删除你的答案,即使“不完整”也很有趣!
【解决方案2】:

为了后代,应@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);

【讨论】:

    猜你喜欢
    • 2013-03-02
    • 1970-01-01
    • 2020-01-14
    • 2011-06-15
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    相关资源
    最近更新 更多