Project

General

Profile

-- -----------------------------------------------------------------------
--
-- Syntiac's generic VHDL support files.
--
-- -----------------------------------------------------------------------
-- Copyright 2005-2010 by Peter Wendrich (pwsoft@syntiac.com)
-- http://www.syntiac.com/?.html
-- -----------------------------------------------------------------------
--
-- gen_usart.vhd
--
-- -----------------------------------------------------------------------
--
-- USART - Synchronous serial receiver/transmitter
--
-- -----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

-- -----------------------------------------------------------------------

entity gen_usart is
generic (
bits : integer := 8
);
port (
clk : in std_logic;

d : in unsigned(bits-1 downto 0) := (others => '0');
d_trigger : in std_logic := '0';
d_empty : out std_logic;
q : out unsigned(bits-1 downto 0);
q_trigger : out std_logic;

serial_clk : in std_logic;
serial_rxd : in std_logic := '1';
serial_txd : out std_logic;
serial_cts_n : in std_logic := '0'
);
end entity;

-- -----------------------------------------------------------------------

architecture rtl of gen_usart is
type state_t is (
STATE_IDLE,
STATE_BITS,
STATE_STOP);
signal serial_clk_reg : std_logic := '0';
signal serial_clk_dly : std_logic := '0';
signal receive_state : state_t := STATE_IDLE;
signal receive_shift : unsigned(bits-1 downto 0) := (others => '0');
signal receive_cnt : integer range 0 to bits-1 := 0;

signal transmit_state : state_t := STATE_IDLE;
signal transmit_empty : std_logic := '1';
signal transmit_buffer : unsigned(bits-1 downto 0) := (others => '0');
signal transmit_shift : unsigned(bits-1 downto 0) := (others => '0');
signal transmit_cnt : integer range 0 to bits-1 := 0;
begin
d_empty <= transmit_empty and (not d_trigger);

process(clk)
begin
if rising_edge(clk) then
serial_clk_reg <= serial_clk;
serial_clk_dly <= serial_clk_reg;
end if;
end process;

receive_process: process(clk)
begin
if rising_edge(clk) then
q_trigger <= '0';
-- Detect rising edge
if (serial_clk_reg = '1') and (serial_clk_dly = '0') then
case receive_state is
when STATE_IDLE =>
receive_cnt <= 0;
if serial_rxd = '0' then
receive_state <= STATE_BITS;
end if;
when STATE_BITS =>
receive_shift <= serial_rxd & receive_shift(receive_shift'high downto 1);
if receive_cnt = bits-1 then
receive_state <= STATE_STOP;
else
receive_cnt <= receive_cnt + 1;
end if;
when STATE_STOP =>
receive_state <= STATE_IDLE;
if serial_rxd = '1' then
q <= receive_shift;
q_trigger <= '1';
end if;
end case;
end if;
end if;
end process;
transmit_process: process(clk)
begin
if rising_edge(clk) then
-- Detect falling edge
if (serial_clk_reg = '0') and (serial_clk_dly = '1') then
case transmit_state is
when STATE_IDLE =>
transmit_cnt <= 0;
if (transmit_empty = '0') and (serial_cts_n = '0') then
transmit_shift <= transmit_buffer;
transmit_empty <= '1';
transmit_state <= STATE_BITS;
serial_txd <= '0';
else
serial_txd <= '1';
end if;
when STATE_BITS =>
serial_txd <= transmit_shift(transmit_cnt);
if transmit_cnt = bits-1 then
transmit_state <= STATE_STOP;
else
transmit_cnt <= transmit_cnt + 1;
end if;
when STATE_STOP =>
serial_txd <= '1';
transmit_state <= STATE_IDLE;
end case;
end if;
if d_trigger = '1' then
transmit_buffer <= d;
transmit_empty <= '0';
end if;
end if;
end process;
end architecture;





(16-16/33)