You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
2.8 KiB

  1. -- Copyright (c) 2022 by Torsten Meissner
  2. --
  3. -- Licensed under the Apache License, Version 2.0 (the "License");
  4. -- you may not use this file except in compliance with the License.
  5. -- You may obtain a copy of the License at
  6. --
  7. -- https://www.apache.org/licenses/LICENSE-2.0
  8. --
  9. -- Unless required by applicable law or agreed to in writing, software
  10. -- distributed under the License is distributed on an "AS IS" BASIS,
  11. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. -- See the License for the specific language governing permissions and
  13. -- limitations under the License.
  14. library ieee;
  15. use ieee.std_logic_1164.all;
  16. use ieee.numeric_std.all;
  17. entity uart_rx is
  18. generic (
  19. CLK_DIV : natural := 10
  20. );
  21. port (
  22. -- globals
  23. rst_n_i : in std_logic;
  24. clk_i : in std_logic;
  25. -- axis user interface
  26. tdata_o : out std_logic_vector(7 downto 0);
  27. tvalid_o : out std_logic;
  28. tready_i : in std_logic;
  29. -- uart interface
  30. rx_i : in std_logic
  31. );
  32. end entity uart_rx;
  33. architecture rtl of uart_rx is
  34. type t_uart_state is (IDLE, RECEIVE, VALID);
  35. signal s_uart_state : t_uart_state;
  36. signal s_clk_en : std_logic;
  37. signal s_clk_cnt : natural range 0 to CLK_DIV-1;
  38. signal s_bit_cnt : natural range 0 to tdata_o'length+1;
  39. signal s_rx_d : std_logic_vector(3 downto 0);
  40. begin
  41. ClkDivP : process (clk_i, rst_n_i) is
  42. begin
  43. if (not rst_n_i) then
  44. s_clk_cnt <= CLK_DIV-1;
  45. elsif (rising_edge(clk_i)) then
  46. if (s_uart_state = IDLE) then
  47. s_clk_cnt <= CLK_DIV-2;
  48. elsif (s_uart_state = RECEIVE) then
  49. if (s_clk_cnt = 0) then
  50. s_clk_cnt <= CLK_DIV-1;
  51. else
  52. s_clk_cnt <= s_clk_cnt - 1;
  53. end if;
  54. end if;
  55. end if;
  56. end process ClkDivP;
  57. s_clk_en <= '1' when s_uart_state = RECEIVE and s_clk_cnt = CLK_DIV/2-1 else '0';
  58. RxP : process (clk_i, rst_n_i) is
  59. begin
  60. if (not rst_n_i) then
  61. s_uart_state <= IDLE;
  62. tdata_o <= (others => '0');
  63. s_rx_d <= x"1";
  64. s_bit_cnt <= 0;
  65. elsif (rising_edge(clk_i)) then
  66. s_rx_d <= s_rx_d(2 downto 0) & rx_i;
  67. FsmL : case s_uart_state is
  68. when IDLE =>
  69. s_bit_cnt <= tdata_o'length+1;
  70. if (s_rx_d = "1000") then
  71. s_uart_state <= RECEIVE;
  72. end if;
  73. when RECEIVE =>
  74. if (s_clk_en) then
  75. if (s_bit_cnt = 0) then
  76. s_uart_state <= VALID;
  77. else
  78. tdata_o <= s_rx_d(3) & tdata_o(tdata_o'length-1 downto 1);
  79. s_bit_cnt <= s_bit_cnt - 1;
  80. end if;
  81. end if;
  82. when VALID =>
  83. if (tready_i) then
  84. s_uart_state <= IDLE;
  85. end if;
  86. end case;
  87. end if;
  88. end process RxP;
  89. tvalid_o <= '1' when s_uart_state = VALID else '0';
  90. end architecture rtl;