1

これは私が定期的に遭遇する問題です-うまくいけば、誰かが私にそれについて考える正しい方法を明確にすることができます!

私は基本的に私の問題をこれに減らすことができます:私は入力p_in、出力p_out、クロックを備えたモジュールを持っていますclkin機能は、ローになるたびにout、1クロック周期の持続時間でハイパルスを生成する必要があるということです。この「ネガティブエッジ検出器」は、次の4つの状態を持つFSMとして実装されresetます。wt_in_lo(入力がローになるのを待ちます); sample_signal(入力でゼロへの遷移が検出されると、出力でハイ信号を生成します); wt_in_hi(サンプル信号が発生した後、入力がハイになるのを待ちます)。

コードは以下に含まれており、isimシミュレーターの結果は次のようになります(これは動作シミュレーションであるため、プラットフォーム固有の変換の影響はありません)。

fsm_react_test_annot.png

基本的に、状態は私が期待するとおりに変化します-最初のクロックポーズ、FSMは低いと認識しているため、 ;inに移行します。sample_signal2番目の時計のポーズ、私たちはsample_signal状態にあります。

  • ただし、ここに私の問題があります。状態に入るoutとすぐにが高くなることを期待していsample_signalます(または、少なくとも、それが私が達成しようとしていることです)。それでも、次の状態( )に入るまで、はoutハイパルスを実行しません!wt_in_hi

そして、私は通常、これを回避してコーディングしようとします(つまりout、同期fsm部分での設定は、おそらく悪い考えです)-そして、シンセサイザーと私自身の両方を混乱させることになります:)

 

つまり、簡単に言えばout、2番目の状態に入るとすぐに(そして2番目の状態の期間中)信号を受け取る可能性はありますか?そしてそれをコーディングする適切な方法は何でしょうか?

よろしくお願いし
ます。

 

コード:

-- 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
4

2 に答える 2

3

state_ned問題は、同期プロセス内からの値をチェックしていることです。つまり、出力は次のクロックの立ち上がりエッジの前に変化しません。

出力の同期を維持したい場合は、次の値を確認する必要がありますnext_state_ned。例:

out_sm_ned: PROCESS(clk) -- synchronous process part --
BEGIN
  IF (rising_edge(clk)) THEN -- returns only valid transitions;
    IF next_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;
于 2011-11-04T13:44:44.767 に答える
0

ここではステートマシンは必要ないと思います。私のアプローチは、シングルフロップとANDゲートを持つことです。

proc_reg: process (clk,reset)
begin
  if reset = RESET_ACTIVE_LEVEL then

    q_r0 <= '0';

  elsif clk'event and clk = '1' then

    q_r0 <= p_in;

  end if;
end process proc_reg;

p_out <= '1' when p_in = '0' and q_r0 = '1' else '0';

p_inがclkと同期していない場合は、q_r0の前にレジスタステージを追加して、メタスタビリティをクリーンアップできます。

于 2011-11-29T19:07:00.230 に答える