Это проблема, с которой я регулярно сталкиваюсь - надеюсь, кто-то сможет прояснить мне правильный способ думать об этом!
Я могу в принципе свести мою проблему к следующему: у меня есть модуль с вводом p_in
, вывод p_out
и часы clk
.Функциональность заключается в том, что всякий раз, когда in
становится низким - out
должен генерировать высокий импульс с длительностью один тактовый период;и этот «детектор отрицательного фронта» реализован в виде FSM с четырьмя состояниями: reset
;wt_in_lo
(дождитесь низкого уровня ввода);sample_signal
(генерировать высокий сигнал на выходе при обнаруженном переходе к нулю на входе);wt_in_hi
(дождитесь высокого уровня на входе, после того как сигнал сэмпла будет повышен).
Код включен ниже, и результат в симуляторе isim
выглядит следующим образом (, и это поведенческое моделирование, поэтому не должно быть никакого влияния перевода конкретной платформы ):
В основном, состояния меняются, как я и ожидаю - первая тактовая частота, FSM распознает, что in
низкий, поэтому он переходит к sample_signal
;вторые часы, мы находимся в sample_signal
состоянии.
- Однако, вот моя проблема - я ожидаю, что
out
повысится, как только войдет в состояние sample_signal
(или, по крайней мере, это то, что я пытаюсьдостижения);тем не менее, out
не выполняет высокий импульс , пока не будет введено следующее состояние (wt_in_hi
)!
А потом я обычно пытаюсь обойти это (например, установить out
в синхронной части fsm, что, вероятно, является плохой идеей) - и в конечном итоге путаю и синтезатор, и меня :)
Итак, вкратце - возможно ли, что я получу сигнал out
, как только будет введено второе состояние (и на время второго состояния);и какой будет правильный способ его кодирования?
Заранее большое спасибо за любые ответы,
Ура!
Код:
-- file: fsm_react_test_twb.vhd
---------------
-- single file testbench examples - see also;
-- http://www.cs.umbc.edu/portal/help/VHDL/samples/samples.shtml
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
-- NEVER call port pins "in"; "out": ERROR:HDLCompiler:806 'Syntax error near "in"'!
ENTITY negedgeDetector IS
PORT (
clk: IN STD_LOGIC;
p_in : IN STD_LOGIC;
p_out: OUT STD_LOGIC
);
END negedgeDetector;
ARCHITECTURE structure OF negedgeDetector IS
-- 'dummy signals' - registers
SIGNAL w_in : STD_LOGIC := 'Z';
SIGNAL w_out : STD_LOGIC := 'Z';
-- fsm states
TYPE states_ned IS -- ned: negedgeDetector
(
ned_reset,
ned_wt_in_lo, -- wait for in active low
ned_sample_signal, -- signal for sampling
ned_wt_in_hi -- wait for in active hi
);
-- init fsm state vars
SIGNAL state_ned, next_state_ned: states_ned := ned_reset;
-- implementation:
BEGIN
-- assign 'wire' / registers
w_in <= p_in;
p_out <= w_out;
-- STATE MACHINES CODE =========
sm_ned: PROCESS(state_ned, w_in) -- combinatorial process part
BEGIN
CASE state_ned IS
WHEN ned_reset =>
next_state_ned <= ned_wt_in_lo;
WHEN ned_wt_in_lo =>
IF w_in = '0' THEN
next_state_ned <= ned_sample_signal;
ELSE
next_state_ned <= ned_wt_in_lo;
END IF;
WHEN ned_sample_signal =>
next_state_ned <= ned_wt_in_hi;
WHEN ned_wt_in_hi =>
IF w_in = '0' THEN
next_state_ned <= ned_wt_in_lo;
ELSE
next_state_ned <= ned_wt_in_hi;
END IF;
END CASE;
END PROCESS sm_ned;
out_sm_ned: PROCESS(clk) -- synchronous process part --
BEGIN
IF (rising_edge(clk)) THEN -- returns only valid transitions;
IF state_ned = ned_sample_signal THEN
-- signal for sampling
w_out <= '1';
ELSE
w_out <= '0';
END IF;
state_ned <= next_state_ned;
END IF;
END PROCESS out_sm_ned;
-- END STATE MACHINES CODE =====
END structure; -- ARCHITECTURE
-- #########################
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
ENTITY fsm_react_test_twb IS
END fsm_react_test_twb;
ARCHITECTURE testbench_arch OF fsm_react_test_twb IS
COMPONENT negedgeDetector
PORT(
clk: IN STD_LOGIC;
p_in : IN STD_LOGIC;
p_out: OUT STD_LOGIC
);
END COMPONENT;
-- 'wires'
SIGNAL wCLK : std_logic := '0';
SIGNAL wIN : std_logic := 'Z';
SIGNAL wOUT : std_logic := 'Z';
-- clock parameters
constant PERIODN : natural := 20; -- can be real := 20.0;
constant PERIOD : time := PERIODN * 1 ns;
constant DUTY_CYCLE : real := 0.5;
constant OFFSET : time := 100 ns;
-- implementation of workbench
BEGIN
-- instances of components, and their wiring (port maps)...
UUT : negedgeDetector -- VHDL
PORT MAP(
clk => wCLK,
p_in => wIN,
p_out => wOUT
);
-- PROCESSES (STATE MACHINES) CODE =========
-- clock process for generating CLK
clocker: PROCESS
BEGIN
WAIT for OFFSET;
CLOCK_LOOP : LOOP
wCLK <= '0';
WAIT FOR (PERIOD - (PERIOD * DUTY_CYCLE));
wCLK <= '1';
WAIT FOR (PERIOD * DUTY_CYCLE);
END LOOP CLOCK_LOOP;
END PROCESS clocker;
simulator: PROCESS
BEGIN
WAIT for OFFSET;
WAIT for 10 ns;
-- take 'in' low - out should detect it with a pulse
wIN <= '0';
WAIT for 50 ns;
-- take 'in' high - no out
wIN <= '1';
WAIT for 50 ns;
-- repeat
wIN <= '0';
WAIT for 50 ns;
wIN <= '1';
WAIT for 50 ns;
-- hold
WAIT;
END PROCESS simulator;
-- END PROCESSES (STATE MACHINES) CODE =====
END testbench_arch; -- ARCHITECTURE
-----------------------
-- call with (Xilinx ISE WebPack 13.2 tools):
-- # note: -tclbatch (isim script) _needs_ -view (*.wcfg) to run! (empty *.wcfg ok)
-- # must use isim script to run at start (and setup view)..
-- # first run:
-- echo 'vhdl work "fsm_react_test_twb.vhd"' > fsm_react_test_twb.prj
-- touch fsm_react_test_twb.wcfg
-- echo -e "wave add {/fsm_react_test_twb/wclk}\nwave add {/fsm_react_test_twb/win}\nwave add {/fsm_react_test_twb/wout}\nwave add {/fsm_react_test_twb/UUT/state_ned}\nwave add {/fsm_react_test_twb/UUT/next_state_ned}\nrun 500 ns\n" > fsm_react_test_twb.isim
-- # build sim and run:
-- fuse -o fsm_react_test_twb.exe -prj fsm_react_test_twb.prj work.fsm_react_test_twb
-- ./fsm_react_test_twb.exe -gui -tclbatch fsm_react_test_twb.isim -view fsm_react_test_twb.wcfg