Skip to content
Snippets Groups Projects
Select Git revision
  • master
  • blackcat
  • deepsea
3 results

uart_sctrl.vhd

Blame
  • user avatar
    Ingo Froehlich authored
    4196e161
    History
    uart_sctrl.vhd 4.98 KiB
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    library work;
    use work.trb_net_std.all;
    -- use work.version.all;
    -- 
    -- library machxo2;
    -- use machxo2.all;
    
    
    entity uart_sctrl is
      generic(
        CLOCK_SPEED : integer := 33250000;
        BAUD : integer := 115200
        
        );
      port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        UART_RX : in  std_logic;
        UART_TX : out std_logic;
        
        DATA_OUT  : out std_logic_vector(31 downto 0);
        ADDR_OUT  : out std_logic_vector(7 downto 0);
        WRITE_OUT : out std_logic;
        READ_OUT  : out std_logic;
        
        DATA_IN   : in  std_logic_vector(31 downto 0);
        READY_IN  : in  std_logic;
        BUSY_OUT  : out std_logic;
        
        DEBUG   : out std_logic_vector(15 downto 0)
        );
    end entity;
    
    
    architecture uart_sctrl_arch of uart_sctrl is
    
    constant CLK_DIV : integer := CLOCK_SPEED/BAUD;
    
    signal rx_data   : std_logic_vector(7 downto 0);
    signal tx_data   : std_logic_vector(7 downto 0);
    signal rx_ready  : std_logic;
    signal tx_send   : std_logic;
    signal tx_ready  : std_logic;
    signal bytecount   : integer range 0 to 9;
    signal txbytecount : integer range 0 to 7;
    type   rx_state_t is (IDLE,START,START2,DO_COMMAND);
    type   tx_state_t is (DO_READ,SEND_BYTE1,SEND_BYTE2,SEND_BYTE3,SEND_TERM,SEND_FINISH, SEND_WAIT);
    signal state     : rx_state_t;
    signal txstate   : tx_state_t;
    signal txbuf     : unsigned(7 downto 0);
    signal addr_data : std_logic_vector(39 downto 0);
    signal addr_data_tx : std_logic_vector(31 downto 0);
    
    signal timer     : unsigned(25 downto 0) := (others => '0');
    signal timeout   : std_logic := '0';
    signal cmd_wr    : std_logic := '0';
    signal cmd_rd    : std_logic := '0';
    
    begin
    
    
    THE_RX : entity work.uart_rec
      port map(
        CLK_DIV      => CLK_DIV,
        CLK          => CLK,
        RST          => RESET,
        RX           => UART_RX,
        DATA_OUT     => rx_data,
        DATA_WAITING => rx_ready
        );
    
    THE_TX : entity work.uart_trans
      port map(
        CLK_DIV      => CLK_DIV,
        CLK          => CLK,
        RST          => RESET,
        DATA_IN      => tx_data,
        SEND         => tx_send,
        READY        => tx_ready,
        TX           => UART_TX
        );
        
    PROC_RX : process 
      variable tmp2 : unsigned(7 downto 0);
    begin
      wait until rising_edge(CLK);
      READ_OUT  <= '0';
      WRITE_OUT <= '0';
      timer     <= timer + 1;
      case state is
        when IDLE =>
          cmd_rd <= '0';
          cmd_wr <= '0';
          bytecount  <= 9;
          timer  <= (others => '0');
          if rx_ready = '1' then
            state <= START;
            if rx_data = x"52" then
              cmd_rd <= '1';
            elsif rx_data = x"57" then
              cmd_wr <= '1';
            else
              state <= IDLE;
            end if;
          end if;
    
        when START =>
          if rx_data >= x"40" then  
            tmp2 := unsigned(rx_data) + x"09";
          else
            tmp2 := unsigned(rx_data);
          end if;
          if rx_ready = '1' then
            state <= START2;
          end if;      
            
        when START2 =>    
          addr_data(bytecount*4+3 downto bytecount*4) <= std_logic_vector(tmp2(3 downto 0));
          bytecount <= bytecount - 1;
          
          if (bytecount = 0 and cmd_wr = '1') or (bytecount = 8 and cmd_rd = '1') then
            state <= DO_COMMAND;
          else
            state <= START;
          end if;
          
        when DO_COMMAND =>
          WRITE_OUT <= cmd_wr;
          READ_OUT  <= cmd_rd;
          state <= IDLE;
      end case;
          
      if RESET = '1' or timeout = '1' then
        state <= IDLE;
      end if;
    end process;  
          
          
    PROC_TX : process begin
      wait until rising_edge(CLK);
      tx_send <= '0';
      case txstate is
    --Read cycle
        when DO_READ =>
          if READY_IN = '1' then
            addr_data_tx(31 downto 0) <= DATA_IN;
            tx_send <= '1';
            txbuf <= x"52";
            txstate   <= SEND_BYTE1;
            txbytecount <= 7;
          end if;
    
        when SEND_BYTE1 =>
          txbuf <= x"0" & unsigned(addr_data_tx(txbytecount*4+3 downto txbytecount*4));
          txstate <= SEND_BYTE2;
          
        when SEND_BYTE2 =>     
          if txbuf(3 downto 0) > x"9" then
            txbuf <= txbuf + x"41" - x"0a";
          else
            txbuf <= txbuf + x"30";
          end if;     
          txstate <= SEND_BYTE3;
        
        
        when SEND_BYTE3 =>
          
          if tx_ready = '1' then
            tx_send <= '1';
            if txbytecount = 0 then
              txstate <= SEND_TERM;
            else
              txbytecount <= txbytecount - 1;
              txstate <= SEND_BYTE1;
            end if;      
          end if;
    
          
          
        when SEND_TERM=>
          if tx_ready = '1' then
            tx_send <= '1';
            txbuf <= x"0d";
            txstate   <= SEND_FINISH;
          end if;
        when SEND_FINISH=>
          if tx_ready = '1' then
            tx_send <= '1';
            txbuf <= x"0a";
            txstate   <= SEND_WAIT;
          end if;
        when SEND_WAIT =>
          if tx_ready = '1' then
            txstate <= DO_READ;
          end if;  
      end case;
      if RESET = '1' then
        txstate <= DO_READ;
      end if;
    
    end process;
    
    DATA_OUT  <= addr_data(31 downto 0);
    ADDR_OUT  <= addr_data(39 downto 32);
    tx_data <= std_logic_vector(txbuf);      
    timeout <= timer(20);
    
    BUSY_OUT <= '0' when txstate = DO_READ else '1';
    
    end architecture;