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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_uart.vhd] - Diff between revs 66 and 68

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 66 Rev 68
Line 161... Line 161...
  constant data_rx_avail_c : natural := 31; -- r/-: RX data available
  constant data_rx_avail_c : natural := 31; -- r/-: RX data available
 
 
  -- access control --
  -- access control --
  signal acc_en : std_ulogic; -- module access enable
  signal acc_en : std_ulogic; -- module access enable
  signal addr   : std_ulogic_vector(31 downto 0); -- access address
  signal addr   : std_ulogic_vector(31 downto 0); -- access address
  signal wr_en  : std_ulogic; -- word write enable
  signal wren   : std_ulogic; -- word write enable
  signal rd_en  : std_ulogic; -- read enable
  signal rden   : std_ulogic; -- read enable
 
 
  -- clock generator --
  -- clock generator --
  signal uart_clk : std_ulogic;
  signal uart_clk : std_ulogic;
 
 
  -- numbers of bits in transmission frame --
  -- numbers of bits in transmission frame --
Line 179... Line 179...
  -- UART transmitter --
  -- UART transmitter --
  type tx_state_t is (S_TX_IDLE, S_TX_GET, S_TX_CHECK, S_TX_TRANSMIT, S_TX_SIM);
  type tx_state_t is (S_TX_IDLE, S_TX_GET, S_TX_CHECK, S_TX_TRANSMIT, S_TX_SIM);
  type tx_engine_t is record
  type tx_engine_t is record
    state    : tx_state_t;
    state    : tx_state_t;
    busy     : std_ulogic;
    busy     : std_ulogic;
 
    done     : std_ulogic;
    bitcnt   : std_ulogic_vector(03 downto 0);
    bitcnt   : std_ulogic_vector(03 downto 0);
    sreg     : std_ulogic_vector(10 downto 0);
    sreg     : std_ulogic_vector(10 downto 0);
    baud_cnt : std_ulogic_vector(11 downto 0);
    baud_cnt : std_ulogic_vector(11 downto 0);
    cts      : std_ulogic; -- allow new transmission when 1
    cts      : std_ulogic; -- allow new transmission when 1
  end record;
  end record;
Line 190... Line 191...
 
 
  -- UART receiver --
  -- UART receiver --
  type rx_state_t is (S_RX_IDLE, S_RX_RECEIVE);
  type rx_state_t is (S_RX_IDLE, S_RX_RECEIVE);
  type rx_engine_t is record
  type rx_engine_t is record
    state    : rx_state_t;
    state    : rx_state_t;
 
    done     : std_ulogic;
    sync     : std_ulogic_vector(04 downto 0);
    sync     : std_ulogic_vector(04 downto 0);
    bitcnt   : std_ulogic_vector(03 downto 0);
    bitcnt   : std_ulogic_vector(03 downto 0);
    sreg     : std_ulogic_vector(09 downto 0);
    sreg     : std_ulogic_vector(09 downto 0);
    baud_cnt : std_ulogic_vector(11 downto 0);
    baud_cnt : std_ulogic_vector(11 downto 0);
    overr    : std_ulogic;
    overr    : std_ulogic;
Line 225... Line 227...
    free  : std_ulogic; -- free entry available?
    free  : std_ulogic; -- free entry available?
    half  : std_ulogic; -- half full
    half  : std_ulogic; -- half full
  end record;
  end record;
  signal rx_buffer : rx_buffer_t;
  signal rx_buffer : rx_buffer_t;
 
 
 
  -- interrupt generator --
 
  type irq_t is record
 
    pending : std_ulogic; -- pending interrupt request
 
    set     : std_ulogic;
 
    clr     : std_ulogic;
 
  end record;
 
  signal rx_irq, tx_irq : irq_t;
 
 
begin
begin
 
 
  -- Sanity Checks --------------------------------------------------------------------------
  -- Sanity Checks --------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  assert not (is_power_of_two_f(UART_RX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: UART" &
  assert not (is_power_of_two_f(UART_RX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: UART" &
Line 239... Line 249...
 
 
  -- Access Control -------------------------------------------------------------------------
  -- Access Control -------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = uart_id_base_c(hi_abb_c downto lo_abb_c)) else '0';
  acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = uart_id_base_c(hi_abb_c downto lo_abb_c)) else '0';
  addr   <= uart_id_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
  addr   <= uart_id_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
  wr_en  <= acc_en and wren_i;
  wren   <= acc_en and wren_i;
  rd_en  <= acc_en and rden_i;
  rden   <= acc_en and rden_i;
 
 
 
 
  -- Read/Write Access ----------------------------------------------------------------------
  -- Read/Write Access ----------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  rw_access: process(clk_i)
  rw_access: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      -- bus access acknowledge --
      -- bus access acknowledge --
      ack_o <= wr_en or rd_en;
      ack_o <= wren or rden;
 
 
      -- write access --
      -- write access --
      if (wr_en = '1') then
      if (wren = '1') then
        if (addr = uart_id_ctrl_addr_c) then
        if (addr = uart_id_ctrl_addr_c) then
          ctrl <= (others => '0');
          ctrl <= (others => '0');
          ctrl(ctrl_baud11_c downto ctrl_baud00_c) <= data_i(ctrl_baud11_c downto ctrl_baud00_c);
          ctrl(ctrl_baud11_c downto ctrl_baud00_c) <= data_i(ctrl_baud11_c downto ctrl_baud00_c);
          ctrl(ctrl_sim_en_c)                      <= data_i(ctrl_sim_en_c);
          ctrl(ctrl_sim_en_c)                      <= data_i(ctrl_sim_en_c);
          ctrl(ctrl_pmode1_c downto ctrl_pmode0_c) <= data_i(ctrl_pmode1_c downto ctrl_pmode0_c);
          ctrl(ctrl_pmode1_c downto ctrl_pmode0_c) <= data_i(ctrl_pmode1_c downto ctrl_pmode0_c);
Line 269... Line 279...
        end if;
        end if;
      end if;
      end if;
 
 
      -- read access --
      -- read access --
      data_o <= (others => '0');
      data_o <= (others => '0');
      if (rd_en = '1') then
      if (rden = '1') then
        if (addr = uart_id_ctrl_addr_c) then
        if (addr = uart_id_ctrl_addr_c) then
          data_o(ctrl_baud11_c downto ctrl_baud00_c) <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
          data_o(ctrl_baud11_c downto ctrl_baud00_c) <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
          data_o(ctrl_sim_en_c)                      <= ctrl(ctrl_sim_en_c);
          data_o(ctrl_sim_en_c)                      <= ctrl(ctrl_sim_en_c);
          data_o(ctrl_pmode1_c downto ctrl_pmode0_c) <= ctrl(ctrl_pmode1_c downto ctrl_pmode0_c);
          data_o(ctrl_pmode1_c downto ctrl_pmode0_c) <= ctrl(ctrl_pmode1_c downto ctrl_pmode0_c);
          data_o(ctrl_prsc2_c  downto ctrl_prsc0_c)  <= ctrl(ctrl_prsc2_c  downto ctrl_prsc0_c);
          data_o(ctrl_prsc2_c  downto ctrl_prsc0_c)  <= ctrl(ctrl_prsc2_c  downto ctrl_prsc0_c);
Line 344... Line 354...
 
 
  -- control --
  -- control --
  tx_buffer.clear <= not ctrl(ctrl_en_c);
  tx_buffer.clear <= not ctrl(ctrl_en_c);
 
 
  -- write access --
  -- write access --
  tx_buffer.we    <= '1' when (wr_en = '1') and (addr = uart_id_rtx_addr_c) else '0';
  tx_buffer.we    <= '1' when (wren = '1') and (addr = uart_id_rtx_addr_c) else '0';
  tx_buffer.wdata <= data_i;
  tx_buffer.wdata <= data_i;
 
 
 
 
  -- UART Transmitter Engine ----------------------------------------------------------------
  -- UART Transmitter Engine ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 356... Line 366...
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      -- defaults --
      -- defaults --
      uart_txd_o   <= '1'; -- keep TX line idle (=high) if waiting for permission to start sending (->CTS)
      uart_txd_o   <= '1'; -- keep TX line idle (=high) if waiting for permission to start sending (->CTS)
      tx_buffer.re <= '0';
      tx_buffer.re <= '0';
 
      tx_engine.done <= '0';
 
 
      -- FSM --
      -- FSM --
      if (ctrl(ctrl_en_c) = '0') then -- disabled
      if (ctrl(ctrl_en_c) = '0') then -- disabled
        tx_engine.state <= S_TX_IDLE;
        tx_engine.state <= S_TX_IDLE;
      else
      else
Line 406... Line 417...
                tx_engine.baud_cnt <= std_ulogic_vector(unsigned(tx_engine.baud_cnt) - 1);
                tx_engine.baud_cnt <= std_ulogic_vector(unsigned(tx_engine.baud_cnt) - 1);
              end if;
              end if;
            end if;
            end if;
            uart_txd_o <= tx_engine.sreg(0);
            uart_txd_o <= tx_engine.sreg(0);
            if (or_reduce_f(tx_engine.bitcnt) = '0') then -- all bits send?
            if (or_reduce_f(tx_engine.bitcnt) = '0') then -- all bits send?
 
              tx_engine.done  <= '1'; -- sending done
              tx_engine.state <= S_TX_IDLE;
              tx_engine.state <= S_TX_IDLE;
            end if;
            end if;
 
 
          when S_TX_SIM => -- simulation mode output
          when S_TX_SIM => -- simulation mode output
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
Line 434... Line 446...
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      -- input synchronizer --
      -- input synchronizer --
      rx_engine.sync <= uart_rxd_i & rx_engine.sync(rx_engine.sync'left downto 1);
      rx_engine.sync <= uart_rxd_i & rx_engine.sync(rx_engine.sync'left downto 1);
 
 
 
      -- default --
 
      rx_engine.done <= '0';
 
 
      -- FSM --
      -- FSM --
      if (ctrl(ctrl_en_c) = '0') then -- disabled
      if (ctrl(ctrl_en_c) = '0') then -- disabled
        rx_engine.overr <= '0';
        rx_engine.overr <= '0';
        rx_engine.state <= S_RX_IDLE;
        rx_engine.state <= S_RX_IDLE;
      else
      else
Line 461... Line 476...
              else
              else
                rx_engine.baud_cnt <= std_ulogic_vector(unsigned(rx_engine.baud_cnt) - 1);
                rx_engine.baud_cnt <= std_ulogic_vector(unsigned(rx_engine.baud_cnt) - 1);
              end if;
              end if;
            end if;
            end if;
            if (or_reduce_f(rx_engine.bitcnt) = '0') then -- all bits received?
            if (or_reduce_f(rx_engine.bitcnt) = '0') then -- all bits received?
 
              rx_engine.done  <= '1'; -- receiving done
              rx_engine.state <= S_RX_IDLE;
              rx_engine.state <= S_RX_IDLE;
            end if;
            end if;
 
 
          when others => -- undefined
          when others => -- undefined
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            rx_engine.state <= S_RX_IDLE;
            rx_engine.state <= S_RX_IDLE;
 
 
        end case;
        end case;
 
 
        -- overrun flag --
        -- overrun flag --
        if (rd_en = '1') and (addr = uart_id_rtx_addr_c) then -- clear when reading data register
        if (rden = '1') and (addr = uart_id_rtx_addr_c) then -- clear when reading data register
          rx_engine.overr <= '1';
          rx_engine.overr <= '1';
        elsif (rx_buffer.we = '1') and (rx_buffer.free = '0') then -- write to full FIFO
        elsif (rx_buffer.we = '1') and (rx_buffer.free = '0') then -- write to full FIFO
          rx_engine.overr <= '0';
          rx_engine.overr <= '0';
        end if;
        end if;
      end if;
      end if;
Line 518... Line 534...
  -- read/write access --
  -- read/write access --
  rx_buffer.wdata(7 downto 0) <= rx_engine.sreg(7 downto 0) when (ctrl(ctrl_pmode1_c) = '1') else rx_engine.sreg(8 downto 1); -- RX data
  rx_buffer.wdata(7 downto 0) <= rx_engine.sreg(7 downto 0) when (ctrl(ctrl_pmode1_c) = '1') else rx_engine.sreg(8 downto 1); -- RX data
  rx_buffer.wdata(8) <= ctrl(ctrl_pmode1_c) and (xor_reduce_f(rx_engine.sreg(8 downto 0)) xor ctrl(ctrl_pmode0_c)); -- parity error flag
  rx_buffer.wdata(8) <= ctrl(ctrl_pmode1_c) and (xor_reduce_f(rx_engine.sreg(8 downto 0)) xor ctrl(ctrl_pmode0_c)); -- parity error flag
  rx_buffer.wdata(9) <= not rx_engine.sreg(9); -- frame error flag: check stop bit (error if not set)
  rx_buffer.wdata(9) <= not rx_engine.sreg(9); -- frame error flag: check stop bit (error if not set)
  rx_buffer.we <= '1' when (rx_engine.bitcnt = "0000") and (rx_engine.state = S_RX_RECEIVE) else '0'; -- RX complete
  rx_buffer.we <= '1' when (rx_engine.bitcnt = "0000") and (rx_engine.state = S_RX_RECEIVE) else '0'; -- RX complete
  rx_buffer.re <= '1' when (rd_en = '1') and (addr = uart_id_rtx_addr_c) else '0';
  rx_buffer.re <= '1' when (rden = '1') and (addr = uart_id_rtx_addr_c) else '0';
 
 
 
 
  -- Hardware Flow Control ------------------------------------------------------------------
  -- Hardware Flow Control ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  tx_engine.cts <= (not uart_cts_ff(1)) when (ctrl(ctrl_cts_en_c) = '1') else '1'; -- input is low-active, internal signal is high-active
  tx_engine.cts <= (not uart_cts_ff(1)) when (ctrl(ctrl_cts_en_c) = '1') else '1'; -- input is low-active, internal signal is high-active
Line 536... Line 552...
      uart_rts_o  <= uart_rts;
      uart_rts_o  <= uart_rts;
    end if;
    end if;
  end process flow_control_buffer;
  end process flow_control_buffer;
 
 
 
 
  -- Interrupts -----------------------------------------------------------------------------
  -- Interrupt Generator --------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  irq_generator: process(clk_i)
  irq_type: process(ctrl, tx_buffer, rx_buffer)
  begin
  begin
    if rising_edge(clk_i) then
 
      if (ctrl(ctrl_en_c) = '0') then -- no interrupts when disabled
 
        irq_txd_o <= '0';
 
        irq_rxd_o <= '0';
 
      else
 
        -- TX interrupt --
        -- TX interrupt --
        if (UART_TX_FIFO = 1) then
        if (UART_TX_FIFO = 1) then
          irq_txd_o <= tx_buffer.free; -- fire IRQ if FIFO is not full
      tx_irq.set <= tx_buffer.free; -- fire IRQ if FIFO is not full
        else
        else
          if (ctrl(ctrl_tx_irq_c) = '1') then
          if (ctrl(ctrl_tx_irq_c) = '1') then
            irq_txd_o <= not tx_buffer.half; -- fire IRQ if FIFO is less than half-full
        tx_irq.set <= not tx_buffer.half; -- fire IRQ if FIFO is less than half-full
          else
          else
            irq_txd_o <= tx_buffer.free; -- fire IRQ if FIFO is not full
        tx_irq.set <= tx_buffer.free; -- fire IRQ if FIFO is not full
          end if;
          end if;
        end if;
        end if;
 
 
        -- RX interrupt --
        -- RX interrupt --
        if (UART_RX_FIFO = 1) then
        if (UART_RX_FIFO = 1) then
          irq_rxd_o <= rx_buffer.avail; -- fire IRQ if FIFO is not empty
      rx_irq.set <= rx_buffer.avail; -- fire IRQ if FIFO is not empty
        else
        else
          if (ctrl(ctrl_rx_irq_c) = '1') then
          if (ctrl(ctrl_rx_irq_c) = '1') then
            irq_rxd_o <= rx_buffer.half; -- fire IRQ if FIFO is at least half-full
        rx_irq.set <= rx_buffer.half; -- fire IRQ if FIFO is at least half-full
          else
          else
            irq_rxd_o <= rx_buffer.avail; -- fire IRQ is FIFO is not empty
        rx_irq.set <= rx_buffer.avail; -- fire IRQ is FIFO is not empty
          end if;
          end if;
        end if;
        end if;
 
  end process irq_type;
 
 
 
  -- interrupt arbiter --
 
  irq_generator: process(clk_i)
 
  begin
 
    if rising_edge(clk_i) then
 
      if (ctrl(ctrl_en_c) = '0') then
 
        rx_irq.pending <= '0';
 
        tx_irq.pending <= '0';
 
      else
 
        -- TX --
 
        if (tx_irq.set = '1') and (tx_engine.done = '1') then -- evaluate IRQ condition when TX is done with current sending
 
          tx_irq.pending <= '1';
 
        elsif (tx_irq.clr = '1') then
 
          tx_irq.pending <= '0';
 
        end if;
 
        -- RX --
 
        if (rx_irq.set = '1') and (rx_engine.done = '1') then -- evaluate IRQ condition when RX is done with current receiving
 
          rx_irq.pending <= '1';
 
        elsif (rx_irq.clr = '1') then
 
          rx_irq.pending <= '0';
 
        end if;
      end if;
      end if;
    end if;
    end if;
  end process irq_generator;
  end process irq_generator;
 
 
 
  -- IRQ requests to CPU --
 
  irq_txd_o <= tx_irq.pending;
 
  irq_rxd_o <= rx_irq.pending;
 
 
 
  -- IRQ acknowledge --
 
  tx_irq.clr <= '1' when (tx_buffer.we = '1') or ((wren = '1') and (addr = uart_id_ctrl_addr_c)) else '0'; -- write to data reg OR write to control reg
 
  rx_irq.clr <= '1' when (rx_buffer.re = '1') or ((wren = '1') and (addr = uart_id_ctrl_addr_c)) else '0'; -- read from data reg OR write to control reg
 
 
 
 
  -- SIMULATION Transmitter -----------------------------------------------------------------
  -- SIMULATION Transmitter -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
-- pragma translate_off
-- pragma translate_off
-- synthesis translate_off
-- synthesis translate_off

powered by: WebSVN 2.1.0

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