]> jspc29.x-matter.uni-frankfurt.de Git - mdcfee.git/commitdiff
UART with independent send / receive
authorJan Michel <j.michel@gsi.de>
Wed, 25 May 2016 09:11:01 +0000 (11:11 +0200)
committerJan Michel <j.michel@gsi.de>
Wed, 25 May 2016 09:11:01 +0000 (11:11 +0200)
code/uart_sctrl.vhd [new file with mode: 0644]

diff --git a/code/uart_sctrl.vhd b/code/uart_sctrl.vhd
new file mode 100644 (file)
index 0000000..210709b
--- /dev/null
@@ -0,0 +1,214 @@
+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_ready = '1' then
+        if rx_data >= x"40" then  
+          tmp2 := unsigned(rx_data) + x"09";
+        else
+          tmp2 := unsigned(rx_data);
+        end if;
+        state <= START2;
+      end if;      
+        
+    when START2 =>    
+      addr_data(bytecount*4+3 downto bytecount*4) <= std_logic_vector(tmp2(3 downto 0));
+      if (bytecount = 0 and cmd_wr = '1') or (bytecount = 8 and cmd_rd = '1') then
+        state <= DO_COMMAND;
+      else
+        bytecount <= bytecount - 1;
+        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;
+    timer <= (others => '0');
+  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"0a";
+        txstate   <= SEND_FINISH;
+      end if;
+    when SEND_FINISH=>
+      if tx_ready = '1' then
+        tx_send <= '1';
+        txbuf <= x"0d";
+        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;
\ No newline at end of file