将VHDL逻辑向量转换为用户定义的字符串以进行模拟

时间:2018-03-03 05:51:39

标签: vhdl fpga lattice-diamond active-hdl

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

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

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;

这实际上运作得很好,并且可能适合我想要做的大多数事情:

enter image description here

主要的问题是我遇到了字符串常量,所以对于像mov acc,x这样的更复杂的东西以及真实世界设计所能提供的所有其他变体来说,它太不切实际了。

有没有办法构建这样的动态模拟标识符?或者它是高密度脂蛋白的基本限制?

2 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:0)

为了后代,应@B的要求。走,这是我之前的答案:

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

考虑一个具有相关名称的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;

尽管您有一套完整的套件,但它要简单一些。考虑一个名称为“ idle,start,running,done”的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);