OpenCores
URL https://opencores.org/ocsvn/simple_uart_for_fpga/simple_uart_for_fpga/trunk

Subversion Repositories simple_uart_for_fpga

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /simple_uart_for_fpga
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/source/uart_tb.vhd
0,0 → 1,136
--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE: TESTBANCH OF UART TOP MODULE
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- lICENSE: The MIT License (MIT)
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity UART_TB is
end UART_TB;
 
architecture FULL of UART_TB is
 
signal CLK : std_logic := '0';
signal RST : std_logic := '0';
signal tx_uart : std_logic;
signal rx_uart : std_logic := '1';
signal data_vld : std_logic;
signal data_out : std_logic_vector(7 downto 0);
signal frame_error : std_logic;
signal data_send : std_logic;
signal busy : std_logic;
signal data_in : std_logic_vector(7 downto 0);
 
constant clk_period : time := 20 ns;
constant uart_period : time := 8680.56 ns;
constant data_value : std_logic_vector(7 downto 0) := "10100111";
constant data_value2 : std_logic_vector(7 downto 0) := "00110110";
 
begin
 
utt: entity work.UART
generic map (
CLK_FREQ => 50e6,
BAUD_RATE => 115200,
PARITY_BIT => "none"
)
port map (
CLK => CLK,
RST => RST,
-- UART INTERFACE
UART_TXD => tx_uart,
UART_RXD => rx_uart,
-- USER DATA INPUT INTERFACE
DATA_OUT => data_out,
DATA_VLD => data_vld,
FRAME_ERROR => frame_error,
-- USER DATA OUTPUT INTERFACE
DATA_IN => data_in,
DATA_SEND => data_send,
BUSY => busy
);
 
clk_process : process
begin
CLK <= '0';
wait for clk_period/2;
CLK <= '1';
wait for clk_period/2;
end process;
 
test_rx_uart : process
begin
rx_uart <= '1';
RST <= '1';
wait for 100 ns;
RST <= '0';
 
wait until rising_edge(CLK);
 
rx_uart <= '0'; -- start bit
wait for uart_period;
 
for i in 0 to (data_value'LENGTH-1) loop
rx_uart <= data_value(i); -- data bits
wait for uart_period;
end loop;
 
rx_uart <= '1'; -- stop bit
wait for uart_period;
 
rx_uart <= '0'; -- start bit
wait for uart_period;
 
for i in 0 to (data_value2'LENGTH-1) loop
rx_uart <= data_value2(i); -- data bits
wait for uart_period;
end loop;
 
rx_uart <= '1'; -- stop bit
wait for uart_period;
 
wait;
 
end process;
 
test_tx_uart : process
begin
data_send <= '0';
RST <= '1';
wait for 100 ns;
RST <= '0';
 
wait until rising_edge(CLK);
 
data_send <= '1';
data_in <= data_value;
 
wait until rising_edge(CLK);
 
data_send <= '0';
 
wait until rising_edge(CLK);
 
wait for 80 us;
wait until rising_edge(CLK);
 
data_send <= '1';
data_in <= data_value2;
 
wait until rising_edge(CLK);
 
data_send <= '0';
 
wait until rising_edge(CLK);
 
wait;
 
end process;
 
end FULL;
/trunk/source/uart.vhd
0,0 → 1,131
--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE: UART TOP MODULE
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- lICENSE: The MIT License (MIT)
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
-- UART FOR FPGA REQUIRES: 1 START BIT, 8 DATA BITS, 1 STOP BIT!!!
-- OTHER PARAMETERS CAN BE SET USING GENERICS.
 
entity UART is
Generic (
CLK_FREQ : integer := 50e6; -- set system clock frequency in Hz
BAUD_RATE : integer := 115200; -- baud rate value
PARITY_BIT : string := "none" -- legal values: "none", "even", "odd", "mark", "space"
);
Port (
CLK : in std_logic; -- system clock
RST : in std_logic; -- high active synchronous reset
-- UART INTERFACE
UART_TXD : out std_logic;
UART_RXD : in std_logic;
-- USER DATA INPUT INTERFACE
DATA_IN : in std_logic_vector(7 downto 0);
DATA_SEND : in std_logic; -- when DATA_SEND = 1, data on DATA_IN will be transmit, DATA_SEND can set to 1 only when BUSY = 0
BUSY : out std_logic; -- when BUSY = 1 transiever is busy, you must not set DATA_SEND to 1
-- USER DATA OUTPUT INTERFACE
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_VLD : out std_logic; -- when DATA_VLD = 1, data on DATA_OUT are valid
FRAME_ERROR : out std_logic -- when FRAME_ERROR = 1, stop bit was invalid, current and next data may be invalid
);
end UART;
 
architecture FULL of UART is
 
constant divider_value : integer := CLK_FREQ/(16*BAUD_RATE);
 
signal uart_ticks : integer range 0 to divider_value-1;
signal uart_clk_en : std_logic;
signal uart_rxd_shreg : std_logic_vector(3 downto 0);
signal uart_rxd_debounced : std_logic;
 
begin
 
-- -------------------------------------------------------------------------
-- UART OVERSAMPLING CLOCK DIVIDER
-- -------------------------------------------------------------------------
 
uart_oversampling_clk_divider : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
uart_ticks <= 0;
uart_clk_en <= '0';
elsif (uart_ticks = divider_value-1) then
uart_ticks <= 0;
uart_clk_en <= '1';
else
uart_ticks <= uart_ticks + 1;
uart_clk_en <= '0';
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART RXD DEBAUNCER
-- -------------------------------------------------------------------------
 
uart_rxd_debouncer : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
uart_rxd_shreg <= (others => '1');
uart_rxd_debounced <= '1';
else
uart_rxd_shreg <= UART_RXD & uart_rxd_shreg(3 downto 1);
uart_rxd_debounced <= uart_rxd_shreg(0) OR
uart_rxd_shreg(1) OR
uart_rxd_shreg(2) OR
uart_rxd_shreg(3);
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART TRANSMITTER
-- -------------------------------------------------------------------------
 
uart_tx_i: entity work.UART_TX
generic map (
PARITY_BIT => PARITY_BIT
)
port map (
CLK => CLK,
RST => RST,
-- UART INTERFACE
UART_CLK_EN => uart_clk_en,
UART_TXD => UART_TXD,
-- USER DATA INPUT INTERFACE
DATA_IN => DATA_IN,
DATA_SEND => DATA_SEND,
BUSY => BUSY
);
 
-- -------------------------------------------------------------------------
-- UART RECEIVER
-- -------------------------------------------------------------------------
 
uart_rx_i: entity work.UART_RX
generic map (
PARITY_BIT => PARITY_BIT
)
port map (
CLK => CLK,
RST => RST,
-- UART INTERFACE
UART_CLK_EN => uart_clk_en,
UART_RXD => uart_rxd_debounced,
-- USER DATA OUTPUT INTERFACE
DATA_OUT => DATA_OUT,
DATA_VLD => DATA_VLD,
FRAME_ERROR => FRAME_ERROR
);
 
end FULL;
/trunk/source/comp/uart_parity.vhd
0,0 → 1,73
--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE: UART PARITY BIT GENERATOR
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- lICENSE: The MIT License (MIT)
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity UART_PARITY is
Generic (
DATA_WIDTH : integer := 8;
PARITY_TYPE : string := "none" -- legal values: "none", "even", "odd", "mark", "space"
);
Port (
DATA_IN : in std_logic_vector(DATA_WIDTH-1 downto 0);
PARITY_OUT : out std_logic
);
end UART_PARITY;
 
architecture FULL of UART_PARITY is
 
begin
 
-- -------------------------------------------------------------------------
-- PARITY BIT GENERATOR
-- -------------------------------------------------------------------------
 
even_parity_g : if (PARITY_TYPE = "even") generate
 
process (DATA_IN)
variable parity_temp : std_logic;
begin
parity_temp := '0';
for i in DATA_IN'range loop
parity_temp := parity_temp XOR DATA_IN(i);
end loop;
PARITY_OUT <= parity_temp;
end process;
 
end generate;
 
odd_parity_g : if (PARITY_TYPE = "odd") generate
 
process (DATA_IN)
variable parity_temp : std_logic;
begin
parity_temp := '1';
for i in DATA_IN'range loop
parity_temp := parity_temp XOR DATA_IN(i);
end loop;
PARITY_OUT <= parity_temp;
end process;
 
end generate;
 
mark_parity_g : if (PARITY_TYPE = "mark") generate
 
PARITY_OUT <= '1';
 
end generate;
 
space_parity_g : if (PARITY_TYPE = "space") generate
 
PARITY_OUT <= '0';
 
end generate;
 
end FULL;
/trunk/source/comp/uart_rx.vhd
0,0 → 1,272
--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE: UART RECEIVER
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- lICENSE: The MIT License (MIT)
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity UART_RX is
Generic (
PARITY_BIT : string := "none" -- legal values: "none", "even", "odd", "mark", "space"
);
Port (
CLK : in std_logic; -- system clock
RST : in std_logic; -- high active synchronous reset
-- UART INTERFACE
UART_CLK_EN : in std_logic; -- oversampling (16x) UART clock enable
UART_RXD : in std_logic;
-- USER DATA OUTPUT INTERFACE
DATA_OUT : out std_logic_vector(7 downto 0);
DATA_VLD : out std_logic; -- when DATA_VLD = 1, data on DATA_OUT are valid
FRAME_ERROR : out std_logic -- when FRAME_ERROR = 1, stop bit was invalid, current and next data may be invalid
);
end UART_RX;
 
architecture FULL of UART_RX is
 
signal rx_clk_en : std_logic;
signal rx_ticks : unsigned(3 downto 0);
signal rx_clk_divider_en : std_logic;
signal rx_data : std_logic_vector(7 downto 0);
signal rx_bit_count : unsigned(2 downto 0);
signal rx_bit_count_en : std_logic;
signal rx_data_shreg_en : std_logic;
signal rx_parity_bit : std_logic;
signal rx_parity_error : std_logic;
signal rx_parity_check_en : std_logic;
signal rx_output_reg_en : std_logic;
 
type state is (idle, startbit, databits, paritybit, stopbit);
signal rx_pstate : state;
signal rx_nstate : state;
 
begin
 
-- -------------------------------------------------------------------------
-- UART RECEIVER CLOCK DIVIDER
-- -------------------------------------------------------------------------
 
uart_rx_clk_divider : process (CLK)
begin
if (rising_edge(CLK)) then
if (rx_clk_divider_en = '1') then
if (uart_clk_en = '1') then
if (rx_ticks = "1111") then
rx_ticks <= (others => '0');
rx_clk_en <= '0';
elsif (rx_ticks = "0111") then
rx_ticks <= rx_ticks + 1;
rx_clk_en <= '1';
else
rx_ticks <= rx_ticks + 1;
rx_clk_en <= '0';
end if;
else
rx_ticks <= rx_ticks;
rx_clk_en <= '0';
end if;
else
rx_ticks <= (others => '0');
rx_clk_en <= '0';
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART RECEIVER BIT COUNTER
-- -------------------------------------------------------------------------
 
uart_rx_bit_counter : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
rx_bit_count <= (others => '0');
elsif (rx_bit_count_en = '1' AND rx_clk_en = '1') then
if (rx_bit_count = "111") then
rx_bit_count <= (others => '0');
else
rx_bit_count <= rx_bit_count + 1;
end if;
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART RECEIVER DATA SHIFT REGISTER
-- -------------------------------------------------------------------------
 
uart_rx_data_shift_reg : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
rx_data <= (others => '0');
elsif (rx_clk_en = '1' AND rx_data_shreg_en = '1') then
rx_data <= UART_RXD & rx_data(7 downto 1);
end if;
end if;
end process;
 
DATA_OUT <= rx_data;
 
-- -------------------------------------------------------------------------
-- UART RECEIVER PARITY GENERATOR AND CHECK
-- -------------------------------------------------------------------------
 
uart_rx_parity_g : if (PARITY_BIT /= "none") generate
uart_rx_parity_gen_i: entity work.UART_PARITY
generic map (
DATA_WIDTH => 8,
PARITY_TYPE => PARITY_BIT
)
port map (
DATA_IN => rx_data,
PARITY_OUT => rx_parity_bit
);
 
uart_rx_parity_check_reg : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
rx_parity_error <= '0';
elsif (rx_parity_check_en = '1') then
rx_parity_error <= rx_parity_bit XOR UART_RXD;
end if;
end if;
end process;
end generate;
 
uart_rx_noparity_g : if (PARITY_BIT = "none") generate
rx_parity_error <= '0';
end generate;
 
-- -------------------------------------------------------------------------
-- UART RECEIVER OUTPUT REGISTER
-- -------------------------------------------------------------------------
 
uart_rx_output_reg : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
DATA_VLD <= '0';
FRAME_ERROR <= '0';
else
if (rx_output_reg_en = '1') then
DATA_VLD <= NOT rx_parity_error AND UART_RXD;
FRAME_ERROR <= NOT UART_RXD;
else
DATA_VLD <= '0';
FRAME_ERROR <= '0';
end if;
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART RECEIVER FSM
-- -------------------------------------------------------------------------
 
-- PRESENT STATE REGISTER
process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
rx_pstate <= idle;
else
rx_pstate <= rx_nstate;
end if;
end if;
end process;
 
-- NEXT STATE AND OUTPUTS LOGIC
process (rx_pstate, UART_RXD, rx_clk_en, rx_bit_count)
begin
case rx_pstate is
 
when idle =>
rx_output_reg_en <= '0';
rx_bit_count_en <= '0';
rx_data_shreg_en <= '0';
rx_clk_divider_en <= '0';
rx_parity_check_en <= '0';
 
if (UART_RXD = '0') then
rx_nstate <= startbit;
else
rx_nstate <= idle;
end if;
 
when startbit =>
rx_output_reg_en <= '0';
rx_bit_count_en <= '0';
rx_data_shreg_en <= '0';
rx_clk_divider_en <= '1';
rx_parity_check_en <= '0';
 
if (rx_clk_en = '1') then
rx_nstate <= databits;
else
rx_nstate <= startbit;
end if;
 
when databits =>
rx_output_reg_en <= '0';
rx_bit_count_en <= '1';
rx_data_shreg_en <= '1';
rx_clk_divider_en <= '1';
rx_parity_check_en <= '0';
 
if ((rx_clk_en = '1') AND (rx_bit_count = "111")) then
if (PARITY_BIT = "none") then
rx_nstate <= stopbit;
else
rx_nstate <= paritybit;
end if ;
else
rx_nstate <= databits;
end if;
 
when paritybit =>
rx_output_reg_en <= '0';
rx_bit_count_en <= '0';
rx_data_shreg_en <= '0';
rx_clk_divider_en <= '1';
rx_parity_check_en <= '1';
 
if (rx_clk_en = '1') then
rx_nstate <= stopbit;
else
rx_nstate <= paritybit;
end if;
 
when stopbit =>
rx_bit_count_en <= '0';
rx_data_shreg_en <= '0';
rx_clk_divider_en <= '1';
rx_parity_check_en <= '0';
 
if (rx_clk_en = '1') then
rx_nstate <= idle;
rx_output_reg_en <= '1';
else
rx_nstate <= stopbit;
rx_output_reg_en <= '0';
end if;
 
when others =>
rx_output_reg_en <= '0';
rx_bit_count_en <= '0';
rx_data_shreg_en <= '0';
rx_clk_divider_en <= '0';
rx_parity_check_en <= '0';
rx_nstate <= idle;
 
end case;
end process;
 
end FULL;
/trunk/source/comp/uart_tx.vhd
0,0 → 1,269
--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE: UART TRANSMITTER
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- lICENSE: The MIT License (MIT)
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity UART_TX is
Generic (
PARITY_BIT : string := "none" -- legal values: "none", "even", "odd", "mark", "space"
);
Port (
CLK : in std_logic; -- system clock
RST : in std_logic; -- high active synchronous reset
-- UART INTERFACE
UART_CLK_EN : in std_logic; -- oversampling (16x) UART clock enable
UART_TXD : out std_logic;
-- USER DATA INPUT INTERFACE
DATA_IN : in std_logic_vector(7 downto 0);
DATA_SEND : in std_logic; -- when DATA_SEND = 1, data on DATA_IN will be transmit, DATA_SEND can set to 1 only when BUSY = 0
BUSY : out std_logic -- when BUSY = 1 transiever is busy, you must not set DATA_SEND to 1
);
end UART_TX;
 
architecture FULL of UART_TX is
 
signal tx_clk_en : std_logic;
signal tx_clk_divider_en : std_logic;
signal tx_ticks : unsigned(3 downto 0);
signal tx_data : std_logic_vector(7 downto 0);
signal tx_bit_count : unsigned(2 downto 0);
signal tx_bit_count_en : std_logic;
signal tx_busy : std_logic;
signal tx_parity_bit : std_logic;
signal tx_data_out_sel : std_logic_vector(1 downto 0);
 
type state is (idle, txsync, startbit, databits, paritybit, stopbit);
signal tx_pstate : state;
signal tx_nstate : state;
 
begin
 
BUSY <= tx_busy;
 
-- -------------------------------------------------------------------------
-- UART TRANSMITTER CLOCK DIVIDER
-- -------------------------------------------------------------------------
 
uart_tx_clk_divider : process (CLK)
begin
if (rising_edge(CLK)) then
if (tx_clk_divider_en = '1') then
if (uart_clk_en = '1') then
if (tx_ticks = "1111") then
tx_ticks <= (others => '0');
tx_clk_en <= '0';
elsif (tx_ticks = "0001") then
tx_ticks <= tx_ticks + 1;
tx_clk_en <= '1';
else
tx_ticks <= tx_ticks + 1;
tx_clk_en <= '0';
end if;
else
tx_ticks <= tx_ticks;
tx_clk_en <= '0';
end if;
else
tx_ticks <= (others => '0');
tx_clk_en <= '0';
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART TRANSMITTER INPUT DATA REGISTER
-- -------------------------------------------------------------------------
 
uart_tx_input_data_reg : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
tx_data <= (others => '0');
elsif (DATA_SEND = '1' AND tx_busy = '0') then
tx_data <= DATA_IN;
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART TRANSMITTER BIT COUNTER
-- -------------------------------------------------------------------------
 
uart_tx_bit_counter : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
tx_bit_count <= (others => '0');
elsif (tx_bit_count_en = '1' AND tx_clk_en = '1') then
if (tx_bit_count = "111") then
tx_bit_count <= (others => '0');
else
tx_bit_count <= tx_bit_count + 1;
end if;
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART TRANSMITTER PARITY GENERATOR
-- -------------------------------------------------------------------------
 
uart_tx_parity_g : if (PARITY_BIT /= "none") generate
uart_tx_parity_gen_i: entity work.UART_PARITY
generic map (
DATA_WIDTH => 8,
PARITY_TYPE => PARITY_BIT
)
port map (
DATA_IN => tx_data,
PARITY_OUT => tx_parity_bit
);
end generate;
 
uart_tx_noparity_g : if (PARITY_BIT = "none") generate
tx_parity_bit <= 'Z';
end generate;
 
-- -------------------------------------------------------------------------
-- UART TRANSMITTER OUTPUT DATA REGISTER
-- -------------------------------------------------------------------------
 
uart_tx_output_data_reg : process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
UART_TXD <= '1';
else
case tx_data_out_sel is
when "01" => -- START BIT
UART_TXD <= '0';
when "10" => -- DATA BITS
UART_TXD <= tx_data(to_integer(tx_bit_count));
when "11" => -- PARITY BIT
UART_TXD <= tx_parity_bit;
when others => -- STOP BIT OR IDLE
UART_TXD <= '1';
end case;
end if;
end if;
end process;
 
-- -------------------------------------------------------------------------
-- UART TRANSMITTER FSM
-- -------------------------------------------------------------------------
 
-- PRESENT STATE REGISTER
process (CLK)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
tx_pstate <= idle;
else
tx_pstate <= tx_nstate;
end if;
end if;
end process;
 
-- NEXT STATE AND OUTPUTS LOGIC
process (tx_pstate, DATA_SEND, tx_clk_en, tx_bit_count)
begin
 
case tx_pstate is
 
when idle =>
tx_busy <= '0';
tx_data_out_sel <= "00";
tx_bit_count_en <= '0';
tx_clk_divider_en <= '0';
 
if (DATA_SEND = '1') then
tx_nstate <= txsync;
else
tx_nstate <= idle;
end if;
 
when txsync =>
tx_busy <= '1';
tx_data_out_sel <= "00";
tx_bit_count_en <= '0';
tx_clk_divider_en <= '1';
 
if (tx_clk_en = '1') then
tx_nstate <= startbit;
else
tx_nstate <= txsync;
end if;
 
when startbit =>
tx_busy <= '1';
tx_data_out_sel <= "01";
tx_bit_count_en <= '0';
tx_clk_divider_en <= '1';
 
if (tx_clk_en = '1') then
tx_nstate <= databits;
else
tx_nstate <= startbit;
end if;
 
when databits =>
tx_busy <= '1';
tx_data_out_sel <= "10";
tx_bit_count_en <= '1';
tx_clk_divider_en <= '1';
 
if ((tx_clk_en = '1') AND (tx_bit_count = "111")) then
if (PARITY_BIT = "none") then
tx_nstate <= stopbit;
else
tx_nstate <= paritybit;
end if ;
else
tx_nstate <= databits;
end if;
 
when paritybit =>
tx_busy <= '1';
tx_data_out_sel <= "11";
tx_bit_count_en <= '0';
tx_clk_divider_en <= '1';
 
if (tx_clk_en = '1') then
tx_nstate <= stopbit;
else
tx_nstate <= paritybit;
end if;
 
when stopbit =>
tx_busy <= '0';
tx_data_out_sel <= "00";
tx_bit_count_en <= '0';
tx_clk_divider_en <= '1';
 
if (DATA_SEND = '1') then
tx_nstate <= txsync;
elsif (tx_clk_en = '1') then
tx_nstate <= idle;
else
tx_nstate <= stopbit;
end if;
 
when others =>
tx_busy <= '1';
tx_data_out_sel <= "00";
tx_bit_count_en <= '0';
tx_clk_divider_en <= '0';
tx_nstate <= idle;
 
end case;
end process;
 
end FULL;
/trunk/LICENSE
0,0 → 1,22
The MIT License (MIT)
 
Copyright (c) 2015 Jakub Cabal
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
/trunk/example/uart_loopback.vhd
0,0 → 1,67
--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE: UART LOOPBACK EXAMPLE TOP MODULE
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- lICENSE: The MIT License (MIT)
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
-- UART FOR FPGA REQUIRES: 1 START BIT, 8 DATA BITS, 1 STOP BIT!!!
-- OTHER PARAMETERS CAN BE SET USING GENERICS.
 
entity UART_LOOPBACK is
Generic (
CLK_FREQ : integer := 50e6; -- set system clock frequency in Hz
BAUD_RATE : integer := 115200; -- baud rate value
PARITY_BIT : string := "none" -- legal values: "none", "even", "odd", "mark", "space"
);
Port (
CLK : in std_logic; -- system clock
RST_N : in std_logic; -- low active synchronous reset
-- UART INTERFACE
UART_TXD : out std_logic;
UART_RXD : in std_logic;
-- DEBUG INTERFACE
BUSY : out std_logic;
FRAME_ERR : out std_logic
);
end UART_LOOPBACK;
 
architecture FULL of UART_LOOPBACK is
 
signal data : std_logic_vector(7 downto 0);
signal valid : std_logic;
signal reset : std_logic;
 
begin
 
reset <= not RST_N;
 
uart_i: entity work.UART
generic map (
CLK_FREQ => CLK_FREQ,
BAUD_RATE => BAUD_RATE,
PARITY_BIT => PARITY_BIT
)
port map (
CLK => CLK,
RST => reset,
-- UART INTERFACE
UART_TXD => UART_TXD,
UART_RXD => UART_RXD,
-- USER DATA OUTPUT INTERFACE
DATA_OUT => data,
DATA_VLD => valid,
FRAME_ERROR => FRAME_ERR,
-- USER DATA INPUT INTERFACE
DATA_IN => data,
DATA_SEND => valid,
BUSY => BUSY
);
 
end FULL;
/trunk/example/uart_loopback_tb.vhd
0,0 → 1,115
--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE: TESTBANCH OF UART LOOPBACK EXAMPLE TOP MODULE
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- lICENSE: The MIT License (MIT)
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity UART_LOOPBACK_TB is
end UART_LOOPBACK_TB;
 
architecture FULL of UART_LOOPBACK_TB is
 
signal CLK : std_logic := '0';
signal RST_N : std_logic := '0';
signal tx_uart : std_logic;
signal rx_uart : std_logic := '1';
signal busy : std_logic;
signal frame_error : std_logic;
 
constant clk_period : time := 20 ns;
constant uart_period : time := 8680.56 ns;
constant data_value : std_logic_vector(7 downto 0) := "10100111";
constant data_value2 : std_logic_vector(7 downto 0) := "00110110";
 
begin
 
utt: entity work.UART_LOOPBACK
generic map (
CLK_FREQ => 50e6,
BAUD_RATE => 115200,
PARITY_BIT => "none"
)
port map (
CLK => CLK,
RST_N => RST_N,
-- UART INTERFACE
UART_TXD => tx_uart,
UART_RXD => rx_uart,
-- DEBUG INTERFACE
BUSY => busy,
FRAME_ERR => frame_error
);
 
clk_process : process
begin
CLK <= '0';
wait for clk_period/2;
CLK <= '1';
wait for clk_period/2;
end process;
 
test_rx_uart : process
begin
rx_uart <= '1';
RST_N <= '0';
wait for 100 ns;
RST_N <= '1';
 
wait for uart_period;
 
rx_uart <= '0'; -- start bit
wait for uart_period;
 
for i in 0 to (data_value'LENGTH-1) loop
rx_uart <= data_value(i); -- data bits
wait for uart_period;
end loop;
 
rx_uart <= '1'; -- stop bit
wait for uart_period;
 
rx_uart <= '0'; -- start bit
wait for uart_period;
 
for i in 0 to (data_value2'LENGTH-1) loop
rx_uart <= data_value2(i); -- data bits
wait for uart_period;
end loop;
 
rx_uart <= '1'; -- stop bit
wait for uart_period;
 
rx_uart <= '0'; -- start bit
wait for uart_period;
 
for i in 0 to (data_value'LENGTH-1) loop
rx_uart <= data_value(i); -- data bits
wait for uart_period;
end loop;
 
rx_uart <= '1'; -- stop bit
wait for uart_period;
 
rx_uart <= '0'; -- start bit
wait for uart_period;
 
for i in 0 to (data_value2'LENGTH-1) loop
rx_uart <= data_value2(i); -- data bits
wait for uart_period;
end loop;
 
rx_uart <= '1'; -- stop bit
wait for uart_period;
 
wait;
 
end process;
 
end FULL;
/trunk/README.md
0,0 → 1,32
# Simple UART for FPGA
 
Simple UART for FPGA is UART (Universal Asynchronous Receiver & Transmitter) controller for serial communication with an FPGA. The UART controller was implemented using VHDL 93 and is applicable to any FPGA.
 
**Simple UART for FPGA requires: 1 start bit, 8 data bits, 1 stop bit!**
 
The UART controller was simulated and tested in hardware.
 
# Inputs and outputs ports:
 
Port name | IN/OUT | Width | Port description
---|:---:|:---:|---
CLK | IN | 1b | System clock.
RST | IN | 1b | High active synchronous reset.
UART_TXD | OUT | 1b | Serial transmit data.
UART_RXD | IN | 1b | Serial receive data.
DATA_IN | IN | 8b | Data byte for transmit.
DATA_SEND | IN | 1b | Send data byte for transmit.
BUSY | OUT | 1b | Transmitter is busy, can not send next data.
DATA_OUT | OUT | 8b | Received data byte.
DATA_VLD | OUT | 1b | Received data byte is valid.
FRAME_ERROR | OUT | 1b | Stop bit is invalid, current and next data may be corrupted.
 
# Synthesis resource usage summary:
 
Parity | LE (LUT) | FF | BRAM
:---:|:---:|:---:|:---:
none | 80 | 55 | 0
even/odd | 91 | 58 | 0
mark/space | 84 | 58 | 0
 
*Synthesis was performed using Quartus II 64-Bit Version 13.0.1 for FPGA Altera Cyclone II with these settings: 115200 baud rate and 50 MHz system clock .*

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.