Пожалуйста, простите меня, если вы найдете какие-то тривиальные ошибки в моем коде. Я все еще новичок в VHDL.
Ну, я должен иметь дело с последовательным интерфейсом от АЦП. Интерфейс довольно прост ... есть провод для последовательных данных (кадр из 24 бит), сигнал DRDY, который сообщает мне, когда доступны новые данные выборки, и последовательные часы (SCLK), которые вставляют бит в ( поднимающийся край). Все работает непрерывно...
Мне нужно правильно захватить 24-битный образец, поместить их на параллельную шину (сдвиговый регистр) и предоставить сигнал «действительные данные» для блоков, которые будут обрабатывать образцы...
Из-за того, что мои системные часы в 4 раза превышают частоту последовательного интерфейса, я подумал, что работать с FSM будет легко...
Когда вы посмотрите на код, вы увидите процесс захвата нарастающих фронтов DRDY и SCLK.
Затем FSM с несколькими состояниями (Init, wait_drdy, wait_sclk, inc_count, check_count).
Я использую счетчик (cnt unsigned), чтобы проверить, захватил ли я уже 24 бита, а также перенаправить состояния FSM в состояние «check_count». Вот картинка:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity serial_ads1675 is
Port (
clk : in STD_LOGIC;
reset : in STD_LOGIC;
sclk : in std_logic;
sdata : in std_logic;
drdy : in std_logic;
pdata : out std_logic_vector(23 downto 0);
pdready : out std_logic
);
end serial_ads1675;
architecture Behavioral of serial_ads1675 is
-- Internal declarations
signal ipdata : std_logic_vector (23 downto 0);
signal ipdready : std_logic;
signal tmp1, tmp2, tmp3, tmp4 : std_logic;
signal rise_drdy, rise_sclk : std_logic;
signal cnt : unsigned (4 downto 0);
type state is (init, wait_drdy, wait_sclk, inc_count, check_count);
signal actual_state, next_state : state;
begin
-- Concurrent statements
pdata <= ipdata;
pdready <= ipdready;
rise_drdy <= '1' when ((tmp1 = '1') and (tmp2 = '0')) else '0';
rise_sclk <= '1' when ((tmp3 = '1') and (tmp4 = '0')) else '0';
-- Process
process (clk, reset)
begin
if (reset = '0') then
tmp1 <= '0';
tmp2 <= '0';
tmp3 <= '0';
tmp4 <= '0';
elsif (falling_edge(clk)) then
tmp1 <= drdy;
tmp2 <= tmp1;
tmp3 <= sclk;
tmp4 <= tmp3;
end if;
end process;
process (reset, clk)
begin
if (reset = '0') then
actual_state <= init;
elsif (rising_edge(clk)) then
actual_state <= next_state;
end if;
end process;
process (rise_sclk, rise_drdy) -- Next State affectation
begin
case actual_state is
when init =>
next_state <= wait_drdy;
ipdata <= (others => '0');
ipdready <= '0';
cnt <= (others => '0');
when wait_drdy =>
if (rise_drdy = '0') then
next_state <= actual_state;
else
next_state <= wait_sclk;
end if;
cnt <= (others => '0');
when wait_sclk =>
if (rise_sclk = '0') then
next_state <= actual_state;
else
next_state <= inc_count;
end if;
ipdready <= '0';
when inc_count =>
next_state <= check_count;
cnt <= cnt + 1;
ipdready <= '0';
ipdata(23 downto 1) <= ipdata(22 downto 0);
ipdata(0) <= sdata;
when check_count =>
case cnt is
when "11000" =>
next_state <= wait_drdy;
ipdready <= '1';
when others =>
next_state <= wait_sclk;
ipdready <= '0';
end case;
when others =>
next_state <= init;
end case;
end process;
end Behavioral;
Моя проблема в состоянии check_count...
Я ожидаю, что это состояние должно длиться один системный такт, но на самом деле оно длится гораздо дольше.
Вот снимок поведенческого моделирования:
Из-за того, что это состояние длится дольше ожидаемого, я пропускаю следующий импульс SCLK и не записываю следующий бит...
Я не понимаю, почему это состояние длится столько системных тактов, а не один...
У кого-нибудь есть какие-нибудь подсказки и принести немного света в мою темную ночь?
Заранее спасибо.
Редактировать: я пытался изменить сигнал cnt для целочисленной переменной, внутренней для процесса FSM... Те же результаты
Если вы не хотите использовать VHDL 2008, вам нужно изменить процесс на process(actual_state, rdy_sclk, rise_drdy , cnt, ipdata, sdata)
После этого вы, вероятно, заметите, что код больше не работает так, как вы ожидали. Я настоятельно рекомендую вам синхронизировать все с помощью clk
.
Ошибка такова:
process (rise_sclk, rise_drdy) -- Next State affectation
begin
-- code omitted, but does generally this:
next_state <= SOME_VALUE;
end process;
Поскольку список чувствительности включает только сигналы rise_sclk
и rise_drdy
, процесс «выполняется» только в случае изменения любого из этих сигналов. Вы можете проследить это на волновой диаграмме.
У вас нет синхронного дизайна, работающего на clk
. Внесите clk
в список чувствительности и основывайте решения на уровнях rise_sclk
и rise_drdy
. Как отрывок:
process (clk) -- Next State affectation
begin
if rising_edge(clk) then
case actual_state is
when init =>
next_state <= wait_drdy;
-- and so on
end case;
end if;
end process;
Привет и добро пожаловать в SO. Обычно читателям было бы полезно предоставить MCVE. У вас есть несколько проблем в вашем коде. Синтез будет игнорировать списки конфиденциальности и создавать логику исключительно из того, что находится в процессе. Чтобы получить лучшее представление о том, что аппаратное обеспечение действительно будет делать, я настоятельно рекомендую вам изменить режим файла на
VHDL 2008
и использоватьprocess(all)
, чтобы компилятор мог определить список чувствительности.