Преобразование логических векторов VHDL в определяемые пользователем строки для моделирования

Я использую 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 и все другие варианты, которые есть у реального дизайна.

Есть ли способы создать идентификаторы динамического моделирования, как это? Или это фундаментальное ограничение ЛПВП?

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,

Для потомков и по просьбе @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;

Хотя, если у вас есть полный набор, это немного проще. Рассмотрим 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);
Другие вопросы по тегам