FPGA spartan 3 - X mod 3 внутри комбинаторного процесса без часов

Я работаю над проектом, одна часть которого вращается вокруг поиска X mod 3 с помощью FPGA spartan 3 (Xilinx) внутри комбинаторного процесса. на самом деле в этом проекте есть несколько других модулей, которые являются последовательными перед этим модулем ALU. но внутри модуля ALU не разрешено использовать последовательный процесс. поэтому я попытался использовать один метод из здесь:

Вот простой способ сделать это своими руками. Поскольку 1 = 22 по модулю 3, мы получаем 1 = 22n по модулю 3 для каждого положительного целого числа. Кроме того, 2 = 22n+1 mod 3. Следовательно, можно определить, делится ли целое число на 3, подсчитав биты 1 в нечетных битовых позициях, умножить это число на 2, добавить количество битов 1 в четных битовых позициях, добавить их к результат и проверить, делится ли результат на 3.

Пример: 5710=1110012. 2 бита в нечетных позициях и 2 бита в четных позициях. 2*2 + 2 = 6 делится на 3. Следовательно, 57 делится на 3.

Я разместил свои коды там. проблема в том, что после объединения нечетных и четных битов в двух разных сигналах:

        mod_un_t1 <= A(6) & A(4)& A(2) & A(0);
        mod_un_t2 <= A(7) & A(5)& A(3) & A(1);

Я теряю все данные, и после этого оператор if не работает. Я смоделировал свой код на тестовом стенде. но он всегда дает:

result <= "00000000";

Я проверил это и обнаружил, что после этой конкатенации данные не будут переданы. Я не могу использовать последовательную сеть и методы прямого и обратного отсчета или метод регистра сдвига, которые все работают с clk и последовательным процессом.

Может ли кто-нибудь помочь мне решить проблему в моем коде, и если у кого-то есть лучший метод или лучший способ реализации, позвольте мне пройти через это нигде !!!

и это мой код:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Use Ieee.std_logic_unsigned.all;

entity ALU is
   port ( A          : in  std_logic_vector (7 downto 0);   -- Input A
          B          : in  std_logic_vector (7 downto 0);   -- Input B
          FN         : in  std_logic_vector (3 downto 0);   -- ALU functions provided by the ALU_Controller (see the lab manual)
          result       : out std_logic_vector (7 downto 0);   -- ALU output (unsigned binary)
           overflow   : out std_logic;                       -- '1' if overflow ocurres, '0' otherwise 
           sign       : out std_logic                        -- '1' if the result is a negative value, '0' otherwise
        );
end ALU;

architecture behavioral of ALU is

signal mod_un_t1: std_logic_vector (3 downto 0);
signal mod_un_t2: std_logic_vector (3 downto 0);
signal mod_un_t3: std_logic_vector (3 downto 0);
signal mod_un_t4: std_logic_vector (3 downto 0);
signal mod_unsigned: std_logic_vector (3 downto 0);

signal mod_si_t1: std_logic_vector (3 downto 0);
signal mod_si_t2: std_logic_vector (3 downto 0);
signal mod_si_t3: std_logic_vector (3 downto 0);
signal mod_si_t4: std_logic_vector (3 downto 0);
signal mod_signed: std_logic_vector (3 downto 0);

begin
   process ( FN, A, B , result_tmp)
   begin
        result <= (others => '0');
        mod_un_t1 <= (others => '0');
        mod_un_t2 <= (others => '0');
        mod_un_t3 <= (others => '0');
        mod_un_t4 <= (others => '0');
        mod_unsigned <= (others => '0');
        mod_si_t1 <= (others => '0');
        mod_si_t2 <= (others => '0');
        mod_si_t3 <= (others => '0');
        mod_si_t4 <= (others => '0');
        mod_signed <= (others => '0');

        if (FN = "0100") then -- Unsigned (A) mod 3
            mod_un_t1 <= A(6) & A(4)& A(2) & A(0);
            mod_un_t2 <= A(7) & A(5)& A(3) & A(1);

            if(mod_un_t1= "1111") then
              mod_un_t3 <= "1000";
            elsif(mod_un_t1 = "1110" or mod_un_t1 = "1101" or  mod_un_t1 = "1011" or mod_un_t1 = "0111") then
                mod_un_t3 <= "0110";
            elsif(mod_un_t1 = "1100" or mod_un_t1 = "1010" or mod_un_t1 = "1001" or mod_un_t1 = "0110" or mod_un_t1 = "0101" or mod_un_t1 = "0011") then
                mod_un_t3 <= "0100";
            elsif(mod_un_t1 = "0001" or mod_un_t1 = "0010" or mod_un_t1 = "0100" or mod_un_t1 = "1000") then
                mod_un_t3 <= "0010";
            elsif (mod_un_t1 = "0000") then
                mod_un_t3 <= "0000";
            end if;

            if (mod_un_t2 = "1111") then
                mod_un_t4 <= "0100";
            elsif (mod_un_t2 = "1110" or mod_un_t2 = "1101" or mod_un_t2 = "1011" or mod_un_t2 = "0111") then
                mod_un_t4 <= "0011";
            elsif(mod_un_t2 = "1100" or mod_un_t2 = "1010" or mod_un_t2 = "1001" or mod_un_t2 = "0110" or mod_un_t2 = "0101" or mod_un_t2 = "0011") then
                mod_un_t4 <= "0010";
            elsif(mod_un_t2 = "0001" or mod_un_t2 = "0010" or mod_un_t2 = "0100" or mod_un_t2 = "1000") then
                mod_un_t4 <= "0001";
            elsif(mod_un_t2 = "0000") then
                mod_un_t4 <= "0000";
            end if;

            mod_unsigned <= mod_un_t3 + mod_un_t4;

            if  (mod_unsigned = "0010" or  mod_unsigned = "0101" or mod_unsigned ="0111" or mod_unsigned = "1010") then
                result <= "00000001";
            elsif (mod_unsigned = "0001" or mod_unsigned = "0100" or mod_unsigned = "1000" or mod_unsigned = "1011") then
                result <= "00000010";
            elsif (mod_unsigned = "0000" or mod_unsigned = "0011" or mod_unsigned = "0110" or mod_unsigned = "1001") then
                result <= "00000000";
            end if;
        end if;

   end process;
end behavioral;

person manpmanp    schedule 05.10.2014    source источник


Ответы (1)


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

Кандидатами на переменные являются:

signal mod_un_t1: std_logic_vector (3 downto 0);
signal mod_un_t2: std_logic_vector (3 downto 0);
signal mod_un_t3: std_logic_vector (3 downto 0);
signal mod_un_t4: std_logic_vector (3 downto 0);
signal mod_unsigned: std_logic_vector (3 downto 0);

signal mod_si_t1: std_logic_vector (3 downto 0);
signal mod_si_t2: std_logic_vector (3 downto 0);
signal mod_si_t3: std_logic_vector (3 downto 0);
signal mod_si_t4: std_logic_vector (3 downto 0);
signal mod_signed: std_logic_vector (3 downto 0);

Эти объявления могут быть изменены на переменную класса объекта и перемещены в процесс (до begin). Назначение сигналов для них (<=) будет переключено на назначение переменных (:=).

Вы можете просто поместить те, которые отображаются справа от назначения в списке конфиденциальности, но это вызовет дополнительные дельта-циклы.

Если есть причина сохранять их сигналы, вы можете рассмотреть возможность разбиения вашего процесса на несколько процессов и/или других параллельных операторов.

В списке конфиденциальности есть result_tmp, у которого нет объявления или назначения в коде, который вы показали.

... не могли бы вы также привести краткий пример разделения процесса на несколько процессов и/или других параллельных операторов?

Aarchitecture foo of ALU is

    signal mod_un_t1: std_logic_vector (3 downto 0);
    signal mod_un_t2: std_logic_vector (3 downto 0);
    signal mod_un_t3: std_logic_vector (3 downto 0);
    signal mod_un_t4: std_logic_vector (3 downto 0);
    signal mod_unsigned: std_logic_vector (3 downto 0);

    signal mod_si_t1: std_logic_vector (3 downto 0);
    signal mod_si_t2: std_logic_vector (3 downto 0);
    signal mod_si_t3: std_logic_vector (3 downto 0);
    signal mod_si_t4: std_logic_vector (3 downto 0);
    signal mod_signed: std_logic_vector (3 downto 0);
    -- dummy 
    signal result_tmp: std_logic_vector(7 downto 0);

begin

    -- Concurrent signal assignments - these are just wires
    mod_un_t1 <= A(6) & A(4)& A(2) & A(0);
    mod_un_t2 <= A(7) & A(5)& A(3) & A(1); 

UNPROC1:
    process (FN, mod_un_t1)
    begin
    if FN = "0100" then
        case mod_un_t1 is
            when "0000" =>
                mod_un_t3 <= "0000";
            when "0001" | "0010" | "0100" | "1000" =>
                mod_un_t3 <= "0010";
            when "1100" | "1010" | "1001" | "0110" =>
                mod_un_t3 <= "0100";
            when "1110" | "1101" | "1011" | "0111" =>
                mod_un_t3 <= "0100";
            when others =>
            end case;
    else
    --
    end if;
end process;

UNPROC2:
    process (FN, mod_un_t2)
    begin
    if FN = "0100" then 
        if mod_un_t2 = "1111" then
            mod_un_t4 <= "0100";
        elsif mod_un_t2 = "1110" or mod_un_t2 = "1101" or mod_un_t2 = "1011" or mod_un_t2 = "0111" then
            mod_un_t4 <= "0011";
        elsif mod_un_t2 = "1100" or mod_un_t2 = "1010" or mod_un_t2 = "1001" or mod_un_t2 = "0110" or mod_un_t2 = "0101" or mod_un_t2 = "0011" then
            mod_un_t4 <= "0010";
        elsif mod_un_t2 = "0001" or mod_un_t2 = "0010" or mod_un_t2 = "0100" or mod_un_t2 = "1000" then
            mod_un_t4 <= "0001";
        elsif mod_un_t2 = "0000" then
            mod_un_t4 <= "0000";
        end if;
    else
        --
    end if;
end process;

ALU_PROC:  -- keep all the arithemetic operations in one process
    process (FN, mod_un_t3, mod_un_t4)
    begin
        if FN = "0100" then 
             mod_unsigned <= mod_un_t3 + mod_un_t4;
        else 

        end if;
    end process;

OUT_PROC: -- keep all the result assignment in one process
process (FN, mod_unsigned)
    begin
        if FN = "0100" then 
            if  mod_unsigned = "0010" or  mod_unsigned = "0101" or mod_unsigned ="0111" or mod_unsigned = "1010" then
                result <= "00000001";
            elsif mod_unsigned = "0001" or mod_unsigned = "0100" or mod_unsigned = "1000" or mod_unsigned = "1011" then
                result <= "00000010";
            elsif mod_unsigned = "0000" or mod_unsigned = "0011" or mod_unsigned = "0110" or mod_unsigned = "1001" then
                result <= "00000000";
            else 
            --
            end if;
        end if;
    end process;

end architecture foo;
person Community    schedule 06.10.2014
comment
@ Дэвид Кунц, Ваш ответ дал именно тот результат, который мне нужен. Большое спасибо. Это была действительно большая помощь. Кстати, result_tmp предназначен для другой арифметической операции в моем разработанном ALU. - person manpmanp; 06.10.2014
comment
@ Дэвид Кунц, не могли бы вы также привести краткий пример разделения процесса на несколько процессов и/или других параллельных операторов?? - person manpmanp; 06.10.2014
comment
Обратите внимание, что у вас нет полного охвата двоичных значений в условиях оператора if, что означает предполагаемые защелки. - person ; 06.10.2014
comment
Что мне делать? Вы имеете в виду, что мне лучше выбрать, когда/случай или когда/выбрать вместо этого, или я должен присвоить фиктивное значение моему результату и добавить еще в конце всех операторов if ?? - person manpmanp; 06.10.2014