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.

135 lines
3.4 KiB

  1. -- UART register
  2. -- Register file with 8 registers storing values of one byte each.
  3. --
  4. -- The first received byte on the axis in port contains command & address:
  5. --
  6. -- 7 reserved
  7. -- 6:4 register address
  8. -- 3:0 command
  9. -- 0x0 read
  10. -- 0x1 write
  11. --
  12. -- In case of a write command, the payload has to follow
  13. -- with the next byte.
  14. --
  15. -- In case of a read command, the value of the addressed
  16. -- register is returned on the axis out port.
  17. --
  18. -- Register at address 0 is special. It contains the version
  19. -- and is read-only. Writes to that register are ignored.
  20. library ieee;
  21. use ieee.std_logic_1164.all;
  22. use ieee.numeric_std.all;
  23. entity uart_ctrl is
  24. port (
  25. -- globals
  26. rst_n_i : in std_logic;
  27. clk_i : in std_logic;
  28. -- axis in
  29. tdata_i : in std_logic_vector(7 downto 0);
  30. tvalid_i : in std_logic;
  31. tready_o : out std_logic;
  32. -- axis out
  33. tdata_o : out std_logic_vector(7 downto 0);
  34. tvalid_o : out std_logic;
  35. tready_i : in std_logic
  36. );
  37. end entity uart_ctrl;
  38. architecture rtl of uart_ctrl is
  39. type t_state is (IDLE, GET_CMD, RECV_DATA, SEND_DATA);
  40. signal s_state : t_state;
  41. subtype t_reg is std_logic_vector(7 downto 0);
  42. type t_reg_file is array (1 to 7) of t_reg;
  43. signal s_reg_file : t_reg_file;
  44. constant c_version : t_reg := x"01";
  45. signal s_reg_addr : natural range 0 to 7;
  46. signal s_reg_data : t_reg;
  47. subtype t_cmd is std_ulogic_vector(3 downto 0);
  48. constant c_read : t_cmd := x"0";
  49. constant c_write : t_cmd := x"1";
  50. alias a_tdata_cmd is tdata_i(3 downto 0);
  51. alias a_tdata_addr is tdata_i(6 downto 4);
  52. begin
  53. -- Register memory, omitted reset of memory during synthesis
  54. -- for better RAM detection
  55. process (clk_i, rst_n_i) is
  56. begin
  57. if (not rst_n_i) then
  58. -- synthesis translate_off
  59. s_reg_file <= (others => (others => '0'));
  60. -- synthesis translate_on
  61. s_reg_data <= (others => '0');
  62. elsif (rising_edge(clk_i)) then
  63. -- Write
  64. if (s_state = RECV_DATA and tvalid_i = '1') then
  65. -- Ignore writes to version register
  66. if (s_reg_addr /= 0) then
  67. s_reg_file(s_reg_addr) <= tdata_i;
  68. end if;
  69. end if;
  70. -- Always read, regardless of write or read command
  71. if (s_state = GET_CMD) then
  72. if (s_reg_addr /= 0) then
  73. s_reg_data <= s_reg_file(s_reg_addr);
  74. end if;
  75. end if;
  76. end if;
  77. end process;
  78. -- Control state machine
  79. process (clk_i, rst_n_i) is
  80. begin
  81. if (not rst_n_i) then
  82. s_state <= IDLE;
  83. s_reg_addr <= 0;
  84. elsif (rising_edge(clk_i)) then
  85. case s_state is
  86. when IDLE =>
  87. if (tvalid_i) then
  88. s_state <= GET_CMD;
  89. s_reg_addr <= to_integer(unsigned(a_tdata_addr));
  90. end if;
  91. when GET_CMD =>
  92. if (a_tdata_cmd = c_read) then
  93. s_state <= SEND_DATA;
  94. elsif (a_tdata_cmd = c_write) then
  95. s_state <= RECV_DATA;
  96. else
  97. s_state <= IDLE;
  98. end if;
  99. when RECV_DATA =>
  100. if (tvalid_i) then
  101. s_state <= IDLE;
  102. end if;
  103. when SEND_DATA =>
  104. if (tready_i) then
  105. s_state <= IDLE;
  106. end if;
  107. when others =>
  108. null;
  109. end case;
  110. end if;
  111. end process;
  112. tready_o <= '1' when s_state = GET_CMD or s_state = RECV_DATA else '0';
  113. tdata_o <= c_version when s_reg_addr = 0 else s_reg_data;
  114. tvalid_o <= '1' when s_state = SEND_DATA else '0';
  115. end architecture;