Внутренний сигнал VHDL для изменения выхода - не работает?

У меня есть этот модуль PC, очень простой (код в конце). Сначала я генерирую некоторый входной сигнал port_int, а в конце процесса говорю pc_out <= port_int. Моя цель состоит в том, чтобы либо увеличить, либо добавить, либо вычесть из ПК, в зависимости от входных сигналов.

В моделировании внутренний сигнал port_int работает нормально, а pc_out — нет. Почему это происходит? Посмотрите на симуляцию: sim

Посмотрите, как port_int меняется как надо, а pc_out опаздывает. Позже в симуляции pc_out становится еще хуже, меняясь нерегулярно, даже не просто опаздывая.

Что я делаю неправильно? Есть ли другой способ изменить pc_out? Потому что вы не можете изменить сигналы out, а мне сказали, что inout — это очень плохая практика.

Вот код:

entity PC is
    Port ( clk : in STD_LOGIC; 
       enable : in STD_LOGIC; 
       reset : in STD_LOGIC;
       pc_out : out  STD_LOGIC_VECTOR (3 downto 0);
       data : in  STD_LOGIC_VECTOR (3 downto 0);    -- jump value
       zero : in  STD_LOGIC;    -- jump condition
       jmp_en : in  STD_LOGIC;      -- jump enable
       jmp_dir : in STD_LOGIC;  -- jump direction
       ctrl_en : out STD_LOGIC);   -- output signal
end PC;

architecture Behavioral of PC is

type state_type is (s0, s1, s2, s3);
signal reg_state, next_state : state_type;

signal port_int : std_logic_vector(3 downto 0);

begin

state_transition: process(clk, reset)
begin
    if (reset = '1') then
        reg_state <= s0;
    elsif(rising_edge(clk)) then
        reg_state <= next_state;
    end if;
end process;

next_state_logic: process(reg_state, enable)
begin
    case reg_state is
        when s0 =>
            if(enable = '1') then
                next_state <= s2;
            else
                next_state <= s1;
            end if;

        when s1 =>
            if(enable = '1') then
                next_state <= s2;
            else
                next_state <= s1;
            end if;

        when s2 =>
            next_state <= s3;

        when s3 =>
            if(enable = '1') then
                next_state <= s2;
            else
                next_state <= s1;
            end if;
    end case;
end process;

output_logic: process(reg_state, zero, jmp_en, jmp_dir, data)
begin
    case reg_state is
        when s0 =>
            pc_out <= "0000";
            port_int <= "0000";
            ctrl_en <= '0';

        when s1 =>
            ctrl_en <= '0';

        when s2 =>
            if(zero = '1' and jmp_en = '1' and jmp_dir = '1')then
                port_int <= port_int + data;    -- jump forward
            elsif(zero = '1' and jmp_en = '1' and jmp_dir = '0')then
                port_int <= port_int - data;    -- jump backward
            else    -- nije ispunjen uslov skoka
                port_int <= port_int + '1'; -- increment PC
            end if;
            pc_out <= port_int;

        when s3 =>
            ctrl_en <= '1';
    end case;
end process;

end Behavioral;

ИЗМЕНИТЬ:

Когда я импортирую модуль в целый процессор, происходит следующее: sim3тот же сигнал pc_out ведет себя странно, и все входы одинаковые. Я использую сигнал pc_out только в одном месте, для выбора памяти. Почему не ведет себя нормально? Что могло быть причиной этого?


person Vidak    schedule 18.12.2013    source источник


Ответы (2)


Второй процесс (output_logic: process), который вычисляет выходные значения, имеет некоторые проблемы.

Во-первых, напомним, что он реализует комбинационную схему (следовательно, без памяти), поэтому уравнения типа port_int ‹= port_int + data могут быть вычислены только в том случае, если значение port_int где-то хранится. Кстати, после исправления кода вы можете отказаться от внутреннего сигнала port_int и напрямую использовать pc_out.

Во-вторых, поскольку этот процесс представляет собой комбинационную схему, необходимо указать его полную таблицу истинности; в противном случае защелки будут выведены. Обратите внимание, например, что в состоянии s1 указано только значение ctrl_en. Вы должны либо указать все выходные значения (один и тот же список) во всех состояниях, либо, что то же самое, вы можете составить список выходных значений перед операторами case, чтобы компилятор использовал их как значения по умолчанию, когда значения явно не объявляются.

person VAP    schedule 23.12.2013

Если я понимаю, что вы пытаетесь сделать правильно, вам просто нужен один оператор вне блоков process:

pc_out <= port_int;

Уберите все другие операторы, присваивающие что-то pc_out из вашего дизайна. Я думаю, вас сбивает с толку оператор <=, который ждет следующей дельты моделирования, чтобы фактически обновить драйвер сигнала.

person godel9    schedule 18.12.2013
comment
Еще один момент, когда я подключаю этот модуль к вышестоящему, pc_out не меняется как надо. Все входные сигналы остаются прежними, и все же pc_out переходит от 0000 к 0100 вместо 0001. Я использую pc_out в другом модуле в качестве входных данных, может ли это повлиять на это? Я ничего не делаю с этим, кроме простого чтения. - person Vidak; 18.12.2013
comment
@Vidak Трудно сказать ... Ты смешиваешь TO и DOWNTO? Это может привести к переворачиванию битов. - person godel9; 18.12.2013
comment
Я отредактировал пост, чтобы показать вам симуляцию. Я никогда не использую to, только downto. Я совсем запутался, я не понимаю, почему и как может измениться вывод, когда все входные сигналы одинаковы. - person Vidak; 18.12.2013
comment
@Vidak Я не могу сказать по твоему обновленному сообщению. Я предполагаю, что входы как-то не совпадают. Попробуйте отслеживать все сигналы этого модуля и ищите что-нибудь неожиданное. - person godel9; 18.12.2013