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

Subversion Repositories light8080

[/] [light8080/] [trunk/] [vhdl/] [soc/] [uart.vhdl] - Diff between revs 70 and 77

Only display areas with differences | Details | Blame | View Log

Rev 70 Rev 77
--##############################################################################
--##############################################################################
-- uart.vhdl -- Basic, hardwired RS232 UART.
-- uart.vhdl -- Basic, hardwired RS232 UART.
--
--
-- Most operational parameters are hardcoded: 8 bit words, no parity, 1 stop 
-- Most operational parameters are hardcoded: 8 bit words, no parity, 1 stop 
-- bit. The only parameter that can be configured in run time is the baud rate.
-- bit. The only parameter that can be configured in run time is the baud rate.
--
--
-- The receiver logic is a simplified copy of the 8051 UART. The bit period is 
-- The receiver logic is a simplified copy of the 8051 UART. The bit period is 
-- split in 16 sampling periods, and 3 samples are taken at the center of each 
-- split in 16 sampling periods, and 3 samples are taken at the center of each 
-- bit period. The bit value is decided by majority. The receiver logic has some
-- bit period. The bit value is decided by majority. The receiver logic has some
-- error recovery capability that should make this core reliable enough for
-- error recovery capability that should make this core reliable enough for
-- actual application use -- yet, the core does not have a format test bench.
-- actual application use -- yet, the core does not have a format test bench.
--
--
-- See usage notes below.
-- See usage notes below.
--
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- This file is free software (See COPYING.TXT) 
-- This file is free software (See COPYING.TXT) 
--##############################################################################
--##############################################################################
 
 
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_std.all;
 
 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- UART programmer model
-- UART programmer model
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--
--
-- The UART has a number of configuration registers addressable with input 
-- The UART has a number of configuration registers addressable with input 
-- signal addr_i:
-- signal addr_i:
--
--
-- [00] => Data buffer, both transmission and reception.
-- [00] => Data buffer, both transmission and reception.
-- [01] => Status/control register (r/w).
-- [01] => Status/control register (r/w).
-- [10] => Bit period register, low byte.
-- [10] => Bit period register, low byte.
-- [11] => Bit period register, high byte.
-- [11] => Bit period register, high byte.
--
--
--
--
-- Data buffers:
-- Data buffers:
----------------
----------------
--
--
-- The same address [00b] is used for both the receive buffer and the 
-- The same address [00b] is used for both the receive buffer and the 
-- transmision buffer. 
-- transmision buffer. 
--
--
-- Writing to the data buffer when flag TxRdy is high will trigger a 
-- Writing to the data buffer when flag TxRdy is high will trigger a 
-- transmission and clear flag TxRdy.
-- transmission and clear flag TxRdy.
-- Writing to the data buffer when flag TxRdy is clear will have no effect.
-- Writing to the data buffer when flag TxRdy is clear will have no effect.
-- 
-- 
-- Reading the data register when flag RxRdy is high will return the last 
-- Reading the data register when flag RxRdy is high will return the last 
-- received data byte, and will clear flag RxRdy but NOT RxIrq. 
-- received data byte, and will clear flag RxRdy but NOT RxIrq. 
-- Reading the register when flag RxRdy is clear will return indeterminate data,
-- Reading the register when flag RxRdy is clear will return indeterminate data,
-- which in practice will usually be the last byte received.
-- which in practice will usually be the last byte received.
--
--
-- Interrupts:
-- Interrupts:
--------------
--------------
--
--
-- The core has two interrupt sources tied to a single external irq line. The
-- The core has two interrupt sources tied to a single external irq line. The
-- sources are these:
-- sources are these:
-- 
-- 
-- -# Receiver interrupt: Raised when the stop bit is sampled and determined 
-- -# Receiver interrupt: Raised when the stop bit is sampled and determined 
--    to be valid (about the middle of the bit period).
--    to be valid (about the middle of the bit period).
--    If the stop bit is not valid (not high) then the interrupt is not 
--    If the stop bit is not valid (not high) then the interrupt is not 
--    triggered. If a start bit is determined to be spurious (i.e. the falling
--    triggered. If a start bit is determined to be spurious (i.e. the falling
--    edge is detected but the bit value when sampled is not 0) then the
--    edge is detected but the bit value when sampled is not 0) then the
c
--    interrupt is not triggered.
--    This interrupt sets flag RxIrw in the status register.
--    This interrupt sets flag RxIrw in the status register.
-- -# Transmitter interrupt: Raised at the end of the transmission of the stop
-- -# Transmitter interrupt: Raised at the end of the transmission of the stop
--    bit.
--    bit.
--    This interrupt sets flag TxIrq in the status register 1 clock cycle after
--    This interrupt sets flag TxIrq in the status register 1 clock cycle after
--    the interrupt is raised.
--    the interrupt is raised.
-- 
-- 
-- The core does not have any interrupt enable mask. If any interrupt source 
-- The core does not have any interrupt enable mask. If any interrupt source 
-- triggers, the output irq_o is asserted for one cycle. This is all the extent 
-- triggers, the output irq_o is asserted for one cycle. This is all the extent 
-- of the interrupt processing done by this module: this UART needs a separate 
-- of the interrupt processing done by this module: this UART needs a separate 
-- interrupt controller to interface the light8080 core.
-- interrupt controller to interface the light8080 core.
-- 
-- 
-- Error detection:
-- Error detection:
-------------------
-------------------
--
--
-- The core is capable of detecting and recovering from these error conditions:
-- The core is capable of detecting and recovering from these error conditions:
-- 
-- 
-- -# When a start bit is determined to be spurious (i.e. the falling edge is 
-- -# When a start bit is determined to be spurious (i.e. the falling edge is 
--    detected but the bit value when sampled is not 0) then the core returns to
--    detected but the bit value when sampled is not 0) then the core returns to
--    its idle state (waiting for a new start bit).
--    its idle state (waiting for a new start bit).
-- -# If a stop bit is determined to be invalid (not 1 when sampled), the 
-- -# If a stop bit is determined to be invalid (not 1 when sampled), the 
--    reception interrupt is not triggered and the received byte is discarded.
--    reception interrupt is not triggered and the received byte is discarded.
-- -# When the 3 samples taken from the center of a bit period are not equal, 
-- -# When the 3 samples taken from the center of a bit period are not equal, 
--    the bit value is decided by majority.
--    the bit value is decided by majority.
-- 
-- 
-- In none of the 3 cases does the core raise any error flag. It would be very 
-- In none of the 3 cases does the core raise any error flag. It would be very 
-- easy to include those flags in the core, but it would take a lot more time 
-- easy to include those flags in the core, but it would take a lot more time 
-- to test them minimally and that's why they haven't been included.
-- to test them minimally and that's why they haven't been included.
--
--
-- Status register flags:
-- Status register flags:
-------------------------
-------------------------
--
--
--      7       6       5       4       3       2       1       0
--      7       6       5       4       3       2       1       0
--  +-------+-------+-------+-------+-------+-------+-------+-------+
--  +-------+-------+-------+-------+-------+-------+-------+-------+
--  |   0   |   0   | RxIrq | TxIrq |   0   |   0   | RxRdy | TxRdy |
--  |   0   |   0   | RxIrq | TxIrq |   0   |   0   | RxRdy | TxRdy |
--  +-------+-------+-------+-------+-------+-------+-------+-------+
--  +-------+-------+-------+-------+-------+-------+-------+-------+
--      h       h      W1C     W1C      h       h       r       r     
--      h       h      W1C     W1C      h       h       r       r     
--
--
--  Bits marked 'h' are hardwired and can't be modified. 
--  Bits marked 'h' are hardwired and can't be modified. 
--  Bits marked 'r' are read only; they are set and clear by the core.
--  Bits marked 'r' are read only; they are set and clear by the core.
--  Bits marked W1C ('Write 1 Clear') are set by the core when an interrupt 
--  Bits marked W1C ('Write 1 Clear') are set by the core when an interrupt 
--  has been triggered and must be cleared by the software by writing a '1'.
--  has been triggered and must be cleared by the software by writing a '1'.
--
--
-- -# Status bit TxRdy is high when there isn't any transmission in progress. 
-- -# Status bit TxRdy is high when there isn't any transmission in progress. 
--    It is cleared when data is written to the transmission buffer and is 
--    It is cleared when data is written to the transmission buffer and is 
--    raised at the same time the transmission interrupt is triggered.
--    raised at the same time the transmission interrupt is triggered.
-- -# Status bit RxRdy is raised at the same time the receive interrupt is
-- -# Status bit RxRdy is raised at the same time the receive interrupt is
--    triggered and is cleared when the data register is read.
--    triggered and is cleared when the data register is read.
-- -# Status bit TxIrq is raised when the transmission interrupt is triggered 
-- -# Status bit TxIrq is raised when the transmission interrupt is triggered 
--    and is cleared when a 1 is written to it.
--    and is cleared when a 1 is written to it.
-- -# Status bit RxIrq is raised when the reception interrupt is triggered 
-- -# Status bit RxIrq is raised when the reception interrupt is triggered 
--    and is cleared when a 1 is written to it.
--    and is cleared when a 1 is written to it.
--
--
-- When writing to the status/control registers, only flags TxIrq and RxIrq are
-- When writing to the status/control registers, only flags TxIrq and RxIrq are
-- affected, and only when writing a '1' as explained above. All other flags 
-- affected, and only when writing a '1' as explained above. All other flags 
-- are read-only.
-- are read-only.
--
--
-- Baud rate configuration:
-- Baud rate configuration:
---------------------------
---------------------------
--
--
-- The baud rate is determined by the value of 14-bit register 'bit_period_reg'.
-- The baud rate is determined by the value of 14-bit register 'bit_period_reg'.
-- This register holds the length of the bit period in clock cycles and its
-- This register holds the length of the bit period in clock cycles and its
-- value may be hardcoded or configured at run time.
-- value may be hardcoded or configured at run time.
--
--
-- When generic HARDWIRED is true, bit_period_reg is hardwired with a value 
-- When generic HARDWIRED is true, bit_period_reg is hardwired with a value 
-- computed from the value of generic BAUD_RATE. The bit period computation 
-- computed from the value of generic BAUD_RATE. The bit period computation 
-- needs to know the master clock rate, which should be given in generic 
-- needs to know the master clock rate, which should be given in generic 
-- CLOCK_RATE.
-- CLOCK_RATE.
-- Writes to the baud registers when HARDWIRED is true will be ignored.
-- Writes to the baud registers when HARDWIRED is true will be ignored.
--
--
-- When generic HARDWIRED is false, generics BAUD_RATE and CLOCK_RATE determine 
-- When generic HARDWIRED is false, generics BAUD_RATE and CLOCK_RATE determine 
-- the reset value of bit_period_reg, but the register can be changed at run 
-- the reset value of bit_period_reg, but the register can be changed at run 
-- time by writing at addresses [10b] and [11b], which access the low and high 
-- time by writing at addresses [10b] and [11b], which access the low and high 
-- bytes of the register, respectively.
-- bytes of the register, respectively.
-- Reading from those register addresses returns the value of the status 
-- Reading from those register addresses returns the value of the status 
-- register (a LUT saving measure) so the registers are effectively write-only.
-- register (a LUT saving measure) so the registers are effectively write-only.
--
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Core interface signals:
-- Core interface signals:
--
--
-- clk_i:     Clock input, active rising edge.
-- clk_i:     Clock input, active rising edge.
-- reset_i:   Synchronous reset.
-- reset_i:   Synchronous reset.
-- txd_o:     TxD UART output.
-- txd_o:     TxD UART output.
-- rxd_i:     RxD UART input -- synchronization logic included.
-- rxd_i:     RxD UART input -- synchronization logic included.
-- irq_o:     Interrupt output, asserted for 1 cycle when triggered.
-- irq_o:     Interrupt output, asserted for 1 cycle when triggered.
-- data_i:    Data bus, input.
-- data_i:    Data bus, input.
-- data_o:    Data bus, output.
-- data_o:    Data bus, output.
-- addr_i:    Register selection address (see above).
-- addr_i:    Register selection address (see above).
-- wr_i:      Write enable input.
-- wr_i:      Write enable input.
-- rd_i:      Read enable input.
-- rd_i:      Read enable input.
-- ce_i:      Chip enable, must be active at the same time as wr_i or rd_i.
-- ce_i:      Chip enable, must be active at the same time as wr_i or rd_i.
-- 
-- 
--
--
-- A detailed explanation of the interface timing will not be given. The core 
-- A detailed explanation of the interface timing will not be given. The core 
-- reads and writes like a synchronous memory. There's usage examples in other 
-- reads and writes like a synchronous memory. There's usage examples in other 
-- project files.
-- project files.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
 
entity uart is
entity uart is
  generic (
  generic (
    HARDWIRED     : boolean := true;  -- Baud rate hardwired to constant value 
    HARDWIRED     : boolean := true;  -- Baud rate hardwired to constant value 
    BAUD_RATE     : integer := 19200; -- Default (or hardwired) baud rate 
    BAUD_RATE     : integer := 19200; -- Default (or hardwired) baud rate 
    CLOCK_FREQ    : integer := 50E6); -- Clock rate
    CLOCK_FREQ    : integer := 50E6); -- Clock rate
    port (
    port (
        rxd_i     : in std_logic;
        rxd_i     : in std_logic;
        txd_o     : out std_logic;
        txd_o     : out std_logic;
 
 
        irq_o     : out std_logic;
        irq_o     : out std_logic;
 
 
        data_i    : in std_logic_vector(7 downto 0);
        data_i    : in std_logic_vector(7 downto 0);
        data_o    : out std_logic_vector(7 downto 0);
        data_o    : out std_logic_vector(7 downto 0);
 
 
        addr_i    : in std_logic_vector(1 downto 0);
        addr_i    : in std_logic_vector(1 downto 0);
        wr_i      : in std_logic;
        wr_i      : in std_logic;
        rd_i      : in std_logic;
        rd_i      : in std_logic;
        ce_i      : in std_logic;
        ce_i      : in std_logic;
 
 
        clk_i     : in std_logic;
        clk_i     : in std_logic;
        reset_i   : in std_logic);
        reset_i   : in std_logic);
end uart;
end uart;
 
 
architecture hardwired of uart is
architecture hardwired of uart is
 
 
-- Bit period expressed in master clock cycles
-- Bit period expressed in master clock cycles
constant DEFAULT_BIT_PERIOD : integer := (CLOCK_FREQ / BAUD_RATE);
constant DEFAULT_BIT_PERIOD : integer := (CLOCK_FREQ / BAUD_RATE);
 
 
-- Bit sampling period is 1/16 of the baud rate.
-- Bit sampling period is 1/16 of the baud rate.
constant DEFAULT_SAMPLING_PERIOD : integer := DEFAULT_BIT_PERIOD / 16;
constant DEFAULT_SAMPLING_PERIOD : integer := DEFAULT_BIT_PERIOD / 16;
 
 
 
 
 
 
--##############################################################################
--##############################################################################
 
 
-- Common signals
-- Common signals
 
 
signal reset :            std_logic;
signal reset :            std_logic;
signal clk :              std_logic;
signal clk :              std_logic;
 
 
 
 
signal bit_period_reg :   unsigned(13 downto 0);
signal bit_period_reg :   unsigned(13 downto 0);
signal sampling_period :  unsigned(9 downto 0);
signal sampling_period :  unsigned(9 downto 0);
 
 
 
 
-- Interrupt & status register signals
-- Interrupt & status register signals
 
 
signal tx_irq_flag :      std_logic;
signal tx_irq_flag :      std_logic;
signal rx_irq_flag :      std_logic;
signal rx_irq_flag :      std_logic;
signal load_stat_reg :    std_logic;
signal load_stat_reg :    std_logic;
signal load_tx_reg :      std_logic;
signal load_tx_reg :      std_logic;
 
 
-- Receiver signals
-- Receiver signals
signal rxd_q :            std_logic;
signal rxd_q :            std_logic;
signal tick_ctr :         unsigned(3 downto 0);
signal tick_ctr :         unsigned(3 downto 0);
signal state :            unsigned(3 downto 0);
signal state :            unsigned(3 downto 0);
signal next_state :       unsigned(3 downto 0);
signal next_state :       unsigned(3 downto 0);
signal start_bit_detected : std_logic;
signal start_bit_detected : std_logic;
signal reset_tick_ctr :   std_logic;
signal reset_tick_ctr :   std_logic;
signal stop_bit_sampled : std_logic;
signal stop_bit_sampled : std_logic;
signal load_rx_buffer :   std_logic;
signal load_rx_buffer :   std_logic;
signal stop_error :       std_logic;
signal stop_error :       std_logic;
signal samples :          std_logic_vector(2 downto 0);
signal samples :          std_logic_vector(2 downto 0);
signal sampled_bit :      std_logic;
signal sampled_bit :      std_logic;
signal do_shift :         std_logic;
signal do_shift :         std_logic;
signal rx_buffer :        std_logic_vector(7 downto 0);
signal rx_buffer :        std_logic_vector(7 downto 0);
signal rx_shift_reg :     std_logic_vector(9 downto 0);
signal rx_shift_reg :     std_logic_vector(9 downto 0);
signal tick_ctr_enable :  std_logic;
signal tick_ctr_enable :  std_logic;
signal tick_baud_ctr :    unsigned(10 downto 0);
signal tick_baud_ctr :    unsigned(10 downto 0);
 
 
signal rx_rdy_flag :      std_logic;
signal rx_rdy_flag :      std_logic;
signal rx_irq :           std_logic;
signal rx_irq :           std_logic;
signal set_rx_rdy_flag :  std_logic;
signal set_rx_rdy_flag :  std_logic;
signal rxd :              std_logic;
signal rxd :              std_logic;
 
 
signal read_rx :          std_logic;
signal read_rx :          std_logic;
signal status :           std_logic_vector(7 downto 0);
signal status :           std_logic_vector(7 downto 0);
 
 
-- Transmitter signals 
-- Transmitter signals 
 
 
signal tx_counter :       unsigned(13 downto 0);
signal tx_counter :       unsigned(13 downto 0);
signal tx_data :          std_logic_vector(10 downto 0);
signal tx_data :          std_logic_vector(10 downto 0);
signal tx_ctr_bit :       unsigned(3 downto 0);
signal tx_ctr_bit :       unsigned(3 downto 0);
signal tx_busy :          std_logic;
signal tx_busy :          std_logic;
signal tx_irq :           std_logic;
signal tx_irq :           std_logic;
 
 
 
 
 
 
begin
begin
 
 
-- Rename the most commonly used inputs to get rid of the i/o suffix
-- Rename the most commonly used inputs to get rid of the i/o suffix
clk <= clk_i;
clk <= clk_i;
reset <= reset_i;
reset <= reset_i;
rxd <= rxd_i;
rxd <= rxd_i;
 
 
 
 
-- Serial port status byte -- only 2 status flags
-- Serial port status byte -- only 2 status flags
status <=
status <=
    "00" & rx_irq_flag & tx_irq_flag &  -- Interrupt flags
    "00" & rx_irq_flag & tx_irq_flag &  -- Interrupt flags
    "00" & rx_rdy_flag & (not tx_busy); -- State flags
    "00" & rx_rdy_flag & (not tx_busy); -- State flags
 
 
-- Read register multiplexor
-- Read register multiplexor
with addr_i select data_o <=
with addr_i select data_o <=
    rx_buffer   when "00",
    rx_buffer   when "00",
    status      when others;
    status      when others;
 
 
 
 
load_tx_reg <= '1' when wr_i = '1' and ce_i = '1' and addr_i = "00" else '0';
load_tx_reg <= '1' when wr_i = '1' and ce_i = '1' and addr_i = "00" else '0';
load_stat_reg <= '1' when wr_i = '1' and ce_i = '1' and addr_i = "01" else '0';
load_stat_reg <= '1' when wr_i = '1' and ce_i = '1' and addr_i = "01" else '0';
read_rx <= '1' when rd_i = '1' and ce_i = '1' else '0';
read_rx <= '1' when rd_i = '1' and ce_i = '1' else '0';
 
 
rx_irq <= set_rx_rdy_flag;
rx_irq <= set_rx_rdy_flag;
 
 
irq_o <= rx_irq or tx_irq;
irq_o <= rx_irq or tx_irq;
 
 
interrupt_flags:
interrupt_flags:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset = '1' then
    if reset = '1' then
      rx_irq_flag <= '0';
      rx_irq_flag <= '0';
      tx_irq_flag <= '0';
      tx_irq_flag <= '0';
    else
    else
      if set_rx_rdy_flag='1' then
      if set_rx_rdy_flag='1' then
        rx_irq_flag <= '1';
        rx_irq_flag <= '1';
      elsif load_stat_reg='1' and data_i(5)='1' then
      elsif load_stat_reg='1' and data_i(5)='1' then
        rx_irq_flag <= '0';
        rx_irq_flag <= '0';
      end if;
      end if;
      if tx_irq='1' then
      if tx_irq='1' then
        tx_irq_flag <= '1';
        tx_irq_flag <= '1';
      elsif load_stat_reg='1' and data_i(4)='1' then
      elsif load_stat_reg='1' and data_i(4)='1' then
        tx_irq_flag <= '0';
        tx_irq_flag <= '0';
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process interrupt_flags;
end process interrupt_flags;
 
 
 
 
baud_rate_registers:
baud_rate_registers:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset = '1' then
    if reset = '1' then
      bit_period_reg <= to_unsigned(DEFAULT_BIT_PERIOD,14);
      bit_period_reg <= to_unsigned(DEFAULT_BIT_PERIOD,14);
    else
    else
      if wr_i = '1' and ce_i = '1' then
      if wr_i = '1' and ce_i = '1' then
        if addr_i = "10" then
        if addr_i = "10" then
          bit_period_reg(7 downto 0) <= unsigned(data_i);
          bit_period_reg(7 downto 0) <= unsigned(data_i);
        elsif addr_i = "11" then
        elsif addr_i = "11" then
          bit_period_reg(13 downto 8) <= unsigned(data_i(5 downto 0));
          bit_period_reg(13 downto 8) <= unsigned(data_i(5 downto 0));
        end if;
        end if;
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process baud_rate_registers;
end process baud_rate_registers;
 
 
sampling_period <= bit_period_reg(13 downto 4);
sampling_period <= bit_period_reg(13 downto 4);
 
 
 
 
-- Receiver --------------------------------------------------------------------
-- Receiver --------------------------------------------------------------------
 
 
baud_counter:
baud_counter:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset='1' then
    if reset='1' then
      tick_baud_ctr <= (others => '0');
      tick_baud_ctr <= (others => '0');
    else
    else
      if tick_baud_ctr=sampling_period then
      if tick_baud_ctr=sampling_period then
        tick_baud_ctr <= (others => '0');
        tick_baud_ctr <= (others => '0');
      else
      else
        tick_baud_ctr <= tick_baud_ctr + 1;
        tick_baud_ctr <= tick_baud_ctr + 1;
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process baud_counter;
end process baud_counter;
 
 
tick_ctr_enable<= '1' when tick_baud_ctr=sampling_period else '0';
tick_ctr_enable<= '1' when tick_baud_ctr=sampling_period else '0';
 
 
-- Register RxD at the bit sampling rate -- 16 times the baud rate. 
-- Register RxD at the bit sampling rate -- 16 times the baud rate. 
rxd_input_register:
rxd_input_register:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset='1' then
    if reset='1' then
      rxd_q <= '0';
      rxd_q <= '0';
    else
    else
      if tick_ctr_enable='1' then
      if tick_ctr_enable='1' then
        rxd_q <= rxd;
        rxd_q <= rxd;
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process rxd_input_register;
end process rxd_input_register;
 
 
-- We detect the start bit when...
-- We detect the start bit when...
start_bit_detected <= '1' when
start_bit_detected <= '1' when
      state="0000" and        -- ...we're waiting for the start bit...
      state="0000" and        -- ...we're waiting for the start bit...
      rxd_q='1' and rxd='0'   -- ...and we see RxD going 1-to-0
      rxd_q='1' and rxd='0'   -- ...and we see RxD going 1-to-0
      else '0';
      else '0';
 
 
-- As soon as we detect the start bit we synchronize the bit sampler to 
-- As soon as we detect the start bit we synchronize the bit sampler to 
-- the start bit's falling edge.
-- the start bit's falling edge.
reset_tick_ctr <= '1' when start_bit_detected='1' else '0';
reset_tick_ctr <= '1' when start_bit_detected='1' else '0';
 
 
-- We have seen the end of the stop bit when...
-- We have seen the end of the stop bit when...
stop_bit_sampled <= '1' when
stop_bit_sampled <= '1' when
      state="1010" and        -- ...we're in the stop bit period...
      state="1010" and        -- ...we're in the stop bit period...
      tick_ctr="1011"         -- ...and we get the 11th sample in the bit period
      tick_ctr="1011"         -- ...and we get the 11th sample in the bit period
      else '0';
      else '0';
 
 
-- Load the RX buffer with the shift register when...
-- Load the RX buffer with the shift register when...
load_rx_buffer <= '1' when
load_rx_buffer <= '1' when
      stop_bit_sampled='1' and  -- ...we've just seen the end of the stop bit...
      stop_bit_sampled='1' and  -- ...we've just seen the end of the stop bit...
      sampled_bit='1'           -- ...and its value is correct (1)
      sampled_bit='1'           -- ...and its value is correct (1)
      else '0';
      else '0';
 
 
-- Conversely, we detect a stop bit error when...   
-- Conversely, we detect a stop bit error when...   
stop_error <= '1' when
stop_error <= '1' when
      stop_bit_sampled='1' and  -- ...we've just seen the end of the stop bit...
      stop_bit_sampled='1' and  -- ...we've just seen the end of the stop bit...
      sampled_bit='0'           -- ...and its value is incorrect (0)
      sampled_bit='0'           -- ...and its value is incorrect (0)
      else '0';
      else '0';
 
 
-- tick_ctr is a counter 16 times faster than the baud rate that is aligned to 
-- tick_ctr is a counter 16 times faster than the baud rate that is aligned to 
-- the falling edge of the start bit, so that when tick_ctr=0 we're close to 
-- the falling edge of the start bit, so that when tick_ctr=0 we're close to 
-- the start of a bit period.      
-- the start of a bit period.      
bit_sample_counter:
bit_sample_counter:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset='1' then
    if reset='1' then
      tick_ctr <= "0000";
      tick_ctr <= "0000";
    else
    else
      if tick_ctr_enable='1' then
      if tick_ctr_enable='1' then
        -- Restart counter when it reaches 15 OR when the falling edge
        -- Restart counter when it reaches 15 OR when the falling edge
        -- of the start bit is detected; this is how we synchronize to the 
        -- of the start bit is detected; this is how we synchronize to the 
        -- start bit.
        -- start bit.
        if tick_ctr="1111" or reset_tick_ctr='1' then
        if tick_ctr="1111" or reset_tick_ctr='1' then
          tick_ctr <= "0000";
          tick_ctr <= "0000";
        else
        else
          tick_ctr <= tick_ctr + 1;
          tick_ctr <= tick_ctr + 1;
        end if;
        end if;
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process bit_sample_counter;
end process bit_sample_counter;
 
 
-- Main RX state machine: 
-- Main RX state machine: 
-- 0      -> waiting for start bit
-- 0      -> waiting for start bit
-- 1      -> sampling start bit
-- 1      -> sampling start bit
-- 2..9   -> sampling data bit 0 to 7
-- 2..9   -> sampling data bit 0 to 7
-- 10     -> sampling stop bit
-- 10     -> sampling stop bit
next_state <=
next_state <=
  -- Start sampling the start bit when we detect the falling edge
  -- Start sampling the start bit when we detect the falling edge
  "0001" when state="0000" and start_bit_detected='1' else
  "0001" when state="0000" and start_bit_detected='1' else
  -- Return to idle state if the start bit is not a clean 0
  -- Return to idle state if the start bit is not a clean 0
  "0000" when state="0001" and tick_ctr="1010" and sampled_bit='1' else
  "0000" when state="0001" and tick_ctr="1010" and sampled_bit='1' else
  -- Return to idle state at the end of the stop bit period
  -- Return to idle state at the end of the stop bit period
  "0000" when state="1010" and tick_ctr="1111" else
  "0000" when state="1010" and tick_ctr="1111" else
  -- Otherwise, proceed to next bit period at the end of each period
  -- Otherwise, proceed to next bit period at the end of each period
  state + 1 when tick_ctr="1111" and do_shift='1' else
  state + 1 when tick_ctr="1111" and do_shift='1' else
  state;
  state;
 
 
rx_state_machine_register:
rx_state_machine_register:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset='1' then
    if reset='1' then
      state <= "0000";
      state <= "0000";
    else
    else
      if tick_ctr_enable='1' then
      if tick_ctr_enable='1' then
        state <= next_state;
        state <= next_state;
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process rx_state_machine_register;
end process rx_state_machine_register;
 
 
-- Collect 3 RxD samples from the 3 central sampling periods of the bit period.
-- Collect 3 RxD samples from the 3 central sampling periods of the bit period.
rx_sampler:
rx_sampler:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset='1' then
    if reset='1' then
      samples <= "000";
      samples <= "000";
    else
    else
      if tick_ctr_enable='1' then
      if tick_ctr_enable='1' then
        if tick_ctr="0111" then
        if tick_ctr="0111" then
          samples(0) <= rxd;
          samples(0) <= rxd;
        end if;
        end if;
        if tick_ctr="1000" then
        if tick_ctr="1000" then
          samples(1) <= rxd;
          samples(1) <= rxd;
        end if;
        end if;
        if tick_ctr="1001" then
        if tick_ctr="1001" then
          samples(2) <= rxd;
          samples(2) <= rxd;
        end if;
        end if;
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process rx_sampler;
end process rx_sampler;
 
 
-- Decide the value of the RxD bit by majority
-- Decide the value of the RxD bit by majority
with samples select
with samples select
  sampled_bit <=  '0' when "000",
  sampled_bit <=  '0' when "000",
                  '0' when "001",
                  '0' when "001",
                  '0' when "010",
                  '0' when "010",
                  '1' when "011",
                  '1' when "011",
                  '0' when "100",
                  '0' when "100",
                  '1' when "101",
                  '1' when "101",
                  '1' when "110",
                  '1' when "110",
                  '1' when others;
                  '1' when others;
 
 
rx_buffer_register:
rx_buffer_register:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset='1' then
    if reset='1' then
      rx_buffer <= "00000000";
      rx_buffer <= "00000000";
      set_rx_rdy_flag <= '0';
      set_rx_rdy_flag <= '0';
    else
    else
      if tick_ctr_enable='1' and load_rx_buffer='1' and rx_rdy_flag='0' then
      if tick_ctr_enable='1' and load_rx_buffer='1' and rx_rdy_flag='0' then
        rx_buffer <= rx_shift_reg(8 downto 1);
        rx_buffer <= rx_shift_reg(8 downto 1);
        set_rx_rdy_flag <= '1';
        set_rx_rdy_flag <= '1';
      else
      else
        set_rx_rdy_flag <= '0';
        set_rx_rdy_flag <= '0';
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process rx_buffer_register;
end process rx_buffer_register;
 
 
rx_flag:
rx_flag:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset='1' then
    if reset='1' then
      rx_rdy_flag <= '0';
      rx_rdy_flag <= '0';
    else
    else
      if set_rx_rdy_flag='1' then
      if set_rx_rdy_flag='1' then
        rx_rdy_flag <= '1';
        rx_rdy_flag <= '1';
      else
      else
        if read_rx = '1' then
        if read_rx = '1' then
          rx_rdy_flag <= '0';
          rx_rdy_flag <= '0';
        end if;
        end if;
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process rx_flag;
end process rx_flag;
 
 
-- RX shifter control: shift in any state other than idle state (0)
-- RX shifter control: shift in any state other than idle state (0)
do_shift <= state(0) or state(1) or state(2) or state(3);
do_shift <= state(0) or state(1) or state(2) or state(3);
 
 
rx_shift_register:
rx_shift_register:
process(clk)
process(clk)
begin
begin
  if clk'event and clk='1' then
  if clk'event and clk='1' then
    if reset='1' then
    if reset='1' then
      rx_shift_reg <= "1111111111";
      rx_shift_reg <= "1111111111";
    else
    else
      if tick_ctr_enable='1' then
      if tick_ctr_enable='1' then
        if tick_ctr="1010" and do_shift='1' then
        if tick_ctr="1010" and do_shift='1' then
          rx_shift_reg(9) <= sampled_bit;
          rx_shift_reg(9) <= sampled_bit;
          rx_shift_reg(8 downto 0) <= rx_shift_reg(9 downto 1);
          rx_shift_reg(8 downto 0) <= rx_shift_reg(9 downto 1);
        end if;
        end if;
      end if;
      end if;
    end if;
    end if;
  end if;
  end if;
end process rx_shift_register;
end process rx_shift_register;
 
 
 
 
-- Transmitter -----------------------------------------------------------------
-- Transmitter -----------------------------------------------------------------
 
 
 
 
main_tx_process:
main_tx_process:
process(clk)
process(clk)
begin
begin
if clk'event and clk='1' then
if clk'event and clk='1' then
 
 
  if reset='1' then
  if reset='1' then
    tx_data <= "10111111111";
    tx_data <= "10111111111";
    tx_busy <= '0';
    tx_busy <= '0';
    tx_irq <= '0';
    tx_irq <= '0';
    tx_ctr_bit <= "0000";
    tx_ctr_bit <= "0000";
    tx_counter <= (others => '0');
    tx_counter <= (others => '0');
  elsif load_tx_reg='1' and tx_busy='0' then
  elsif load_tx_reg='1' and tx_busy='0' then
    tx_data <= "1"&data_i&"01";
    tx_data <= "1"&data_i&"01";
    tx_busy <= '1';
    tx_busy <= '1';
  else
  else
    if tx_busy='1' then
    if tx_busy='1' then
      if tx_counter = bit_period_reg then
      if tx_counter = bit_period_reg then
        tx_counter <= (others => '0');
        tx_counter <= (others => '0');
        tx_data(9 downto 0) <= tx_data(10 downto 1);
        tx_data(9 downto 0) <= tx_data(10 downto 1);
        tx_data(10) <= '1';
        tx_data(10) <= '1';
        if tx_ctr_bit = "1010" then
        if tx_ctr_bit = "1010" then
           tx_busy <= '0';
           tx_busy <= '0';
           tx_irq <= '1';
           tx_irq <= '1';
           tx_ctr_bit <= "0000";
           tx_ctr_bit <= "0000";
        else
        else
           tx_ctr_bit <= tx_ctr_bit + 1;
           tx_ctr_bit <= tx_ctr_bit + 1;
        end if;
        end if;
      else
      else
        tx_counter <= tx_counter + 1;
        tx_counter <= tx_counter + 1;
      end if;
      end if;
    else
    else
      tx_irq <= '0';
      tx_irq <= '0';
    end if;
    end if;
  end if;
  end if;
end if;
end if;
end process main_tx_process;
end process main_tx_process;
 
 
txd_o <= tx_data(0);
txd_o <= tx_data(0);
 
 
end hardwired;
end hardwired;
 
 

powered by: WebSVN 2.1.0

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