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.

209 lines
7.1 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. use work.uart_aes_types.all;
  24. entity uart_ctrl is
  25. port (
  26. -- globals
  27. rst_n_i : in std_logic;
  28. clk_i : in std_logic;
  29. -- axis in
  30. tdata_i : in std_logic_vector(7 downto 0);
  31. tvalid_i : in std_logic;
  32. tready_o : out std_logic;
  33. -- axis out
  34. tdata_o : out std_logic_vector(7 downto 0);
  35. tvalid_o : out std_logic;
  36. tready_i : in std_logic;
  37. -- aes out
  38. ctrl_aes_o : out t_axis_ctrl_aes_m2s;
  39. ctrl_aes_i : in t_axis_s2m;
  40. -- aes in
  41. aes_ctrl_i : in t_axis_aes_ctrl_m2s;
  42. aes_ctrl_o : out t_axis_s2m
  43. );
  44. end entity uart_ctrl;
  45. architecture rtl of uart_ctrl is
  46. type t_state is (IDLE, GET_CMD, RECV_DATA, SEND_DATA);
  47. signal s_state : t_state;
  48. signal s_reg_file : t_reg_file;
  49. signal s_reg_addr : natural range 0 to 7;
  50. signal s_reg_data : std_logic_vector(7 downto 0);
  51. subtype t_cmd is std_ulogic_vector(3 downto 0);
  52. constant c_read : t_cmd := x"0";
  53. constant c_write : t_cmd := x"1";
  54. alias a_tdata_cmd is tdata_i(3 downto 0);
  55. alias a_tdata_addr is tdata_i(6 downto 4);
  56. constant c_ctrl_addr : natural := 0;
  57. constant c_key_addr : natural := 1;
  58. constant c_nonce_addr : natural := 2;
  59. constant c_din_addr : natural := 3;
  60. constant c_out_addr : natural := 4;
  61. constant AES_RESET : natural := 0; -- Reset key & din registers
  62. constant CTR_START : natural := 1; -- 1st round of counter mode
  63. constant AES_START : natural := 2; -- start AES engine (cleared with AES_END)
  64. constant AES_END : natural := 3; -- AES engine finished
  65. type reg_acc_cnt_t is array (natural range <>) of unsigned(3 downto 0);
  66. signal read_acc_cnt : reg_acc_cnt_t(0 to 3);
  67. signal write_acc_cnt : reg_acc_cnt_t(0 to 2);
  68. begin
  69. -- Register memory
  70. process (clk_i, rst_n_i) is
  71. begin
  72. if (not rst_n_i) then
  73. s_reg_data <= (others => '0');
  74. s_reg_file <= c_reg_file_init;
  75. read_acc_cnt <= (others => x"0");
  76. write_acc_cnt <= (others => x"0");
  77. elsif (rising_edge(clk_i)) then
  78. -- Register write
  79. if (s_state = RECV_DATA and tvalid_i = '1') then
  80. case s_reg_addr is
  81. when 0 => s_reg_file.ctrl <= tdata_i;
  82. -- Clear all regs when AES_RESET bit set
  83. if (tdata_i(AES_RESET)) then
  84. s_reg_file.ctrl <= (others => '0');
  85. s_reg_file.key <= (others => '0');
  86. s_reg_file.nonce <= (others => '0');
  87. s_reg_file.din <= (others => '0');
  88. write_acc_cnt <= (others => x"0");
  89. read_acc_cnt <= (others => x"0");
  90. end if;
  91. when 1 => write_acc_cnt(0) <= write_acc_cnt(0) + 1;
  92. s_reg_file.key(to_integer(write_acc_cnt(0))*8 to to_integer(write_acc_cnt(0))*8+7) <= tdata_i;
  93. when 2 => if (write_acc_cnt(1) = 11) then
  94. write_acc_cnt(1) <= x"0";
  95. else
  96. write_acc_cnt(1) <= write_acc_cnt(1) + 1;
  97. end if;
  98. s_reg_file.nonce(to_integer(write_acc_cnt(1))*8 to to_integer(write_acc_cnt(1))*8+7) <= tdata_i;
  99. when 3 => write_acc_cnt(2) <= write_acc_cnt(2) + 1;
  100. s_reg_file.din(to_integer(write_acc_cnt(2))*8 to to_integer(write_acc_cnt(2))*8+7) <= tdata_i;
  101. when others => null;
  102. end case;
  103. end if;
  104. -- Register read
  105. aes_ctrl_o.tready <= '0';
  106. if (s_state = GET_CMD and a_tdata_cmd = c_read) then
  107. case s_reg_addr is
  108. when 0 => s_reg_data <= s_reg_file.ctrl;
  109. when 1 => read_acc_cnt(0) <= read_acc_cnt(0) + 1;
  110. s_reg_data <= s_reg_file.key(to_integer(read_acc_cnt(0))*8 to to_integer(read_acc_cnt(0))*8+7);
  111. when 2 => if (read_acc_cnt(1) = 11) then
  112. read_acc_cnt(1) <= x"0";
  113. else
  114. read_acc_cnt(1) <= read_acc_cnt(1) + 1;
  115. end if;
  116. s_reg_data <= s_reg_file.nonce(to_integer(read_acc_cnt(1))*8 to to_integer(read_acc_cnt(1))*8+7);
  117. when 3 => read_acc_cnt(2) <= read_acc_cnt(2) + 1;
  118. s_reg_data <= s_reg_file.din(to_integer(read_acc_cnt(2))*8 to to_integer(read_acc_cnt(2))*8+7);
  119. when 4 => read_acc_cnt(3) <= read_acc_cnt(3) + 1;
  120. s_reg_data <= aes_ctrl_i.tdata(to_integer(read_acc_cnt(3))*8 to to_integer(read_acc_cnt(3))*8+7);
  121. if (read_acc_cnt(3) = 15) then
  122. aes_ctrl_o.tready <= aes_ctrl_i.tvalid;
  123. end if;
  124. when others => s_reg_data <= (others => '0');
  125. end case;
  126. end if;
  127. -- Set AES_END when AES out data is valid
  128. -- Reset when AES out data was accepted (all 16 bytes of AES output data were read)
  129. if (aes_ctrl_o.tready) then
  130. s_reg_file.ctrl(AES_END) <= '0';
  131. elsif (aes_ctrl_i.tvalid) then
  132. s_reg_file.ctrl(AES_END) <= '1';
  133. end if;
  134. -- Reset AES_START & CTR_START when AES engine accepts in data
  135. if (ctrl_aes_i.tready and s_reg_file.ctrl(AES_START)) then
  136. s_reg_file.ctrl(AES_START) <= '0';
  137. s_reg_file.ctrl(CTR_START) <= '0';
  138. end if;
  139. end if;
  140. end process;
  141. -- Control state machine
  142. process (clk_i, rst_n_i) is
  143. begin
  144. if (not rst_n_i) then
  145. s_state <= IDLE;
  146. s_reg_addr <= 0;
  147. elsif (rising_edge(clk_i)) then
  148. case s_state is
  149. when IDLE =>
  150. if (tvalid_i) then
  151. s_state <= GET_CMD;
  152. s_reg_addr <= to_integer(unsigned(a_tdata_addr));
  153. end if;
  154. when GET_CMD =>
  155. if (a_tdata_cmd = c_read) then
  156. s_state <= SEND_DATA;
  157. elsif (a_tdata_cmd = c_write) then
  158. s_state <= RECV_DATA;
  159. else
  160. s_state <= IDLE;
  161. end if;
  162. when RECV_DATA =>
  163. if (tvalid_i) then
  164. s_state <= IDLE;
  165. end if;
  166. when SEND_DATA =>
  167. if (tready_i) then
  168. s_state <= IDLE;
  169. end if;
  170. when others =>
  171. null;
  172. end case;
  173. end if;
  174. end process;
  175. tready_o <= '1' when s_state = GET_CMD or s_state = RECV_DATA else '0';
  176. tdata_o <= s_reg_data;
  177. tvalid_o <= '1' when s_state = SEND_DATA else '0';
  178. ctrl_aes_o.tuser.start <= s_reg_file.ctrl(CTR_START);
  179. ctrl_aes_o.tuser.key <= s_reg_file.key;
  180. ctrl_aes_o.tuser.nonce <= s_reg_file.nonce;
  181. ctrl_aes_o.tdata <= s_reg_file.din;
  182. ctrl_aes_o.tvalid <= s_reg_file.ctrl(AES_START);
  183. end architecture;