Используя 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 четыре экземпляра fulladder
s. Подберите пару сущность / архитектура для фулладдера:
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;
(обратите внимание, что длина возвращаемого значения функции соответствует длине левого операнда)
Добавить новую декларацию для вывода сгенерированного fulladder
s:
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
Неразвитый и все U
s, я не написал тестовый стенд для езды operation
или укажите значение по умолчанию).
Обратите внимание на объявление c
имеет длину 8, в то время как возвращаемое значение двух функций будет соответствовать их a
вход (длина 4).
Если вы должны были выполнить фиктивные функции для operation
s "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
выполнит операцию добавления.