1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2024-12-13 22:33:09 +02:00
nn-usb-fpga/plasma/logic/uart.vhd
2010-05-27 21:26:56 -05:00

171 lines
6.2 KiB
VHDL

---------------------------------------------------------------------
-- TITLE: UART
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 5/29/02
-- FILENAME: uart.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Implements the UART.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_unsigned.all;
use std.textio.all;
use work.mlite_pack.all;
entity uart is
generic(log_file : string := "UNUSED");
port(clk : in std_logic;
reset : in std_logic;
cs : in std_logic;
nRdWr : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
uart_read : in std_logic;
uart_write : out std_logic;
busy_write : out std_logic;
data_avail : out std_logic);
end; --entity uart
architecture logic of uart is
signal delay_write_reg : std_logic_vector(9 downto 0);
signal bits_write_reg : std_logic_vector(3 downto 0);
signal data_write_reg : std_logic_vector(8 downto 0);
signal delay_read_reg : std_logic_vector(9 downto 0);
signal bits_read_reg : std_logic_vector(3 downto 0);
signal data_read_reg : std_logic_vector(7 downto 0);
signal data_save_reg : std_logic_vector(17 downto 0);
signal busy_write_sig : std_logic;
signal read_value_reg : std_logic_vector(6 downto 0);
signal uart_read2 : std_logic;
signal enable_read : std_logic;
signal enable_write : std_logic;
begin
interface_proc: process(cs, nRdWr)
begin
if cs = '1' then
if nRdWr = '1' then
enable_read <= '0';
enable_write <= '1';
else
enable_read <= '1';
enable_write <= '0';
end if;
else
enable_read <= '0';
enable_write <= '0';
end if;
end process;
uart_proc: process(clk, reset, enable_read, enable_write, data_in,
data_write_reg, bits_write_reg, delay_write_reg,
data_read_reg, bits_read_reg, delay_read_reg,
data_save_reg, read_value_reg, uart_read2,
busy_write_sig, uart_read)
constant COUNT_VALUE : std_logic_vector(9 downto 0) :=
-- "0100011110"; --33MHz/2/57600Hz = 0x11e
-- "1101100100"; --50MHz/57600Hz = 0x364
"0110110010"; --25MHz/57600Hz = 0x1b2 -- Plasma IF uses div2
-- "0011011001"; --12.5MHz/57600Hz = 0xd9
-- "0000000100"; --for debug (shorten read_value_reg)
begin
uart_read2 <= read_value_reg(read_value_reg'length - 1);
if reset = '1' then
data_write_reg <= ZERO(8 downto 1) & '1';
bits_write_reg <= "0000";
delay_write_reg <= ZERO(9 downto 0);
read_value_reg <= ONES(read_value_reg'length-1 downto 0);
data_read_reg <= ZERO(7 downto 0);
bits_read_reg <= "0000";
delay_read_reg <= ZERO(9 downto 0);
data_save_reg <= ZERO(17 downto 0);
elsif rising_edge(clk) then
--Write UART
if bits_write_reg = "0000" then --nothing left to write?
if enable_write = '1' then
delay_write_reg <= ZERO(9 downto 0); --delay before next bit
bits_write_reg <= "1010"; --number of bits to write
data_write_reg <= data_in & '0'; --remember data & start bit
end if;
else
if delay_write_reg /= COUNT_VALUE then
delay_write_reg <= delay_write_reg + 1; --delay before next bit
else
delay_write_reg <= ZERO(9 downto 0); --reset delay
bits_write_reg <= bits_write_reg - 1; --bits left to write
data_write_reg <= '1' & data_write_reg(8 downto 1);
end if;
end if;
--Average uart_read signal
if uart_read = '1' then
if read_value_reg /= ONES(read_value_reg'length - 1 downto 0) then
read_value_reg <= read_value_reg + 1;
end if;
else
if read_value_reg /= ZERO(read_value_reg'length - 1 downto 0) then
read_value_reg <= read_value_reg - 1;
end if;
end if;
--Read UART
if delay_read_reg = ZERO(9 downto 0) then --done delay for read?
if bits_read_reg = "0000" then --nothing left to read?
if uart_read2 = '0' then --wait for start bit
delay_read_reg <= '0' & COUNT_VALUE(9 downto 1); --half period
bits_read_reg <= "1001"; --bits left to read
end if;
else
delay_read_reg <= COUNT_VALUE; --initialize delay
bits_read_reg <= bits_read_reg - 1; --bits left to read
data_read_reg <= uart_read2 & data_read_reg(7 downto 1);
end if;
else
delay_read_reg <= delay_read_reg - 1; --delay
end if;
--Control character buffer
if bits_read_reg = "0000" and delay_read_reg = COUNT_VALUE then
if data_save_reg(8) = '0' or
(enable_read = '1' and data_save_reg(17) = '0') then
--Empty buffer
data_save_reg(8 downto 0) <= '1' & data_read_reg;
else
--Second character in buffer
data_save_reg(17 downto 9) <= '1' & data_read_reg;
if enable_read = '1' then
data_save_reg(8 downto 0) <= data_save_reg(17 downto 9);
end if;
end if;
elsif enable_read = '1' then
data_save_reg(17) <= '0'; --data_available
data_save_reg(8 downto 0) <= data_save_reg(17 downto 9);
end if;
end if; --rising_edge(clk)
uart_write <= data_write_reg(0);
if bits_write_reg /= "0000"
-- Comment out the following line for full UART simulation (much slower)
and log_file = "UNUSED"
then
busy_write_sig <= '1';
else
busy_write_sig <= '0';
end if;
busy_write <= busy_write_sig;
data_avail <= data_save_reg(8);
data_out <= data_save_reg(7 downto 0);
end process; --uart_proc
end; --architecture logic