基于if语句的VHDL状态转换 - 在板上工作但在模拟器中不起作用

时间:2014-04-10 20:38:42

标签: vhdl simulation state

我不想在这里问另一个问题,但显然我对模拟器真的没用:(。

基本上,我有一个交通灯控制器,它由一堆不同的状态和一些运行不同时间的定时器组成。当系统进入状态时,它会激活一个定时器,并且有一个if语句监视定时器输出,并在定时器输出值为1时将系统指向下一个状态。

这一切都在主板上工作正常,但是当我模拟它时,计数标记为'1'但未选择下一个状态。这可以在这里看到:

Simplified simulation

我已经尝试将代码简化为下面的基本知识,但如果您需要更多上下文(并且感觉比我应得的更慷慨),那么完整的代码是here

初​​始化:

entity trafficlightcontroller is
  port
  (
    clk       : in  std_logic;
    reset     : in  std_logic;
     ambulance : in std_logic;
     smr          : in  std_logic;
     sml          : in  std_logic;
     ssr          : in  std_logic;
    rlmr          : out std_logic;
     almr         : out std_logic;
     glmr         : out std_logic;
     rlsr         : out std_logic;
     alsr         : out std_logic;
     glsr         : out std_logic
  );
end entity;

architecture rtl of trafficlightcontroller is

  -- Build an enumerated type for the state machine
  -- r=red;a=amber;g=green;c=car waiting;m=main road;s=side road
     type state_type is (rmgs, rmas, rmrs, amrs, gmrs, gmrcs, ramrs, rmacs, rmrcs, ramrcs, rmras, rmrs2);

  -- Signals to hold the states
     signal present_state, next_state : state_type;
      signal divclk, reset2, reset2b, reset3, reset3b, reset10, reset20, reset20b, count2, count2b, count3, count3b, count10, count20, count20b: std_logic;

      component timer is
            generic (
                trigger_cnt:    natural := 20
            );
            port (
                 clk:        in      std_logic;
                 reset:      in      std_logic;
                 count:      buffer  std_logic
            );
      end component timer;

      component clockdivider
            port(clkin : in std_logic;
         dividedclk : out std_logic
            );
        end component clockdivider;
      begin

      timer2 : timer generic map (trigger_cnt => 2) port map(divclk,reset2,count2);
      timer2b : timer generic map (trigger_cnt => 2) port map(divclk,reset2b,count2b);
      timer3 : timer generic map (trigger_cnt => 3) port map(divclk,reset3,count3);
      timer3b : timer generic map (trigger_cnt => 3) port map(divclk,reset3b,count3b);
      timer10 : timer generic map (trigger_cnt => 10) port map(divclk,reset10,count10);
      timer20 : timer generic map (trigger_cnt => 20) port map(divclk,reset20,count20);
      timer20b : timer generic map (trigger_cnt => 20) port map(divclk,reset20b,count20b);
      divider : clockdivider port map(clk, divclk);

状态的开始(包括模拟中显示的状态):

 case present_state is

      --Red light main; green side road
    when rmgs=>
         reset2 <= '0';
         reset2b <= '0';
         reset3 <= '0';
         reset3b <= '0';
         reset20 <= '0';
         reset20b <= '0';
         rlmr <= '1';
         almr <= '0';
        glmr <= '0';
        rlsr <= '0';
         alsr <= '0';
         glsr <= '1';
         reset10 <= '1';
         --if count is complete then move to next state
         if ( count10='1' ) THEN
            next_state <= rmas;
         --otherwise, return to current state
         else
            next_state <= rmgs;
         end if;

时钟流程:

--Every clock tick, the next state is selected as the present state.
  state_clocked: process(clk)
  begin
     if ( rising_edge( clk ) ) THEN
        present_state <= next_state;
     end if;
end process state_clocked;

我进入模拟器以初始化时钟的行:

force clk 0 0ns, 1 10 ns -repeat 20ns

2 个答案:

答案 0 :(得分:1)

您的next_state进程在敏感列表中缺少大量信号。这可能会解决它。 VHDL-2008允许您使用关键字“all”而不是信号名称。如果您的综合工具支持此功能,则可能值得使用。

其余的是建议:

使用双进程状态机,最常在state_clocked进程中捕获重置逻辑。因此,看起来更像是这样:

state_clocked: process(clk)
begin
  if ( rising_edge( clk ) ) THEN
    if Reset = '0' then 
      present_state <= rmrs;
    else
      present_state <= next_state;
    end if ;
  end if;
end process state_clocked;

如果使用默认分配将“off”值分配给next_state进程的所有信号输出,则可以显着缩短代码:

next_state_proc : process (present_state, ssr, ambulance, Count10, Count3, ... )
begin
  -- default assignments
  reset2 <= '0';
  reset2b <= '0';
  reset3 <= '0';
  reset3b <='0';
  reset10 <= '0';
  reset20 <= '0';
  reset20b <= '0';
  rlmr <= '1';
  almr <= '0';
  glmr <= '0';
  rlsr <= '1';
  alsr <= '0';
  glsr <= '0';
  next_state <= present_state ;  -- optional

  -- Statemachine code starts here
  -- Only do assignments that are different from the default.

  if ssr = '0' then
    -- Do you change the values from the defaults here?
    -- with the defaults, it is not necessary to do any assignments here, however, 
    -- without the defaults these outputs would have latches on them.
    case present_state is
      when gmrs =>  next_state <= gmrcs;
      when rmas =>  next_state <= rmacs;
      ...
    end case ; 

  elsif ambulance = '0' then 
    -- Do you change the values from the defaults here?
    -- with the defaults, it is not necessary to do any assignments here, however, 
    -- without the defaults these outputs would have latches on them.
    case present_state is
      when gmrs | ramrs | ramrcs =>  next_state <= amrs;
      -- when rmas =>  ???
      when rmgs | rmras =>  next_state <= rmas;
      ...
    end case ; 

  else
    -- main statemachine
    case present_state is
      when rmgs=>
        -- Only drive outputs that are different from the defaults here.
        rlsr <= '0';
        glsr <= '1';
        reset10 <= '1';
        --if count is complete then move to next state
        if ( count10='1' ) THEN
              next_state <= rmas;
        --otherwise, return to current state
        else
              next_state <= rmgs;
        end if;
      when rmas=>
        . . .
    end case ; 

答案 1 :(得分:1)

present_state寄存器的复位不是模拟所必需的,但应该用于合成。

state_clocked: 
    process(reset,clk)
    begin
        if reset = '0' then
            present_state <= rmrs;
        elsif  rising_edge( clk )  THEN
            present_state <= next_state;
        end if;
    end process;

(吉姆打败了我)。

  process (present_state, reset, ssr, ambulance, count2, count2b, 
           count3, count3b, count10, count20, count20b)

添加过程敏感元素(并使用重置):

tb_rfc with cross traffic

(我添加了更多内容。很多设计似乎在很大程度上起作用。)

考虑使用测试台,它可以通过生成救护车,smr,sml和ssr的输入来实现自动化测试。

library ieee;
use ieee.std_logic_1164.all;

entity tb_tfc is
end entity;

architecture foo of tb_tfc is
    signal clk:        std_logic := '0';
    signal reset:      std_logic;
    signal ambulance:  std_logic := '1';
    signal smr:        std_logic := '1';
    signal sml:        std_logic := '1';
    signal ssr:        std_logic := '1';
    signal rlmr:       std_logic;
    signal almr:       std_logic;
    signal glmr:       std_logic;
    signal rlsr:       std_logic;
    signal alsr:       std_logic;
    signal glsr:       std_logic;
begin 

DUT:  
    entity work.trafficlightcontroller
    port map (   
          clk,
          reset,
          ambulance,
          smr,
          sml,
          ssr,
          rlmr, -- out
          almr, -- out
          glmr, -- out
          rlsr, -- out
          alsr, -- out
          glsr  -- out
    );

CLOCK:
    process

    begin
        wait for 10 ns;
        clk <= not clk;
        if Now > 1280 ns then
            wait;
        end if;
    end process;

STIMULUS:
    process 
    begin
        reset <= '0'; -- 
        wait for 20 ns;
        reset <= '1';
        wait for 1020 ns;
        ssr <= '0';
        wait;
    end process;
end architecture;