我已经创建了一个FSM,并且我希望针对FSM的每个状态从我的UART发送一个char(8位)。 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代码在传输r_TX_Data字节时等待DV信号(DataValid)。最后,它设置了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信号,但没有正确的时序。 我得到以下输出:
我在哪里错了?
而且……传递永远不会结束