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

Subversion Repositories pdp8

[/] [pdp8/] [trunk/] [pdp8/] [uart/] [uart_rx.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------
--!
--! PDP-8 Processor
--!
--! \brief
--!      KL8E Generic UART Receiver
--!
--! \details
--!      The UART Receiver is hard configured for:
--!      - 8 data bits
--!      - no parity
--!      - 1 stop bit
--!
--! \note
--!      This UART primitive receiver is kept simple
--!      intentionally and is therefore unbuffered.  If you
--!      require a double buffered UART, then you will need to
--!      layer a set of buffers on top of this device.
--!
--! \file
--!      uart_rx.vhd
--!
--! \author
--!      Rob Doyle - doyle (at) cox (dot) net
--!
--------------------------------------------------------------------
--
--  Copyright (C) 2009, 2010, 2011, 2012 Rob Doyle
--
-- This source file may be used and distributed without
-- restriction provided that this copyright statement is not
-- removed from the file and that any derivative work contains
-- the original copyright notice and the associated disclaimer.
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- version 2.1 of the License.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl.txt
--
--------------------------------------------------------------------
--
-- Comments are formatted for doxygen
--
 
library ieee;                                   --! IEEE Library
use ieee.std_logic_1164.all;                    --! IEEE 1164
use work.uart_types.all;                        --! UART Types
use work.cpu_types.all;                         --! CPU Types
 
--
--! KL8E Generic UART Receiver Entity
--
 
entity eUART_RX is port (
    sys   : in  sys_t;                          --! Clock/Reset
    clkBR : in  std_logic;                      --! Clock Enable (for Baud Rate)
    rxd   : in  std_logic;                      --! Serial Data In
    intr  : out std_logic;                      --! Data Received
    data  : out ascii_t                         --! Data Output
);
end eUART_RX;
 
--
--! KL8E Generic UART Receiver RTL
--
 
architecture rtl of eUART_RX is
    type   state_t is (stateIdle,               --! Idle
                       stateStart,              --! Working on Start Bit
                       stateBit0,               --! Working on Bit 0
                       stateBit1,               --! Working on Bit 1
                       stateBit2,               --! Working on Bit 2
                       stateBit3,               --! Working on Bit 3
                       stateBit4,               --! Working on Bit 4
                       stateBit5,               --! Working on Bit 5
                       stateBit6,               --! Working on Bit 6
                       stateBit7,               --! Working on Bit 7
                       stateStop,               --! Working on Stop Bit
                       stateDone);              --! Generate Intr
    signal state   : state_t;                   --! Receiver State
    signal rxReg   : ascii_t;                   --! Receiver Register
    signal rxdd    : std_logic_vector(0 to 1);  --! Demet RXD
 
begin
 
    --
    --! This process synchronizes the Received Data to this clock
    --! domain.
    --
 
    DEMET_RXD : process(sys)
    begin
        if sys.rst = '1' then
            rxdd <= (others => '0');
        elsif rising_edge(sys.clk) then
            rxdd(0) <= rxd;
            rxdd(1) <= rxdd(0);
        end if;
    end process DEMET_RXD;
 
 
    --
    --! UART Receiver:
    --!  The clkBR is 16 clocks per bit.  The UART receives LSB first.
    --!
    --!  The state machine is initialized to the idle state where it
    --!  looks for a start bit.  When it find the 'edge' of the start
    --!  bit starts the state machine which does the following:
    --!
    --!  -# Continuously sample the start bit for half a bit period.
    --!     If the start bit is narrower than half a bit then, go back
    --!     to the idle state and look for a real start bit.   Othewise,
    --!  -# Delay one bit time from the middle of the Start bit and
    --!     sample bit D7 (LSB), then
    --!  -# Delay one bit time from the middle of D7 and sample bit D6, then
    --!  -# Delay one bit time from the middle of D6 and sample bit D5, then
    --!  -# Delay one bit time from the middle of D5 and sample bit D4, then
    --!  -# Delay one bit time from the middle of D4 and sample bit D3, then
    --!  -# Delay one bit time from the middle of D3 and sample bit D2, then
    --!  -# Delay one bit time from the middle of D2 and sample bit D1, then
    --!  -# Delay one bit time from the middle of D1 and sample bit D0, then
    --!  -# Delay one bit time from the middle of D0 and sample Stop
    --!     Bit, then
    --!  -# Generate INTR pulse for one clock cycle, then
    --!  -# go back to idle state and wait for a stop bit.
    --!
 
    UARTRX : process(sys)
        variable brdiv : integer range 0 to 15;
    begin
        if sys.rst = '1' then
 
            state <= stateIdle;
            rxReg <= (others => '0');
            brdiv := 0;
 
        elsif rising_edge(sys.clk) then
 
            case state is
 
                --
                -- Reciever is Idle
                --
 
                when stateIdle =>
                    if clkBR = '1' then
                        if rxdd(1) = '0' then
                            state <= stateStart;
                            brdiv := 8;
                        end if;
                    end if;
 
                --
                -- Receive Start Bit
                --
 
                when stateStart =>
                    if clkBR = '1' then
                        if rxdd(1) = '0' then
                            if brdiv = 0 then
                                brdiv := 15;
                                state <= stateBit7;
                            else
                                brdiv := brdiv - 1;
                            end if;
                        else
                            state <= stateIdle;
                        end if;
                    end if;
 
                --
                -- Receive Bit 7 (LSB)
                --
 
                when stateBit7 =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            brdiv := 15;
                            rxReg <= rxdd(1) & rxReg(0 to 6);
                            state <= stateBit6;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Receive Bit 6 
                --
 
                when stateBit6 =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            brdiv := 15;
                            rxReg <= rxdd(1) & rxReg(0 to 6);
                            state <= stateBit5;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Receive Bit 5
                --
 
                when stateBit5 =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            brdiv := 15;
                            rxReg <= rxdd(1) & rxReg(0 to 6);
                            state <= stateBit4;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Receive Bit 4 
                --
 
                when stateBit4 =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            brdiv := 15;
                            rxReg <= rxdd(1) & rxReg(0 to 6);
                            state <= stateBit3;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Receive Bit 3
                --
 
                when stateBit3 =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            brdiv := 15;
                            rxReg <= rxdd(1) & rxReg(0 to 6);
                            state <= stateBit2;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Receive Bit 2
                --
 
                when stateBit2 =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            brdiv := 15;
                            rxReg <= rxdd(1) & rxReg(0 to 6);
                            state <= stateBit1;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Receive Bit 1
                --
 
                when stateBit1 =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            brdiv := 15;
                            rxReg <= rxdd(1) & rxReg(0 to 6);
                            state <= stateBit0;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Receive Bit 0 (MSB)
                --
 
                when stateBit0 =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            brdiv := 15;
                            rxReg <= rxdd(1) & rxReg(0 to 6);
                            state <= stateStop;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Receive Stop Bit
                --
 
                 when stateStop =>
                    if clkBR = '1' then
                        if brdiv = 0 then
                            state <= stateDone;
                        else
                            brdiv := brdiv - 1;
                        end if;
                    end if;
 
                --
                -- Generate Interrupt
                --
 
               when stateDone =>
                  state <= stateIdle;
 
            end case;
        end if;
    end process UARTRX;
 
    data <= rxReg;
    intr <= '1' when state = stateDone else '0';
 
end rtl;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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