--- /dev/null
+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