Используя VHDL генерировать оператор в функции

Я хочу использовать операторы generate, но в моем коде есть операторы case, которые принимают только последовательные операторы.

Тогда я подумал, что буду использовать его в пакете, где я могу определить функцию, так что там я получаю сообщение об ошибке: "Недопустимое последовательное утверждение".

Так что можно сделать. Какие-либо предложения?

Блок кода:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE work.my_package.all;

-- Entity for ALU component
-- Use this Entity for your C&A project

ENTITY ALU_E IS
  PORT(
    reset_n     : in std_logic;
    clk         : in std_logic;
    OperandA    : in std_logic_vector(3 downto 0);
    OperandB    : in std_logic_vector(3 downto 0);
    Operation   : in std_logic_vector(2 downto 0);
    Start       : in std_logic;
    Result_Low  : out std_logic_vector(3 downto 0);
    Result_High : out std_logic_vector(3 downto 0);
    Ready   : out std_logic;
    Errorsig    : out std_Logic);
END ALU_E;

architecture Behavioral_ALU of ALU_E is 
signal c : std_logic_vector(7 downto 0);
signal carry_internal :std_logic_vector(4 downto 0);

COMPONENT fulladder IS
  PORT(
    a: IN std_logic;
    b: IN std_logic;
    cin : IN std_logic;
    cout: OUT std_logic;
    s: OUT std_logic );
END component fulladder;

begin

adders: for N in 0 to 3 generate
            ff1:fulladder
            port map
            (a => OperandA(N),b => OperandB(N),cin => carry_internal(N),cout => carry_internal(N+1),s => c(N));
            end generate adders;            
            c(4) <= carry_internal(4);


process(clk,reset_n)
begin

if reset_n = '0' then
    if (clk'event) then
        case Operation is 
            when "000" =>   --no operation
            NULL;

            when "001" =>   --Rotate left logical operator ?0000?&A by B steps
            c <= rotlef (OperandA,OperandB);

            when "010" =>   --Rotate right logical operator ?0000?&A by B steps (result width is 8 bit)
            c <= rotrig (OperandA,OperandB);

            when "011" =>   --Bitwise XOR operation
            Result_Low <= OperandA xor OperandB;

            when "100" =>   --Sum of A and B
            --here i want to use a statement such that i can call the gatelevel      --add function
--I have already all functions gatelevel defined when i try to use portmap or ----generate it gives an error illegal sequential statement 
            when Others =>
            NULL;
        end case;
    end if;
end if;
end process;
end Behavioral_ALU;

2 ответа

Что касается того, почему вы получаете сообщения об ошибках, которые вы делаете, оператор создания экземпляра компонента или оператор создания является параллельным оператором, в то время как выбор случая или тело функции состоит из последовательных операторов.

Вам не нужна функция, вам нужна сумма и выполнить из оператора Generate четыре экземпляра fulladders. Подберите пару сущность / архитектура для фулладдера:

library ieee;
use ieee.std_logic_1164.all;

entity fulladder is
    port (
        a:    in  std_logic;
        b:    in  std_logic;
        cin:  in  std_logic;
        cout: out std_logic;
        s:    out std_logic 
    );
end entity;

architecture foo of fulladder is

begin
    s <= a xor b xor cin;
    cout <= (a and b) or (a and cin) or (b and cin);
end architecture;

Пустышка не функционал my_package:

library ieee;
use ieee.std_logic_1164.all;
package my_package is
    function rotlef (a, b: std_logic_vector)  return std_logic_vector;
    function rotrig (a, b: std_logic_vector) return std_logic_vector;
end package;
package body my_package is
    function rotlef (a, b: std_logic_vector)  return std_logic_vector is
        variable ret_val: std_logic_vector (a'range);
    begin
        return ret_val;
    end function;
    function rotrig (a, b: std_logic_vector) return std_logic_vector is
        variable ret_val: std_logic_vector (a'range);
    begin
        return ret_val;
    end function;
end package body;

(обратите внимание, что длина возвращаемого значения функции соответствует длине левого операнда)

Добавить новую декларацию для вывода сгенерированного fulladders:

architecture changed of alu_e is 
    signal c:               std_logic_vector(7 downto 0);
    signal carry_internal:  std_logic_vector(4 downto 0);

    signal s:               std_logic_vector(3 downto 0); -- added

Измените оператор создания, чтобы использовать новый сигнал для суммы:

adders: 
    for n in 0 to 3 generate
ff1:
        fulladder
            port map (
                a => operanda(n),
                b => operandb(n),
                cin => carry_internal(n),
                cout => carry_internal(n+1),
                s => s(n)  -- was c(n)
            );
    end generate;            

    -- c(4) <= carry_internal(4);

(исключая присвоение c(4))

И измените последовательность утверждений для выбора "100":

                    when "100" =>   --sum of a and b
                        result_low <= s; -- added
                        result_high(0) <= carry_internal(4); --(un)signed? 

И ваш дизайн анализирует, разрабатывает и моделирует (хотя и не делает много - никаких заданий в процессе для случая others когда operation Неразвитый и все Us, я не написал тестовый стенд для езды operation или укажите значение по умолчанию).

Обратите внимание на объявление c имеет длину 8, в то время как возвращаемое значение двух функций будет соответствовать их a вход (длина 4).

Если вы должны были выполнить фиктивные функции для operations "001" или же "010" Вы получите ошибку симуляции из-за несоответствия длины с правой стороны. Я оставил это как есть без понимания того, является ли ваш rotlef или же rotrig функции на самом деле возвращают большую длину.

Как правило, вы хотите только 8-битный результат для умножения. Длина c и как это назначено result_low а также result_high не очевидны (пока).

Было невозможно определить, выполняете ли вы арифметику со знаком или без, без каких-либо подробностей. Вместо:

                        result_high(0) <= carry_internal(4); --(un)signed? 

Расширение со знаком может выглядеть так:

                        result_high <= (others => carry_internal(4)); --sign extended 

Обратите внимание, что когда вы создаете экземпляр своего множителя, вы также захотите использовать новое объявление сигнала для 8-битного результата. Изменение ваших операций поворота для назначения result_low а также result_high позволит c использоваться для создания экземпляра умножения, хотя вы можете переименовать его.

Думайте об операторе case в операторе процесса как о создании мультиплексора, а в некоторых случаях вы также выражаете логику на входах. xor или расширение знака или вызовы функций (которые являются выражениями) являются примерами.

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

В этом вопросе есть несколько заблуждений.

Сначала заголовок: в вашем реальном коде нет функции. Что вы сделали с for ... generate Оператор генерирует отдельную часть оборудования, работающую параллельно с основным процессом. Он всегда будет работать и всегда выводит сигнал "c" с суммой, как если бы вы написали c <= a + b; вместо for ... generate, Это всегда, постоянно работает, а не функция, которую вы можете вызывать только тогда, когда хотите.

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

Я думаю, что вы хотите сделать, это создать новый сигнал под названием sum для вывода сумматора, и диск sumне c, в for ... generate, Затем, в заявлении Case, присваивая sum в c выполнит операцию добавления.

Другие вопросы по тегам