Увеличение внутреннего сигнала - PullRequest
0 голосов
/ 30 октября 2011

Проблема кодирования VHDL :( Здравствуйте! Я уже некоторое время работаю над этой проблемой. У меня такое ощущение, что это начальная проблема, которую я не совсем понимаю.

- Я получаю доступ к внутреннемупамяти, 4 строки по 2-битные числа в каждой. Я смог нормально читать и записывать в память, моя проблема заключается в увеличении адреса, по которому я буду хранить следующий набор данных.

- Мой блокуправляется автоматом FSM с тремя состояниями: бездействующий, тростниковый и обрядовый. У меня есть три внутренних сигнала, addressin: указатель на адрес, который будет считан следующим, addressout: указатель на адрес, который будет записан следующим, и addressall, адрес, которыйперейдет в реальную стадию памяти.

    PROCESS (y)
    BEGIN
    CASE y IS
    WHEN I=>
    enable<='0';

    WHEN reed=>
    enable<='0';
    IF (addressin="00" OR addressin="01" OR addressin="10") THEN

        addressin<=addressin+"01";
    ELSE
        addressin<="00";
    END IF;
    addressall<=addressin;

    WHEN rite=>
    enable<='1';
    IF (addressout="00" OR addressout="01" OR addressout="10") THEN
        addressout<=addressout+1;
    ELSE
        addressout<="00";
    END IF;
    addressall<=addressout;

    END CASE;
END PROCESS;    

memorystage: memory PORT MAP (clck, NOT reset, NOT enable, addressall, datain, dataout);    

Процесс активируется при изменении y (изменение состояний в коде не видно.) Моя проблема в том, что адрес изменится, адрес изменится,и то же самое произойдет с адресом ... Но никогда по одному и никогда в какой-либо последовательной логике ... (У меня есть это в шестнадцатеричном отображении, чтобы увидеть) Например, я получу для addressin: 3 31 0 3 0 3 0 2 0 2 1 0 .... то же самое с двумя другими адресными сигналами.Понятия не имею, что я делаю не так.Это только часть более крупного проекта, поэтому я решил использовать его самостоятельно.:( Что я делаю не так? Спасибо. -Дженн

Ответы [ 3 ]

1 голос
/ 30 октября 2011

Я думаю, что вы стали жертвой правил обновления сигналов VHDL ( очень хорошо определено , но часто сбивает с толку новичков).См. Также этот вопрос .. Когда сигналы назначаются в VHDL?

Сигнал обновляется только в конце процесса (или когда происходит wait, но мы будемоставьте эту опцию сейчас!)


IF (addressin="00" OR addressin="01" OR addressin="10") THEN
    addressin<=addressin+"01";
ELSE
    addressin<="00";
END IF;
addressall<=addressin;

addressall получит предыдущее значение addressin, а не значение, которое вы только что установили какеще не был обновлен.

Чтобы получить желаемое поведение, измените addressin на variable в процессе (и вам придется изменить все <= назначения на :=задания).Переменные работают так, как вы хотите - обновления применяются немедленно.

Я почти всегда использую переменные для вещей внутри процесса и оставляю сигналы для связи с другими процессами.

0 голосов
/ 02 ноября 2011

Несколько дополнительных моментов для рассмотрения:

1) Несоответствие в увеличении адресов ввода / вывода: addressin<=addressin+"01"; и addressout<=addressout+1;. Поведение этих назначений будет зависеть от типа сигнала операндов, поэтому эта информация полезна, хотя это может и не быть реальной проблемой.

2) Должно быть относительно безопасно предположить, что любые изменения в адресных сигналах напрямую связаны с включением y, поскольку это единственный сигнал в списке чувствительности этого процесса. Вы проверяли значение y рядом с адресами в средстве просмотра формы сигнала?

3) Пол предложил это, но я просто хочу уточнить, почему вы можете захотеть, чтобы эта схема была «синхронизирована» (синхронно). Без часов в списке чувствительности этот процесс чувствителен только к изменениям y. Поэтому любые элементы памяти, подразумеваемые этим процессом, будут полностью не знать о часах и будут затронуты только изменениями на входе y. Другими словами, чтобы продвинуть указатель чтения, y должен был бы переключить между состояниями idle и reed. Вам нужно будет решить, предназначено ли это или логика должна продвигать указатель чтения каждый такт, когда состояние reed присутствует на y. Может быть нетрадиционным для элемента памяти не получать назначенные часы, потому что часы получают специальную обработку для упрощения статического анализа синхронизации, но это не запрещено языком (не может обещать то же самое для последующих инструментов).

В целом, похоже, у вас есть хорошее представление о том, чего вы пытаетесь достичь, и вы понимаете некоторые нюансы VHDL, поэтому следующим шагом будет дальнейшая изоляция неожиданного поведения. Большее количество кода поможет исключить некоторые потенциальные проблемы, но, возможно, лучший способ одновременно протестировать ваши предположения и предоставить воспроизводимый пример - создать тестовую среду, которая иллюстрирует неожиданное поведение.

Например, вот тестовая среда для проверки синхронизированной копии вашего процесса.

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

Entity test Is
End Entity;

Architecture main of test Is
    Signal enable, clock : std_logic := '0';
    Signal addressin, addressout, addressall : unsigned(0 to 1) := "00";
    Type op_t is (reed, idle, rite);
    Signal y : op_t; 
    Signal done : boolean;
Begin
    clocks: process
    begin
        if not done then
            clock <= not clock;
            wait for 0.5 ns;
        else
            wait;
        end if;
    end process;

    PROCESS (clock, y)
    BEGIN
    if rising_edge(clock) then
    CASE y IS
        WHEN idle=>
            enable<='0';

        WHEN reed=>
            enable<='0';
            IF (addressin="00" OR addressin="01" OR addressin="10") THEN
                addressin<=addressin+1;
            ELSE
                addressin<="00";
            END IF;
            addressall<=addressin;

        WHEN rite=>
            enable<='1';
            IF (addressout="00" OR addressout="01" OR addressout="10") THEN
                addressout<=addressout+1;
            ELSE
                addressout<="00";
            END IF;
            addressall<=addressout;

    END CASE;
    end if;
    END PROCESS;

    main: Process
    Begin
        y <= idle;
        wait for 1 ns;
        y <= reed;
        wait for 1 ns;
        assert addressall = "00";
        wait for 1 ns;
        assert addressall = "01";
        wait for 1 ns;
        assert addressall = "10";
        wait for 1 ns;
        assert addressall = "11";
        y <= idle;
        wait for 1 ns;
        done <= true;
        wait;
    End Process;

End Architecture;
0 голосов
/ 01 ноября 2011

Не уверен, что вы можете использовать синхронный дизайн, но я бросил один вместе.Этот дизайн будет увеличиваться через ваш адресный указатель (addressin, addressout) так же быстро, как обновляются часы, если вы находитесь в состоянии тростника или обряда.

PROCESS (y, clk) BEGIN
    IF rising_edge(clk) then
        enable<='0';
        CASE y IS
            WHEN I=>

            WHEN reed=>
                IF(addressin ="11") then
                    addressin <= "00";
                ELSE
                    addressin <= addressin + 1;
                END IF;

                addressall<=addressin;

            WHEN rite=>
                enable<='1';

                IF(addressout ="11") then
                    addressout <= "00";
                ELSE
                    addressout <= addressin + 1;
                END IF;

                addressall<=addressout;
        END CASE;
    END IF;
END PROCESS;    

memorystage: memory PORT MAP (clck, NOT reset, NOT enable, addressall, datain, dataout); 

Если вы хотите, чтобы он обновлялся только один раз для каждого состояния, измениможет сделать что-то вроде

prev_state : PROCESS (y,clk) BEGIN
    IF rising_edge(clk) then
        ybuff <= y;
    END IF;
END PROCESS;

PROCESS (y, clk) BEGIN
    IF rising_edge(clk) then
        IF (ybuff /= y) then
            enable <= '0';
            CASE y IS 
                ....
                ....

Если вы хотите что-то еще, вам нужно дать нам больше вашего кода.Это немного взломано (поскольку у меня нет вашей логики состояния или сигналов обновления)

Я согласен с Мартином, что ваше текущее обновление addressall не является правильным методом.Как он сказал, вы можете использовать переменные, чтобы исправить это, или если вы действительно хотите сохранить это, вы должны поместить его в отдельный блок процесса, который обновляет адрес, чтобы сделать странность более явной и контролируемой.Прямо сейчас (и с одним обновителем, который я разместил вторым) вы всегда будете на один адрес позади ваших указателей (и на один полный цикл позади вашего конечного автомата)

...