Vhdl 为FSM中的输出端口创建的寄存器,为什么?

Vhdl 为FSM中的输出端口创建的寄存器,为什么?,vhdl,spi,fsm,Vhdl,Spi,Fsm,我正在用VHDL实现一个简单的SPI主机。我面临的问题是,在合成过程中,为ss和data\rdy创建了两个触发器。我认为这些端口的输出总是指定的,那么为什么要创建这些寄存器,我如何才能去掉它们呢 下面是我的代码,省略了其中没有ss或数据的状态 实体: library IEEE; use IEEE.std_logic_1164.ALL; entity mcu is port(clk : in std_logic; res : in std_log

我正在用VHDL实现一个简单的SPI主机。我面临的问题是,在合成过程中,为
ss
data\rdy
创建了两个触发器。我认为这些端口的输出总是指定的,那么为什么要创建这些寄存器,我如何才能去掉它们呢

下面是我的代码,省略了其中没有
ss
数据的状态

实体:

library IEEE;
use IEEE.std_logic_1164.ALL;

entity mcu is
    port(clk      : in  std_logic;
         res      : in  std_logic;
         pc       : in  std_logic_vector(7 downto 0);
         pc_new   : in  std_logic;
         data_ack : in  std_logic;
         miso     : in  std_logic;
         data     : out std_logic_vector(12 downto 0);
         data_rdy : out std_logic;
         mosi     : out std_logic;
         sclk     : out std_logic;
         ss       : out std_logic);
end mcu;
架构:

library IEEE;
use IEEE.std_logic_1164.ALL;

architecture behaviour of mcu is
    -- r: send read command
    -- a: send address
    -- rx: receive data
    type state_t is (r0, r1, r2, r3, r4, r5, r6, r7,
                     a0, a1, a2, a3, a4, a5, a6, a7,
                     rx0, rx1, rx2, rx3, rx4, rx5, rx6, rx7, rx8, rx9, rx10, rx11, rx12,
                     idle, starting, done);
    signal state    : state_t                      := idle;
    signal datasig  : std_logic_vector(12 downto 0);
begin
    sclk <= clk;
    mosi <= datasig(12);

    sync : process(clk) is
    begin
        if rising_edge(clk) then
            data_rdy <= '0';
            ss       <= '0';

            if res = '1' then
                state <= idle;
            else
                datasig <= datasig(11 downto 0) & miso;

                if pc_new = '1' then
                    state <= starting;
                else
                    case state is
                    when idle =>
                        ss      <= '1';
                        datasig <= (others => '0');
                        state   <= idle;

                    ...

                    when rx12 =>
                        data     <= datasig;
                        data_rdy <= '1';
                        state    <= done;
                    when done =>
                        if data_ack = '1' then
                            state <= idle;
                        else
                            state <= done;
                        end if;
                end case;
                end if;
            end if;
        end if;
    end process sync;
end behaviour;

另外,为什么状态被分成两个寄存器?

我面临的问题是,在合成过程中,为ss和data\rdy创建了两个触发器。我认为这些端口的输出总是指定的,所以为什么要创建这些寄存器,我如何才能去掉它们?

data_rdy
ss
的寄存器就在这里创建:

    if rising_edge(clk) then
        data_rdy <= '0';
        ss       <= '0';
因为您的同步干扰状态为空闲、启动或使用由状态驱动的输入多路复用器


如果您能够看到映射设计的示意图,这将很有启发性。

注册输出通常是一件好事:它允许更好地定义计时,这可以转化为更可靠的操作,特别是对于SPI外围设备等外部设备

您面临的问题(我认为)是,当您希望在某个状态下的输出为真时,在该状态下(在时钟进程内)分配该输出将引入时钟周期延迟

David Koontz给出了一个答案:将所有分配到该输出的任务移出时钟部分,或者实际上完全移出该过程,只取决于“状态”信号

但另一种方法将保留寄存器,以便进行干净的计时,并且仍然消除了周期延迟。 也就是说,将输出赋值提前到任何状态下的任何条件,该状态转换为该状态,或者(一旦进入该状态)不转换为该状态。例如,修改

            when rx12 =>
                data     <= datasig;
                data_rdy <= '1';
                state    <= done;
当rx12=> 数据
    if rising_edge(clk) then
        data_rdy <= '0';
        ss       <= '0';

        if res = '1' then
            state <= idle;
        else
            datasig <= datasig(11 downto 0) & miso;

            if pc_new = '1' then
                state <= starting;
            else
                case state is
                when idle =>
                    ss      <= '1';
                    datasig <= (others => '0');
                    state   <= idle;
            when rx12 =>
                data     <= datasig;
                data_rdy <= '1';
                state    <= done;
            when rx11 =>
                if ready_to_go_to_rx12 then
                   data_rdy <= '1';  -- keep data_rdy synched with rx12
                   state    <= rx12;
                end if;

            when rx12 =>
                data     <= datasig;
                -- data_rdy <= '1'; -- no, because we leave state rx12 immediately
                state    <= done;