質問

I'm implementing RS-232 transmitter in VHDL. I want to get data typed using PS-2 keyboard and display it in serial port terminal. I have working Receiver and I know that the rest of elements is working apart from this transmitter.

I have the written following code:

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;

During implementing design there are a few warnings:

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. 

Please, help me. Thanks in advance.

Edit:

I adapted my code to your hints and there are no warnings now, but I'm still not sure if it will work correctly. Can anyone check it on hardware? Or just comment the new version.

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;
# #

Hey guys! I have now the following code, I tested in on hardware and it's still not working. Do you have any ideas what can be wrong?

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

Guess you are missing if clk'event and clk = '1' then, or rising_edge(clk), at the out-most level of the tx_process.

The tx_next process also looks weird; it actually does nothing as written now (apart from delta delay).

他のヒント

Latches indicate either unclocked processes that you meant to clock, or combinational logic with incomplete coverage (e.g. if statements with no else part).

I can see two of the former in a brief glance at this code.

Edit re: Edit : Then write a testbench and simulate it. Does it do what you expect?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top