From: Jan Michel Date: Wed, 25 May 2016 09:11:01 +0000 (+0200) Subject: UART with independent send / receive X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=c1d4a875cd38a79e949bc71fdd8524bc78b8ea70;p=mdcfee.git UART with independent send / receive --- diff --git a/code/uart_sctrl.vhd b/code/uart_sctrl.vhd new file mode 100644 index 0000000..210709b --- /dev/null +++ b/code/uart_sctrl.vhd @@ -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