UART RS-232发送器

时间:2014-05-12 17:28:43

标签: serial-port vhdl fpga

我在VHDL中实现RS-232发送器。 我想使用PS-2键盘输入数据并将其显示在串口终端中。 我有工作的接收器,我知道其余的元件正在与这个发射器分开工作。

我有以下代码:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity uart is
generic (
    CLK_FREQ    : integer := 50;        
    SER_FREQ    : integer := 115200     
);
port (
    clk         : in    std_logic;      
    rst         : in    std_logic;      
    tx          : out   std_logic;      

    tx_req      : in    std_logic;                                          
    tx_data     : in    std_logic_vector(7 downto 0);   
    rx_ready    : out   std_logic;                      
    rx_data     : out   std_logic_vector(7 downto 0)    
);
end uart;

architecture Behavioral of uart is


    constant UART_IDLE  :   std_logic := '1';
    constant UART_START :   std_logic := '0';
    constant RST_LVL       :    std_logic := '1';


    type state is (idle,data,stop);         

    signal tx_state         :   state;
    signal tx_next_state    :  state;
    signal tx_clk_en        :   std_logic;
    signal tx_data_tmp  :   std_logic_vector(7 downto 0);   
    signal tx_data_cnt  :   std_logic_vector(2 downto 0);   

begin
--
    tx_clk_gen:process(clk)
        variable counter    :   integer range 0 to conv_integer((CLK_FREQ*1_000_000)/SER_FREQ-1);
    begin
        if clk'event and clk = '1' then
            if counter = (CLK_FREQ*1_000_000)/SER_FREQ-1 then
                tx_clk_en   <=  '1';
                counter     :=  0;
            else
                tx_clk_en   <=  '0';
                counter     :=  counter + 1;
            end if;
        end if;
    end process;

    tx_process:process(clk, tx_state)
    begin
        if tx_clk_en = '0' then
            tx_next_state <= tx_state;
            case tx_state is
                when idle =>
                    if tx_req = '0' then
                        tx <= '0';
                        tx_data_tmp <= tx_data;
                        tx_next_state <= data;
                        tx_data_cnt <= (others=>'1');
                    else
                        tx <= '1';
                        tx_next_state <= idle;
                        tx_data_cnt <= (others=>'1');
                        tx_data_tmp <= (others=>'1');
                    end if;
                when data =>
                    tx <= tx_data_tmp(0);
                    if tx_data_cnt = 0 then
                        tx_next_state <= stop;
                        tx_data_cnt <= (others=>'1');
                        tx_data_tmp <=(others=>'1');
                    else
                        tx_next_state <= data;
                        tx_data_tmp <= '0' & tx_data_tmp(7 downto 1);
                        tx_data_cnt <= tx_data_cnt - 1;
                    end if;
                when stop =>
                    tx <= '1';
                    tx_next_state <= idle;
                    tx_data_cnt <= (others=>'1');
                    tx_data_tmp <=(others=>'1');
            end case;
        end if;
    end process;

    tx_next:process(tx_next_state)
    begin
        tx_state <= tx_next_state;
    end process;

end Behavioral;

在实施设计期间,有一些警告:

One or more signals are missing in the process sensitivity list. To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list. Please note that the result of the synthesis may differ from the initial design specification. The missing signals are:<tx_clk_en>, <tx_req>, <tx_data>

Found 3-bit latch for signal <tx_data_cnt>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

Found 8-bit latch for signal <tx_data_tmp>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

Found 3-bit latch for signal <tx_next_state>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

Found 1-bit latch for signal <tx>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems. 

请帮帮我。 提前谢谢。

编辑:

我根据您的提示修改了我的代码,现在没有任何警告,但我仍然不确定它是否能正常工作。有人可以在硬件上检查吗?或者只是评论新版本。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity uart is
generic (
    CLK_FREQ    : integer := 50;        
    SER_FREQ    : integer := 115200     
);
port (
    clk         : in    std_logic;      
    rst         : in    std_logic;              
    tx          : out   std_logic;      
    tx_req      : in    std_logic;                                      
    tx_data     : in    std_logic_vector(7 downto 0);   
);
end uart;

architecture Behavioral of uart is


    constant UART_IDLE  :   std_logic := '1';
    constant UART_START :   std_logic := '0';
    constant RST_LVL       :    std_logic := '1';

    type state is (idle, active);           

    signal tx_state         :   state;
    signal tx_next_state    :  state;
    signal tx_clk_en        :   std_logic;
    signal tx_data_packet   :   std_logic_vector(9 downto 0);   
    signal tx_data_cnt  :   std_logic_vector(3 downto 0);   

begin
--
    tx_clk_gen:process(clk)
        variable counter    :   integer range 0 to conv_integer((CLK_FREQ*1_000_000)/SER_FREQ-1);
    begin
        if clk'event and clk = '1' then
            if counter = (CLK_FREQ*1_000_000)/SER_FREQ-1 then
                tx_clk_en   <=  '1';
                counter     :=  0;
            else
                tx_clk_en   <=  '0';
                counter     :=  counter + 1;
            end if;
        end if;
    end process;

    tx_reset:process(clk)
    begin
        if clk'event and clk = '1' then
            if rst = '0' then
                tx_state <= idle;
            else
                tx_state <= tx_next_state;
            end if;
        end if;
    end process;

    tx_process:process(clk, tx_state, tx_req, tx_clk_en)
    begin
        if clk'event and clk = '1' then
            if tx_clk_en = '0' then
                tx_next_state <= tx_state;
                case tx_state is
                    when idle =>
                        if tx_req = '0' then
                            tx_data_packet(9) <= '0';
                            tx_data_packet(8 downto 1) <= tx_data;
                            tx_data_packet(0) <= '1';
                            tx_next_state <= active;
                            tx_data_cnt <= "1010";
                        else
                            tx <= '1';
                            tx_next_state <= idle;
                            tx_data_cnt <= (others=>'1');
                            tx_data_packet <= (others=>'1');
                        end if;
                    when active =>
                        tx <= tx_data_packet(0);
                        if tx_data_cnt = 0 then
                            tx_next_state <= idle;
                            tx_data_cnt <= (others=>'1');
                            tx_data_packet <=(others=>'1');
                        else
                            tx_next_state <= active;
                            tx_data_packet <= '0' & tx_data_packet(9 downto 1);
                            tx_data_cnt <= tx_data_cnt - 1;
                        end if;
                end case;
            else
                tx <= '1';
                tx_data_packet <= (others=>'1');
                tx_data_cnt <= (others=>'1');
            end if;
        end if;
    end process;

end Behavioral;
# # 嘿伙计们! 我现在有以下代码,我在硬件上进行了测试,但它仍然无法正常工作。你有什么想法吗?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity uart is
generic (
    CLK_FREQ    : integer := 50;        
    SER_FREQ    : integer := 115200     
);
port (
    clk         : in    std_logic;      
    rst         : in    std_logic;      
    rx          : in    std_logic;      
    tx          : out   std_logic;      

    tx_req      : in    std_logic;                                          
    tx_data     : in    std_logic_vector(7 downto 0);   
);
end uart;

architecture Behavioral of uart is


    constant UART_IDLE  :   std_logic := '1';
    constant UART_START :   std_logic := '0';
    constant RST_LVL       :    std_logic := '1';


    type state is (idle, active);           

    signal tx_busy      :std_logic;
    signal tx_state         :   state;
    signal tx_next_state    :  state;
    signal tx_clk_en        :   std_logic;
    signal tx_data_packet   :   std_logic_vector(8 downto 0);   
    signal tx_data_cnt  :   std_logic_vector(3 downto 0);   

begin
--
    tx_clk_gen:process(clk, tx_req)
        variable counter    :   integer range 0 to conv_integer((CLK_FREQ*1_000_000)/SER_FREQ-1);
    begin
        if rising_edge(clk) then
            if tx_busy = '1' then
                if counter = (CLK_FREQ*1_000_000)/SER_FREQ-1 then
                    tx_clk_en   <=  '1';
                    counter     :=  0;
                else
                    tx_clk_en   <=  '0';
                    counter     :=  counter + 1;
                end if;
            end if;
        end if;
    end process;

    tx_reset:process(clk)
    begin
        if rising_edge(clk) then
            if rst = '0' then
                tx_state <= idle;
            else
                tx_state <= tx_next_state;
            end if;
        end if;
    end process;

    tx_process:process(clk, tx_state, tx_req, tx_clk_en)
    begin
        if rising_edge(clk) then
                case tx_state is
                    when idle =>
                        if tx_req = '1' then
                            tx <= '0';
                            tx_data_packet(7 downto 0) <= tx_data;
                            tx_data_packet(8) <= '1';
                            tx_next_state <= active;
                            tx_data_cnt <= "1010";
                            tx_busy <= '1';
                        else
                            tx <= '1';
                            tx_next_state <= idle;
                            tx_data_cnt <= (others=>'1');
                            tx_data_packet <= (others=>'1');
                        end if;
                    when active =>
                        if tx_clk_en = '1' then
                            tx <= tx_data_packet(0);
                            if tx_data_cnt = 0 then
                                tx_next_state <= idle;
                                tx_data_cnt <= (others=>'1');
                                tx_data_packet <=(others=>'1');
                                tx <= '1';
                                tx_busy <= '0';
                            else
                                tx_next_state <= active;
                                tx_data_packet <= '1' & tx_data_packet(8 downto 1);
                                tx_data_cnt <= tx_data_cnt - 1;
                            end if;
                        end if;
                end case;
        end if;
    end process;

2 个答案:

答案 0 :(得分:1)

锁存器指示您要计时的非时钟进程,或者覆盖不完整的组合逻辑(例如if语句没有else部分)。

我可以在短暂的一瞥中看到前两个代码。

编辑re:编辑:然后编写一个测试平台并进行模拟。它符合您的期望吗?

答案 1 :(得分:0)

猜猜您在if clk'event and clk = '1' then的最外层失踪rising_edge(clk)tx_process

tx_next过程看起来也很奇怪;它实际上没有像现在所写的那样(除了延迟)。