На первый взгляд можно ожидать, что приведенный ниже исходный код VHDL будет вести себя как регистр сдвига. В этом д со временем будет
"UUUU0", "UUU00", "UU000", "U0000", "00000", ....
но вместо этого это всегда U
после пяти (или более) последовательных тактов.
Почему это?
Этот код на самом деле является значительно упрощенной версией гораздо более сложной симуляции. Но это демонстрирует симптомы, которые я вижу.
Это демонстрирует этот интересный и неожиданный результат во время симуляции под ModelSim и ActiveHDL. Я не пробовал другие симуляторы и (во-вторых, объяснение причины) хотел бы знать, действуют ли другие так же.
Чтобы правильно ответить на этот вопрос, вы должны понимать, что:
- Я знаю, что это не лучший способ реализации регистра сдвига
- Я знаю, что для синтеза RTL это должно иметь сброс.
- Я знаю, что массив std_logic является std_logic_vector.
- Я знаю оператора агрегации
&
.
Что я также нашел:
- Если назначение
temp(0)<='0';
перемещается внутри процесса, оно работает. - Если цикл развернут (см. Закомментированный код), он работает.
Я еще раз повторю, что это очень упрощенная версия гораздо более сложной конструкции (для конвейерного процессора), сконфигурированная так, чтобы просто показывать неожиданные результаты моделирования. Фактические типы сигналов являются просто упрощением. По этой причине вы должны рассмотреть свои ответы с кодом в форме, как есть.
Я предполагаю, что оптимизатор механизма моделирования VHDL по ошибке (или, возможно, согласно спецификации) не утруждает себя выполнением выражений внутри цикла, так как нет никаких сигналов вне изменения, хотя я могу опровергнуть это, поместив развернутый цикл в цикл.
Поэтому я ожидаю, что ответ на этот вопрос больше связан со стандартами VHDL-моделирования неявного VHDL-синтаксиса и тем, как механизмы VHDL-моделирования выполняют свою оптимизацию, а не в том случае, если приведенный пример кода является лучшим способом сделать что-то или нет.
А теперь код, который я моделирую:
library ieee;
use ieee.std_logic_1164.all;
entity test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end entity;
architecture example of test_simple is
type t_temp is array(4 downto 0) of std_logic;
signal temp : t_temp;
begin
temp(0) <= '0';
p : process (clk)
begin
if rising_edge(clk) then
for i in 1 to 4 loop
temp(i) <= temp(i - 1);
end loop;
--temp(1) <= temp(0);
--temp(2) <= temp(1);
--temp(3) <= temp(2);
--temp(4) <= temp(3);
end if;
end process p;
q <= temp(4);
end architecture;
И испытательный стенд:
library ieee;
use ieee.std_logic_1164.all;
entity Bench is
end entity;
architecture tb of bench is
component test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end component;
signal clk:std_logic:='0';
signal q:std_logic;
signal rst:std_logic;
constant freq:real:=100.0e3;
begin
clk<=not clk after 0.5 sec / freq;
TB:process
begin
rst<='1';
wait for 10 us;
rst<='0';
wait for 100 us;
wait;
end process;
--Note: rst is not connected
UUT:test_simple port map (clk=>clk,q=>q) ;
end architecture;
temp(0)
потому что нет никаких «событий», связанных с литеральной константой. Помещение назначения внутри process
создает связь с событиями часов, которая заставляет его работать. Интересно, было бы добавление after
пункта к назначению потенциальным обходным путем.