1-- Copyright (c) 2016 Nokia Research Center 2-- 3-- Permission is hereby granted, free of charge, to any person obtaining a 4-- copy of this software and associated documentation files (the "Software"), 5-- to deal in the Software without restriction, including without limitation 6-- the rights to use, copy, modify, merge, publish, distribute, sublicense, 7-- and/or sell copies of the Software, and to permit persons to whom the 8-- Software is furnished to do so, subject to the following conditions: 9-- 10-- The above copyright notice and this permission notice shall be included in 11-- all copies or substantial portions of the Software. 12-- 13-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19-- DEALINGS IN THE SOFTWARE. 20------------------------------------------------------------------------------- 21-- Title : AXI lite interface to TTA debugger and stream IO 22-- Project : 23------------------------------------------------------------------------------- 24-- File : tta-axislave.vhdl 25-- Author : Tommi Zetterman <tommi.zetterman@nokia.com> 26-- Company : Nokia Research Center 27-- Created : 2014-06-23 28-- Last update: 2017-06-01 29-- Platform : 30-- Standard : VHDL'93 31------------------------------------------------------------------------------- 32-- Description: 33------------------------------------------------------------------------------- 34-- Copyright (c) 2014 Nokia Research Center 35------------------------------------------------------------------------------- 36-- Revisions : 37-- Date Version Author Description 38-- 2014-06-23 1.0 zetterma Created (as axi4dbgslave-rtl.vhdl 39-- 2015-01-27 1.1 viitanet Modified into a processor wrapper 40-- 2016-11-18 1.1 tervoa Added full AXI4 interface 41-- 2017-03-27 1.2 tervoa Fixed burst transfer logic 42-- 2017-04-25 1.3 tervoa Combined entiy and architecture files 43-- 2017-06-01 1.4 tervoa Converted to memory buses with handshaking 44-- 2017-06-01 1.5 tervoa Fix address increment logic 45-- 2018-07-30 1.6 tervoa Support for optional sync reset 46------------------------------------------------------------------------------- 47library ieee; 48use ieee.std_logic_1164.all; 49use ieee.numeric_std.all; 50 51entity tta_axislave is 52 generic ( 53 -- Must be at least 2 + max(max(IMEMADDRWIDTH+IMEMWORDSEL,db_addr_width), 54 -- fu_LSU_addrw-2) 55 -- where IMEMWORDSEL = bit_width((IMEMDATAWIDTH+31)/32) 56 axi_addrw_g : integer := 17; 57 axi_dataw_g : integer := 32; 58 axi_idw_g : integer := 12; 59 sync_reset_g : integer := 0 60 ); 61 port ( 62 clk : in std_logic; 63 rstx : in std_logic; 64 -- Accelerator interface 65 avalid_out : out std_logic; 66 aready_in : in std_logic; 67 aaddr_out : out std_logic_vector(axi_addrw_g-2-1 downto 0); 68 awren_out : out std_logic; 69 astrb_out : out std_logic_vector(axi_dataw_g/8-1 downto 0); 70 adata_out : out std_logic_vector(axi_dataw_g-1 downto 0); 71 rvalid_in : in std_logic; 72 rready_out : out std_logic; 73 rdata_in : in std_logic_vector(axi_dataw_g-1 downto 0); 74 -- AXI slave port 75 s_axi_awid : in STD_LOGIC_VECTOR (axi_idw_g-1 downto 0); 76 s_axi_awaddr : in STD_LOGIC_VECTOR (axi_addrw_g-1 downto 0); 77 s_axi_awlen : in STD_LOGIC_VECTOR (8-1 downto 0); 78 s_axi_awsize : in STD_LOGIC_VECTOR (3-1 downto 0); 79 s_axi_awburst : in STD_LOGIC_VECTOR (2-1 downto 0); 80 s_axi_awvalid : in STD_LOGIC; 81 s_axi_awready : out STD_LOGIC; 82 s_axi_wdata : in STD_LOGIC_VECTOR (31 downto 0); 83 s_axi_wstrb : in STD_LOGIC_VECTOR (3 downto 0); 84 s_axi_wvalid : in STD_LOGIC; 85 s_axi_wready : out STD_LOGIC; 86 s_axi_bid : out STD_LOGIC_VECTOR (axi_idw_g-1 downto 0); 87 s_axi_bresp : out STD_LOGIC_VECTOR (2-1 downto 0); 88 s_axi_bvalid : out STD_LOGIC; 89 s_axi_bready : in STD_LOGIC; 90 s_axi_arid : in STD_LOGIC_VECTOR (axi_idw_g-1 downto 0); 91 s_axi_araddr : in STD_LOGIC_VECTOR (axi_addrw_g-1 downto 0); 92 s_axi_arlen : in STD_LOGIC_VECTOR (8-1 downto 0); 93 s_axi_arsize : in STD_LOGIC_VECTOR (3-1 downto 0); 94 s_axi_arburst : in STD_LOGIC_VECTOR (2-1 downto 0); 95 s_axi_arvalid : in STD_LOGIC; 96 s_axi_arready : out STD_LOGIC; 97 s_axi_rid : out STD_LOGIC_VECTOR (axi_idw_g-1 downto 0); 98 s_axi_rdata : out STD_LOGIC_VECTOR (31 downto 0); 99 s_axi_rresp : out STD_LOGIC_VECTOR (2-1 downto 0); 100 s_axi_rlast : out STD_LOGIC; 101 s_axi_rvalid : out STD_LOGIC; 102 s_axi_rready : in STD_LOGIC 103 ); 104end entity tta_axislave; 105 106architecture rtl of tta_axislave is 107 108 constant sync_reset_c : boolean := sync_reset_g /= 0; 109 110 constant FIXED_BURST : std_logic_vector(1 downto 0) := "00"; 111 constant INCR_BURST : std_logic_vector(1 downto 0) := "01"; 112 constant WRAP_BURST : std_logic_vector(1 downto 0) := "10"; 113 114 constant AXI_OKAY : std_logic_vector(1 downto 0) := "00"; 115 constant AXI_SLVERR : std_logic_vector(1 downto 0) := "10"; 116 117 type u8_array is array (natural range <>) of unsigned(7 downto 0); 118 constant burst_size_lut_c : u8_array(0 to 7) := 119 ("00000001", "00000010","00000100","00001000", 120 "00010000", "00100000","01000000","10000000"); 121 122 type state_t is (S_READY, S_WRITE_DATA, S_FINISH_WRITE, 123 S_READ_DATA, S_FINISH_READ); 124 signal state : state_t; 125 126 -- Output registers 127 signal s_axi_awready_r : std_logic; 128 signal s_axi_wready_r : std_logic; 129 signal s_axi_bid_r : std_logic_vector(s_axi_bid'range); 130 signal s_axi_bresp_r : std_logic_vector(s_axi_bresp'range); 131 signal s_axi_bvalid_r : std_logic; 132 signal s_axi_arready_r : std_logic; 133 signal s_axi_rid_r : std_logic_vector(s_axi_rid'range); 134 signal s_axi_rdata_r : std_logic_vector(s_axi_rdata'range); 135 signal s_axi_rresp_r : std_logic_vector(s_axi_rresp'range); 136 signal s_axi_rlast_r : std_logic; 137 signal s_axi_rvalid_r : std_logic; 138 139 signal astrb_r, stall_strb_r : std_logic_vector(astrb_out'range); 140 signal adata_r, stall_data_r : std_logic_vector(adata_out'range); 141 signal aaddr_r, stall_addr_r : std_logic_vector(aaddr_out'range); 142 signal avalid_r, awren_r, stall_data_valid_r, rready_r : std_logic; 143 144 signal burst_cnt_r : unsigned(s_axi_arlen'range); 145 signal read_cnt_r : unsigned(s_axi_arlen'range); 146 signal transaction_r : std_logic_vector(s_axi_arid'range); 147 148 signal burst_type_r : std_logic_vector(s_axi_arburst'range); 149 signal burst_size_r : unsigned(7 downto 0); 150 signal wrap_mask_r : std_logic_vector(s_axi_araddr'range); 151 signal axi_addr_r : std_logic_vector(s_axi_araddr'range); 152 153 signal axi_stall_r : std_logic; 154 155 156 function increment_addr(burst_type : std_logic_vector(s_axi_arburst'range); 157 size : unsigned; 158 wrap_mask : std_logic_vector(axi_addrw_g-1 downto 0); 159 address : std_logic_vector(axi_addrw_g-1 downto 0)) 160 return std_logic_vector is 161 variable address_tmp : std_logic_vector(axi_addrw_g-1 downto 0); 162 begin 163 case burst_type is 164 when FIXED_BURST => 165 return address; 166 when INCR_BURST => 167 return std_logic_vector(unsigned(address) + size); 168 when WRAP_BURST => -- UNTESTED 169 address_tmp := std_logic_vector(unsigned(address) + size); 170 171 for I in address'range loop 172 if wrap_mask(I) = '0' then 173 address_tmp(I) := address(I); 174 end if; 175 end loop; 176 177 return address_tmp; 178 when others => 179 -- coverage off 180 -- pragma translate_off 181 assert false report "Unrecognized burst type" severity warning; 182 -- pragma translate_on 183 -- coverage on 184 return address; 185 end case; 186 end function increment_addr; 187 188 function wrap_mask(axsize : std_logic_vector(s_axi_arsize'range); 189 axlen : std_logic_vector(s_axi_arlen'range)) 190 return std_logic_vector is 191 variable mask_temp : std_logic_vector(axi_addrw_g-1 downto 0); 192 variable axsize_int : integer range 0 to 7 193 := to_integer(unsigned(axsize)); 194 begin 195 for I in mask_temp'range loop 196 if I < axsize_int then 197 mask_temp(I) := '0'; 198 elsif I < axsize_int + axlen'high then 199 mask_temp(I) := axlen(I - axsize_int); 200 else 201 mask_temp(I) := '0'; 202 end if; 203 end loop; 204 return mask_temp; 205 end function wrap_mask; 206 207begin 208 209 sync : process(clk, rstx) 210 variable axi_addr_v : std_logic_vector(axi_addr_r'range); 211 begin 212 if not sync_reset_c and rstx = '0' then 213 s_axi_awready_r <= '0'; 214 s_axi_wready_r <= '0'; 215 s_axi_bid_r <= (others => '0'); 216 s_axi_bresp_r <= (others => '0'); 217 s_axi_bvalid_r <= '0'; 218 s_axi_arready_r <= '0'; 219 s_axi_rid_r <= (others => '0'); 220 s_axi_rdata_r <= (others => '0'); 221 s_axi_rresp_r <= (others => '0'); 222 s_axi_rlast_r <= '0'; 223 s_axi_rvalid_r <= '0'; 224 225 avalid_r <= '0'; 226 aaddr_r <= (others => '0'); 227 awren_r <= '0'; 228 astrb_r <= (others => '0'); 229 adata_r <= (others => '0'); 230 rready_r <= '0'; 231 232 axi_addr_r <= (others => '0'); 233 state <= S_READY; 234 burst_cnt_r <= (others => '0'); 235 transaction_r <= (others => '0'); 236 stall_strb_r <= (others => '0'); 237 stall_data_r <= (others => '0'); 238 stall_addr_r <= (others => '0'); 239 stall_data_valid_r <= '0'; 240 elsif rising_edge(clk) then 241 if sync_reset_c and rstx = '0' then 242 s_axi_awready_r <= '0'; 243 s_axi_wready_r <= '0'; 244 s_axi_bid_r <= (others => '0'); 245 s_axi_bresp_r <= (others => '0'); 246 s_axi_bvalid_r <= '0'; 247 s_axi_arready_r <= '0'; 248 s_axi_rid_r <= (others => '0'); 249 s_axi_rdata_r <= (others => '0'); 250 s_axi_rresp_r <= (others => '0'); 251 s_axi_rlast_r <= '0'; 252 s_axi_rvalid_r <= '0'; 253 254 avalid_r <= '0'; 255 aaddr_r <= (others => '0'); 256 awren_r <= '0'; 257 astrb_r <= (others => '0'); 258 adata_r <= (others => '0'); 259 rready_r <= '0'; 260 261 axi_addr_r <= (others => '0'); 262 state <= S_READY; 263 burst_cnt_r <= (others => '0'); 264 transaction_r <= (others => '0'); 265 stall_strb_r <= (others => '0'); 266 stall_data_r <= (others => '0'); 267 stall_addr_r <= (others => '0'); 268 stall_data_valid_r <= '0'; 269 else 270 if s_axi_arready_r = '1' and s_axi_arvalid = '1' then 271 s_axi_arready_r <= '0'; 272 end if; 273 if s_axi_awready_r = '1' and s_axi_awvalid = '1' then 274 s_axi_awready_r <= '0'; 275 end if; 276 277 s_axi_wready_r <= '0'; 278 rready_r <= '0'; 279 s_axi_rlast_r <= '0'; 280 281 -- valid_r(0) <= '0'; 282 -- valid_r(2 downto 1) <= valid_r(1 downto 0); 283 284 axi_stall_r <= '0'; 285 case state is 286 287 when S_READY => 288 if s_axi_awvalid = '1' then 289 s_axi_awready_r <= '1'; 290 axi_addr_r <= s_axi_awaddr; 291 transaction_r <= s_axi_awid; 292 wrap_mask_r <= wrap_mask(s_axi_awsize, s_axi_awlen); 293 294 burst_size_r <= burst_size_lut_c(to_integer( 295 unsigned(s_axi_awsize))); 296 burst_type_r <= s_axi_awburst; 297 burst_cnt_r <= unsigned(s_axi_awlen); 298 state <= S_WRITE_DATA; 299 elsif s_axi_arvalid = '1' then 300 s_axi_arready_r <= '1'; 301 transaction_r <= s_axi_arid; 302 wrap_mask_r <= wrap_mask(s_axi_arsize, s_axi_arlen); 303 304 axi_addr_r <= s_axi_araddr; 305 aaddr_r <= s_axi_araddr(s_axi_araddr'high downto 2); 306 avalid_r <= '1'; 307 awren_r <= '0'; 308 rready_r <= '1'; 309 310 burst_size_r <= burst_size_lut_c(to_integer( 311 unsigned(s_axi_arsize))); 312 burst_cnt_r <= unsigned(s_axi_arlen); 313 read_cnt_r <= unsigned(s_axi_arlen); 314 burst_type_r <= s_axi_arburst; 315 state <= S_READ_DATA; 316 end if; 317 318 when S_WRITE_DATA => 319 320 if avalid_r = '0' or stall_data_valid_r = '0' then 321 s_axi_wready_r <= '1'; 322 else 323 s_axi_wready_r <= '0'; 324 end if; 325 326 if avalid_r = '1' and aready_in = '1' then 327 if stall_data_valid_r = '1' then 328 astrb_r <= stall_strb_r; 329 adata_r <= stall_data_r; 330 awren_r <= '1'; 331 aaddr_r <= stall_addr_r; 332 stall_data_valid_r <= '0'; 333 else 334 avalid_r <= '0'; 335 end if; 336 end if; 337 338 if s_axi_wvalid = '1' and s_axi_wready_r = '1' then 339 if (aready_in = '1' and stall_data_valid_r = '0') 340 or avalid_r = '0' then 341 avalid_r <= '1'; 342 awren_r <= '1'; 343 astrb_r <= s_axi_wstrb; 344 adata_r <= s_axi_wdata; 345 aaddr_r <= axi_addr_r(axi_addr_r'high downto 2); 346 else 347 stall_data_valid_r <= '1'; 348 stall_data_r <= s_axi_wdata; 349 stall_strb_r <= s_axi_wstrb; 350 stall_addr_r <= axi_addr_r(axi_addr_r'high downto 2); 351 end if; 352 353 if burst_cnt_r = 0 then 354 s_axi_wready_r <= '0'; 355 s_axi_bresp_r <= AXI_OKAY; 356 s_axi_bvalid_r <= '1'; 357 s_axi_bid_r <= transaction_r; 358 state <= S_FINISH_WRITE; 359 else 360 axi_addr_r <= increment_addr(burst_type_r, burst_size_r, 361 wrap_mask_r, axi_addr_r); 362 burst_cnt_r <= burst_cnt_r - 1; 363 end if; 364 end if; 365 366 367 when S_FINISH_WRITE => 368 if s_axi_bready = '1' then 369 s_axi_bvalid_r <= '0'; 370 end if; 371 372 if avalid_r = '1' and aready_in = '1' then 373 if stall_data_valid_r = '1' then 374 astrb_r <= stall_strb_r; 375 adata_r <= stall_data_r; 376 awren_r <= '1'; 377 378 stall_data_valid_r <= '0'; 379 else 380 avalid_r <= '0'; 381 awren_r <= '0'; 382 end if; 383 end if; 384 385 if avalid_r = '0' and s_axi_bvalid_r = '0' then 386 state <= S_READY; 387 end if; 388 389 when S_READ_DATA => 390 if s_axi_rready = '1' and s_axi_rvalid_r = '1' then 391 if stall_data_valid_r = '1' then 392 s_axi_rdata_r <= stall_data_r; 393 stall_data_valid_r <= '0'; 394 else 395 s_axi_rvalid_r <= '0'; 396 end if; 397 end if; 398 399 if avalid_r = '1' and aready_in = '1' then 400 if read_cnt_r = 0 then 401 avalid_r <= '0'; 402 else 403 axi_addr_v := increment_addr(burst_type_r, burst_size_r, 404 wrap_mask_r, axi_addr_r); 405 axi_addr_r <= axi_addr_v; 406 aaddr_r <= axi_addr_v(axi_addr_v'high downto 2); 407 read_cnt_r <= read_cnt_r - 1; 408 end if; 409 end if; 410 411 if s_axi_rvalid_r = '0' or stall_data_valid_r = '0' then 412 rready_r <= '1'; 413 else 414 rready_r <= '0'; 415 end if; 416 417 if rvalid_in = '1' and rready_r = '1' then 418 if (s_axi_rready = '1'and stall_data_valid_r = '0') 419 or s_axi_rvalid_r = '0' then 420 s_axi_rvalid_r <= '1'; 421 s_axi_rdata_r <= rdata_in; 422 s_axi_rresp_r <= AXI_OKAY; 423 s_axi_rid_r <= transaction_r; 424 else 425 stall_data_valid_r <= '1'; 426 stall_data_r <= rdata_in; 427 rready_r <= '0'; 428 end if; 429 430 if burst_cnt_r = 0 then 431 if (s_axi_rready = '1'and stall_data_valid_r = '0') 432 or s_axi_rvalid_r = '0' then 433 s_axi_rlast_r <= '1'; 434 end if; 435 rready_r <= '0'; 436 state <= S_FINISH_READ; 437 else 438 burst_cnt_r <= burst_cnt_r - 1; 439 end if; 440 end if; 441 442 when S_FINISH_READ => 443 if s_axi_rready = '1' and s_axi_rvalid_r = '1' then 444 if stall_data_valid_r = '1' then 445 s_axi_rlast_r <= '1'; 446 s_axi_rdata_r <= stall_data_r; 447 stall_data_valid_r <= '0'; 448 else 449 s_axi_rvalid_r <= '0'; 450 s_axi_rlast_r <= '0'; 451 state <= S_READY; 452 end if; 453 end if; 454 455 end case; 456 end if; 457 end if; 458 end process; 459 460 s_axi_awready <= s_axi_awready_r; 461 s_axi_wready <= s_axi_wready_r; 462 s_axi_bid <= s_axi_bid_r; 463 s_axi_bresp <= s_axi_bresp_r; 464 s_axi_bvalid <= s_axi_bvalid_r; 465 s_axi_arready <= s_axi_arready_r; 466 s_axi_rid <= s_axi_rid_r; 467 s_axi_rdata <= s_axi_rdata_r; 468 s_axi_rresp <= s_axi_rresp_r; 469 s_axi_rlast <= s_axi_rlast_r; 470 s_axi_rvalid <= s_axi_rvalid_r; 471 avalid_out <= avalid_r; 472 aaddr_out <= aaddr_r; 473 awren_out <= awren_r; 474 astrb_out <= astrb_r; 475 adata_out <= adata_r; 476 rready_out <= rready_r; 477end architecture rtl; 478