Преобразование логических векторов 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);