Library of reusable VHDL components
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.

130 lines
3.5 KiB

  1. -- Copyright (c) 2014 - 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. library libvhdl;
  18. use libvhdl.UtilsP.all;
  19. entity UartTx is
  20. generic (
  21. DATA_LENGTH : positive range 5 to 9 := 8;
  22. PARITY : boolean := true;
  23. CLK_DIV : natural := 10
  24. );
  25. port (
  26. reset_n_i : in std_logic; -- async reset
  27. clk_i : in std_logic; -- clock
  28. data_i : in std_logic_vector(DATA_LENGTH-1 downto 0); -- data input
  29. valid_i : in std_logic; -- input data valid
  30. accept_o : out std_logic; -- inpit data accepted
  31. tx_o : out std_logic -- uart tx data output
  32. );
  33. end entity UartTx;
  34. architecture rtl of UartTx is
  35. function to_integer (data : in boolean) return integer is
  36. begin
  37. if data then
  38. return 1;
  39. else
  40. return 0;
  41. end if;
  42. end function to_integer;
  43. type t_uart_state is (IDLE, SEND);
  44. signal s_uart_state : t_uart_state;
  45. signal s_data : std_logic_vector(DATA_LENGTH+1+to_integer(PARITY) downto 0);
  46. signal s_clk_en : boolean;
  47. begin
  48. ClkDivP : process (clk_i, reset_n_i) is
  49. variable v_clk_cnt : natural range 0 to CLK_DIV-1;
  50. begin
  51. if (reset_n_i = '0') then
  52. s_clk_en <= false;
  53. v_clk_cnt := CLK_DIV-1;
  54. elsif (rising_edge(clk_i)) then
  55. if (s_uart_state = IDLE) then
  56. v_clk_cnt := CLK_DIV-2;
  57. s_clk_en <= false;
  58. elsif (s_uart_state = SEND) then
  59. if (v_clk_cnt = 0) then
  60. v_clk_cnt := CLK_DIV-1;
  61. s_clk_en <= true;
  62. else
  63. v_clk_cnt := v_clk_cnt - 1;
  64. s_clk_en <= false;
  65. end if;
  66. end if;
  67. end if;
  68. end process ClkDivP;
  69. TxP : process (clk_i, reset_n_i) is
  70. variable v_bit_cnt : natural range 0 to s_data'length-1;
  71. begin
  72. if (reset_n_i = '0') then
  73. s_uart_state <= IDLE;
  74. s_data <= (0 => '1', others => '0');
  75. accept_o <= '0';
  76. v_bit_cnt := 0;
  77. elsif (rising_edge(clk_i)) then
  78. FsmL : case s_uart_state is
  79. when IDLE =>
  80. accept_o <= '1';
  81. v_bit_cnt := s_data'length-1;
  82. if (valid_i = '1' and accept_o = '1') then
  83. accept_o <= '0';
  84. if (PARITY) then
  85. s_data <= '1' & odd_parity(data_i) & data_i & '0';
  86. else
  87. s_data <= '1' & data_i & '0';
  88. end if;
  89. s_uart_state <= SEND;
  90. end if;
  91. when SEND =>
  92. if (s_clk_en) then
  93. s_data <= '1' & s_data(s_data'length-1 downto 1);
  94. if (v_bit_cnt = 0) then
  95. accept_o <= '1';
  96. s_uart_state <= IDLE;
  97. else
  98. v_bit_cnt := v_bit_cnt - 1;
  99. end if;
  100. end if;
  101. end case;
  102. end if;
  103. end process TxP;
  104. tx_o <= s_data(0);
  105. end architecture rtl;