Я создал 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
Где я не прав?
И ... трансмиссия никогда не заканчивается