Я пытаюсь внедрить универсальный десериализатор в VHDL-2008.(В частности, я стремлюсь к тому, что может быть синтезировано Vivado в режиме VHDL-2008).
Я включил свой текущий код ниже.Объявление порта сущности задает неограниченный std_logic_vector DATA_OUT для десериализованного выходного слова.
Проблема заключается в том, что в этой реализации мне нужно указать CounterType следующим образом, если я хочу иметь возможность обрабатывать 32-битныйслова:
type CounterType is range 0 to 31;
Я не смог придумать, как написать определение CounterType из размера порта DATA_OUT таким образом, чтобы он был действительным VHDL, не говоря уже о способе, который приемлемк компилятору Вивадо.
Есть ли способ сделать это?(Т.е. определить тип диапазона, где диапазон соответствует диапазону фактического параметра без ограничений?)
Если нет, каковы мои варианты, чтобы эта реализация десериализатора была как можно более универсальной, т. Е. Иметь возможностьсоздать экземпляр для разных размеров выходного слова?
(Примечание: я бы предпочел способ, который не добавляет универсальный к интерфейсу объекта, так как он кажется избыточным со спецификацией диапазона DATA_OUT во время создания экземпляра. Но еслииначе это сделать нельзя, меня бы тоже заинтересовали подобные решения.)
library ieee;
use ieee.std_logic_1164.all;
entity deserializer is
-- The deserializer accepts its single input bit DATA_IN whenever (DATA_IN_VALID and DATA_IN_READY) = '1'.
-- The deserializer drops its output word DATA_OUT and proceeds whenever (DATA_OUT_VALID and DATA_OUT_READY) = '1'.
port (
CLK : in std_logic;
RESET : in std_logic;
DATA_IN : in std_logic;
DATA_IN_VALID : in std_logic;
DATA_IN_READY : out std_logic;
DATA_OUT : out std_logic_vector;
DATA_OUT_VALID : out std_logic;
DATA_OUT_READY : in std_logic
);
end entity deserializer;
architecture arch of deserializer is
-- This implementation is designed to have no wait states: if a continuous stream of input bits is offered,
-- and the deserializer can offload its output words unimpeded, DATA_IN_READY will always be true, i.e.,
-- we'll never throttle our input; we'll process 1 bit per clock cycle.
type CounterType is range 0 to 31; -- should correspond to the index range of DATA_OUT.
type StateType is record
-- Internal state.
counter : CounterType;
data_in_bit : std_logic; -- Used to store an input bit while waiting to offload the output word in state (counter == 0).
-- Output registers.
data_in_ready : std_logic;
data_out : std_logic_vector(DATA_OUT'range);
data_out_valid : std_logic;
end record StateType;
constant reset_state : StateType := (
counter => 0,
data_in_bit => '-',
data_in_ready => '1',
data_out => (others => '-'),
data_out_valid => '0'
);
signal current_state : StateType := reset_state;
signal next_state : StateType;
begin
combinatorial: process (all) is
variable state: StateType;
begin
-- Calculate next state based on current state and inputs.
if RESET = '1' then
-- Handle synchronous reset.
state := reset_state;
else
-- Start from current state.
state := current_state;
if state.counter = 0 then
-- Note: we may have a pending output, waiting to be accepted.
if state.data_out_valid = '1' and DATA_OUT_READY = '1' then
state.data_out := (others => '-');
state.data_out_valid := '0';
end if;
if state.data_in_ready = '1' and DATA_IN_VALID = '1' then
state.data_in_bit := DATA_IN;
state.data_in_ready := '0';
end if;
if state.data_out_valid = '0' and state.data_in_ready = '0' then
state.data_out(state.data_out'right) := state.data_in_bit;
state.data_in_bit := '-';
state.counter := state.counter + 1;
state.data_in_ready := '1';
end if;
else
if state.data_in_ready = '1'and DATA_IN_VALID = '1' then
state.data_out := state.data_out sll 1;
state.data_out(state.data_out'right) := DATA_IN;
if state.counter = CounterType'high then
state.data_out_valid := '1';
state.counter := 0;
else
state.counter := state.counter + 1;
end if;
end if;
end if;
end if;
-- Schedule next state for update at next rising clock edge.
next_state <= state;
-- Drive entity outputs from current state.
DATA_IN_READY <= current_state.data_in_ready;
DATA_OUT <= current_state.data_out;
DATA_OUT_VALID <= current_state.data_out_valid;
end process combinatorial;
sequential: process (CLK) is
begin
if rising_edge(CLK) then
current_state <= next_state;
end if;
end process sequential;
end architecture arch;