Передача по UART от FSM - PullRequest
0 голосов
/ 28 марта 2019

Я создал FSM и хотел бы, чтобы для каждого состояния FSM передавал символ (8 бит) из моего UART. Передатчик UART определяется как:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity UART_TX is
  generic (
    g_CLKS_PER_BIT : integer := 139     -- Needs to be set correctly
    );
  port (
    i_Clk       : in  std_logic;
    i_TX_DV     : in  std_logic;
    i_TX_Byte   : in  std_logic_vector(7 downto 0);
    o_TX_Active : out std_logic;
    o_TX_Serial : out std_logic;
    o_TX_Done   : out std_logic
    );
end UART_TX;


architecture RTL of UART_TX is

  type t_SM_Main is (s_Idle, s_TX_Start_Bit, s_TX_Data_Bits,
                     s_TX_Stop_Bit, s_Cleanup);
  signal r_SM_Main : t_SM_Main := s_Idle;

  signal r_Clk_Count : integer range 0 to g_CLKS_PER_BIT-1 := 0;
  signal r_Bit_Index : integer range 0 to 7 := 0;  -- 8 Bits Total
  signal r_TX_Data   : std_logic_vector(7 downto 0) := (others => '0');
  signal r_TX_Done   : std_logic := '0';

begin


  p_UART_TX : process (i_Clk)
  begin
    if rising_edge(i_Clk) then

      case r_SM_Main is

        when s_Idle =>
          o_TX_Active <= '0';
          o_TX_Serial <= '1';         -- Drive Line High for Idle
          r_TX_Done   <= '0';
          r_Clk_Count <= 0;
          r_Bit_Index <= 0;

          if i_TX_DV = '1' then
            r_TX_Data <= i_TX_Byte;
            r_SM_Main <= s_TX_Start_Bit;
          else
            r_SM_Main <= s_Idle;
          end if;


        -- Send out Start Bit. Start bit = 0
        when s_TX_Start_Bit =>
          o_TX_Active <= '1';
          o_TX_Serial <= '0';

          -- Wait g_CLKS_PER_BIT-1 clock cycles for start bit to finish
          if r_Clk_Count < g_CLKS_PER_BIT-1 then
            r_Clk_Count <= r_Clk_Count + 1;
            r_SM_Main   <= s_TX_Start_Bit;
          else
            r_Clk_Count <= 0;
            r_SM_Main   <= s_TX_Data_Bits;
          end if;


        -- Wait g_CLKS_PER_BIT-1 clock cycles for data bits to finish          
        when s_TX_Data_Bits =>
          o_TX_Serial <= r_TX_Data(r_Bit_Index);

          if r_Clk_Count < g_CLKS_PER_BIT-1 then
            r_Clk_Count <= r_Clk_Count + 1;
            r_SM_Main   <= s_TX_Data_Bits;
          else
            r_Clk_Count <= 0;

            -- Check if we have sent out all bits
            if r_Bit_Index < 7 then
              r_Bit_Index <= r_Bit_Index + 1;
              r_SM_Main   <= s_TX_Data_Bits;
            else
              r_Bit_Index <= 0;
              r_SM_Main   <= s_TX_Stop_Bit;
            end if;
          end if;


        -- Send out Stop bit.  Stop bit = 1
        when s_TX_Stop_Bit =>
          o_TX_Serial <= '1';

          -- Wait g_CLKS_PER_BIT-1 clock cycles for Stop bit to finish
          if r_Clk_Count < g_CLKS_PER_BIT-1 then
            r_Clk_Count <= r_Clk_Count + 1;
            r_SM_Main   <= s_TX_Stop_Bit;
          else
            r_TX_Done   <= '1';
            r_Clk_Count <= 0;
            r_SM_Main   <= s_Cleanup;
          end if;


        -- Stay here 1 clock
        when s_Cleanup =>
          o_TX_Active <= '0';
          r_TX_Done   <= '1';
          r_SM_Main   <= s_Idle;


        when others =>
          r_SM_Main <= s_Idle;

      end case;
    end if;
  end process p_UART_TX;

  o_TX_Done <= r_TX_Done;

end RTL;

Хорошо работает только для одного персонажа. Этот VHDL-код ожидает сигнала DV (DataValid), когда он преобразует байт r_TX_Data. Наконец, он установил сигнал o_TX_Done.

Мне нужно отправить различные символы (байты) через мой передатчик. По этой причине я использую этот код:

---[cut]
 type t_SM_serial  is (s_Start, s_COMMAND, s_BA, s_BB, s_BC);
    signal next_state : t_SM_Serial;
  signal r_SM_serial : t_SM_serial := s_Start;


 -- Low-level byte-write---------------------------------------------------------------
  procedure UART_WRITE_BYTE ( i_data_in       : in  std_logic_vector(7 downto 0)  ) is
 begin
            r_TX_BYTE  <=  i_data_in;
            r_TX_DV  <= '1';
 end UART_WRITE_BYTE;
  --------------------------------------------------------------------------------------





 begin --------------architecture begin


 -- Instantiate UART transmitter
  UART_TX_INST : uart_tx
    generic map (
      g_CLKS_PER_BIT => 139 --c_CLKS_PER_BIT
      )
    port map (
      i_clk       => Clk,   
      i_tx_dv     => r_TX_DV, 
      i_tx_byte   => r_TX_BYTE,
      o_tx_active => open,
      o_tx_serial => out_serial_memory,
      o_tx_done   => w_TX_DONE
      );



    st: process (r_SM_serial,w_TX_DONE)
    begin
        case r_SM_Serial is
            when s_COMMAND => 
                if (w_TX_Done = '1' ) then 
                    next_state <= S_BA;
                end if;

            when s_BA => 
                if (w_TX_Done = '1' ) then 
                    next_state <= S_BB;
               end if;
            when s_BB => 
                if (w_TX_Done = '1' ) then 
                    next_state <= S_start;
               end if;
            when others =>
                next_state <= s_Start;
            end case;
    end process;



        ----------------------------------------
        -- Output Logic 
        ----------------------------------------
        OUT_LOGIC: process (r_SM_Serial) 
        begin
            case r_SM_Serial is
                when s_Command => 
                    UART_WRITE_BYTE(X"41");
                when s_BA => 
                    UART_WRITE_BYTE(X"42"); 
                when s_BB => 
                    UART_WRITE_BYTE(X"43"); 
                when s_Start =>
                    r_TX_DV <= '0';
                when others =>  
                    r_TX_DV <= '0';
            end case;
        end process OUT_LOGIC; 


process (Clk,reset)
  begin
  if reset = '1' then 
        r_SM_serial <= s_command;

  elsif (CLK'event and CLK = '1') then
        r_SM_Serial <= NEXT_STATE;
    end if;
  end process;

Это не работает. Передатчик непрерывно отправляет первый символ (статус s_Command) и никогда не останавливается.

По-видимому, сигнал w_TX_Done установлен, но нет правильной синхронизации. Я получаю этот вывод:

Выход PuTTY

Где я не прав?

И ... трансмиссия никогда не заканчивается

...