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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [misclib/] [tap_uart.vhd] - Rev 5

Compare with Previous | Blame | View Log

--!
--! Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
--!
--! Licensed under the Apache License, Version 2.0 (the "License");
--! you may not use this file except in compliance with the License.
--! You may obtain a copy of the License at
--!
--!     http://www.apache.org/licenses/LICENSE-2.0
--! Unless required by applicable law or agreed to in writing, software
--! distributed under the License is distributed on an "AS IS" BASIS,
--! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--! See the License for the specific language governing permissions and
--! limitations under the License.
--!
 
library ieee;
use ieee.std_logic_1164.all;
library commonlib;
use commonlib.types_common.all;
--! AMBA system bus specific library.
library ambalib;
--! AXI4 configuration constants.
use ambalib.types_amba4.all;
library misclib;
use misclib.types_misc.all;
 
entity uart_tap is
  port (
    nrst     : in std_logic;
    clk      : in std_logic;
    i_uart   : in  uart_in_type;
    o_uart   : out uart_out_type;
    i_msti   : in nasti_master_in_type;
    o_msto   : out nasti_master_out_type;
    o_mstcfg : out nasti_master_config_type
  );
end; 
 
architecture arch_uart_tap of uart_tap is
 
  constant MAGIC_ID : std_logic_vector(7 downto 0) := X"31";
  constant SCALER_DEFAULT : std_logic_vector(17 downto 0) := "111111111111111011";
  constant BAUD_DEFAULT : std_logic_vector(17 downto 0) := (others => '1');
  constant HANDSHAKE_ACK : std_logic_vector(31 downto 0) := X"0a4b4341";
 
  constant xmstconfig : nasti_master_config_type := (
     descrsize => PNP_CFG_MASTER_DESCR_BYTES,
     descrtype => PNP_CFG_TYPE_MASTER,
     vid => VENDOR_GNSSSENSOR,
     did => GNSSSENSOR_UART_TAP
  );
 
  type uart_state_type is (idle, startbit, data, stopbit);
  type dma_req_state_type is (
      DMAREQ_IDLE,
      DMAREQ_OPERATION,
      DMAREQ_ADDR,
      DMAREQ_READ,
      DMAREQ_WAIT_READ_RESP,
      DMAREQ_UART_TX,
      DMAREQ_WDATA,
      DMAREQ_WRITE
   );
 
  type registers is record
    dma : dma_bank_type;
 
    tx_data   : std_logic_vector(31 downto 0);
    tx_byte_cnt : integer range 0 to 4;
 
    dma_req_state : dma_req_state_type;
    dma_state_next : dma_req_state_type;
    dma_req_write : std_logic;
    dma_byte_cnt : integer range 0 to 7;
    dma_req_len : integer range 0 to 63;
    dma_req_addr : std_logic_vector(63 downto 0);
    dma_req_wdata : std_logic_vector(31 downto 0);
    rword_valid : std_logic;
    rword : std_logic_vector(31 downto 0);
    watchdog : integer;
  end record;
 
  signal r, rin : registers;
  signal dma_response : dma_response_type;
 
  signal w_com_dready : std_logic;   -- new byte is avaiable for read
  signal w_com_accepted : std_logic; -- new byte can be accepted;
  signal wb_com_data : std_logic_vector(7 downto 0);
  signal w_com_thempty : std_logic; -- transmitter's hold register is empty
  signal w_com_write : std_logic;
 
  component dcom_uart is
  port (
    rst    : in  std_ulogic;
    clk    : in  std_ulogic;
    i_cfg_frame : in std_logic;
    i_cfg_ovf   : in std_logic;
    i_cfg_break : in std_logic;
    i_cfg_tcnt  : in std_logic_vector(1 downto 0);
    i_cfg_rxen  : in std_logic;
    i_cfg_brate : in std_logic_vector(17 downto 0);
    i_cfg_scaler : in std_logic_vector(17 downto 0);
    o_cfg_scaler : out std_logic_vector(31 downto 0);
    o_cfg_rxen : out std_logic;
    o_cfg_txen : out std_logic;
    o_cfg_flow : out std_logic;
 
    i_com_read    	: in std_ulogic;
    i_com_write   	: in std_ulogic;
    i_com_data		: in std_logic_vector(7 downto 0);
    o_com_dready 	: out std_ulogic;
    o_com_tsempty	: out std_ulogic;
    o_com_thempty	: out std_ulogic;
    o_com_lock    	: out std_ulogic;
    o_com_enable 	: out std_ulogic;
    o_com_data		: out std_logic_vector(7 downto 0);
    ui     : in  uart_in_type;
    uo     : out uart_out_type
  );
  end component; 
 
begin
 
  comblogic : process(nrst, i_msti, i_uart, r, dma_response, w_com_dready,
                      wb_com_data, w_com_thempty)
    variable v : registers;
    variable wb_dma_request : dma_request_type;
    variable wb_dma_response : dma_response_type;
    variable wb_msto : nasti_master_out_type;
 
    variable v_com_write : std_logic;
    variable v_com_accepted : std_logic;
  begin
 
    v := r;
    wb_dma_request.valid := '0';
    wb_dma_request.ready := '0';
    wb_dma_request.write := '0';
    wb_dma_request.addr := (others => '0');
    wb_dma_request.size := "010"; -- 4 bytes
    wb_dma_request.bytes := (others => '0');
    wb_dma_request.wdata := (others => '0');
 
    v_com_accepted := '0';
    v_com_write := '0';
 
    --! DMA control
    case r.dma_req_state is
    when DMAREQ_IDLE =>
        v_com_accepted := '1';
        if w_com_dready = '1' and wb_com_data = MAGIC_ID then
            v.dma_req_state := DMAREQ_OPERATION;
        end if;
    when DMAREQ_OPERATION =>
        v_com_accepted := '1';
        if w_com_dready = '1' then
            v.dma_req_write := wb_com_data(6);
            v.dma_req_len := conv_integer(wb_com_data(5 downto 0));
            v.dma_req_state := DMAREQ_ADDR;
            v.dma_byte_cnt := 0;
        end if;
    when DMAREQ_ADDR =>
        v_com_accepted := '1';
        if w_com_dready = '1' then
            v.dma_req_addr := wb_com_data & r.dma_req_addr(63 downto 8);
            if r.dma_byte_cnt = 7 then
                if (wb_com_data & r.dma_req_addr(63 downto 40)) /= X"00000000" then
                    v.dma_req_state := DMAREQ_IDLE;
                elsif r.dma_req_write = '1' then
                    v.dma_req_state := DMAREQ_WDATA;
                    v.dma_byte_cnt := 0;
                else
                    v.dma_req_state := DMAREQ_READ;
                end if;
            else
                v.dma_byte_cnt := r.dma_byte_cnt + 1;
            end if;
        end if;
    when DMAREQ_READ =>
        wb_dma_request.valid := '1';
        wb_dma_request.write := '0';
        wb_dma_request.addr := r.dma_req_addr(CFG_NASTI_ADDR_BITS-1 downto 0);
        wb_dma_request.bytes := conv_std_logic_vector(4, 11);
        wb_dma_request.wdata := (others => '0');
        if dma_response.ready = '1' then
            v.dma_req_state := DMAREQ_WAIT_READ_RESP;
        end if;
    when DMAREQ_WAIT_READ_RESP =>
        wb_dma_request.ready := '1';
        if dma_response.valid = '1' then
            v.dma_req_state := DMAREQ_UART_TX;
            v.tx_data := dma_response.rdata(31 downto 0);
            v.tx_byte_cnt := 4;
            if r.dma_req_len = 0 then
                v.dma_state_next := DMAREQ_IDLE;
            else
                v.dma_req_len := r.dma_req_len - 1;
                v.dma_req_addr := r.dma_req_addr + 4;
                v.dma_state_next := DMAREQ_READ;
            end if;
        end if;
 
    when DMAREQ_WDATA =>
        v_com_accepted := '1';
        if w_com_dready = '1' then
            v.dma_req_wdata := wb_com_data & r.dma_req_wdata(31 downto 8);
            v.dma_byte_cnt := r.dma_byte_cnt + 1;
            if r.dma_byte_cnt = 3 then
               v.dma_req_state := DMAREQ_WRITE;
            end if;
        end if;
    when DMAREQ_WRITE =>
        wb_dma_request.valid := '1';
        wb_dma_request.write := '1';
        wb_dma_request.addr := r.dma_req_addr(CFG_NASTI_ADDR_BITS-1 downto 0);
        wb_dma_request.bytes := conv_std_logic_vector(4, 11);
        wb_dma_request.wdata := r.dma_req_wdata & r.dma_req_wdata;
        if dma_response.ready = '1' then
            if r.dma_req_len = 0 then
                v.dma_req_state := DMAREQ_UART_TX; -- Handshake ACK
                v.tx_data := HANDSHAKE_ACK;
                v.tx_byte_cnt := 4;
                v.dma_state_next := DMAREQ_IDLE;
            else
                v.dma_byte_cnt := 0;
                v.dma_req_len := r.dma_req_len - 1;
                v.dma_req_addr := r.dma_req_addr + 4;
                v.dma_req_state := DMAREQ_WDATA;
            end if;
        end if;
 
    when DMAREQ_UART_TX =>
        v_com_write := '1';
        if r.tx_byte_cnt = 0 then
            v.dma_req_state := r.dma_state_next;
        elsif w_com_thempty = '1' then
            v.tx_byte_cnt := r.tx_byte_cnt - 1;
            v.tx_data := X"00" & r.tx_data(31 downto 8);
        end if;
    when others =>
    end case;
 
 
    procedureAxi4DMA(
        i_request => wb_dma_request,
        o_response => wb_dma_response,
        i_bank => r.dma,
        o_bank => v.dma,
        i_msti => i_msti,
        o_msto => wb_msto
    );
    dma_response <= wb_dma_response;
    w_com_accepted <= v_com_accepted;
    w_com_write <= v_com_write;
 
 
    if nrst = '0' then
        v.tx_byte_cnt := 0;
        v.tx_data := (others => '0');
 
        v.dma := DMA_BANK_RESET;
        v.dma_req_state := DMAREQ_IDLE;
        v.dma_state_next := DMAREQ_IDLE;
        v.dma_req_write := '0';
        v.dma_byte_cnt := 0;
        v.dma_req_len := 0;
        v.dma_req_addr := (others => '0');
        v.dma_req_wdata := (others => '0');
    end if;
 
    rin <= v;
    o_msto <= wb_msto;
  end process;
 
  o_mstcfg <= xmstconfig;
 
  dcom0 : dcom_uart  port map (
    rst    => nrst,
    clk    => clk,
    i_cfg_frame => '0',
    i_cfg_ovf   => '0',
    i_cfg_break => '0',
    i_cfg_tcnt  => "00",
    i_cfg_rxen  => '0',
    i_cfg_brate => BAUD_DEFAULT,
    i_cfg_scaler => SCALER_DEFAULT,
    o_cfg_scaler => open,
    o_cfg_rxen => open,
    o_cfg_txen => open,
    o_cfg_flow => open,
 
    i_com_read => w_com_accepted,
    i_com_write => w_com_write,
    i_com_data	=> r.tx_data(7 downto 0),
    o_com_dready => w_com_dready,
    o_com_tsempty => open,
    o_com_thempty => w_com_thempty,
    o_com_lock => open,
    o_com_enable => open,
    o_com_data => wb_com_data,
    ui => i_uart,
    uo => o_uart
  );
 
 
  -- registers:
  regs : process(clk)
  begin 
     if rising_edge(clk) then 
        r <= rin;
     end if; 
  end process;
 
end;

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.