repo2/chameleon/gen_usart.vhd @ 446
145 | markw | -- -----------------------------------------------------------------------
|
|
--
|
|||
-- 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;
|
|||