blob: 0d95a51abb0db91fcca761cb4dd4cb8ac94ed245 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Filename: faxi_addr.v
//
// Project: Pipelined Wishbone to AXI converter
//
// Purpose: The AXI (full) standard has some rather complicated addressing
// modes, where the address can either be FIXED, INCRementing, or
// even where it can WRAP around some boundary. When in either INCR or
// WRAP modes, the next address must always be aligned. In WRAP mode,
// the next address calculation needs to wrap around a given value, and
// that value is dependent upon the burst size (i.e. bytes per beat) and
// length (total numbers of beats). Since this calculation can be
// non-trivial, and since it needs to be done multiple times, the logic
// below captures it for every time it might be needed.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019-2020, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
`default_nettype none
//
//
module faxi_addr(i_last_addr,
i_size,
i_burst,
i_len,
o_incr,
o_next_addr);
parameter AW=32;
input wire [AW-1:0] i_last_addr;
input wire [2:0] i_size; // 1b, 2b, 4b, 8b, etc
input wire [1:0] i_burst; // fixed, incr, wrap, reserved
input wire [7:0] i_len;
output reg [7:0] o_incr;
output reg [AW-1:0] o_next_addr;
(* keep *) reg [AW-1:0] wrap_mask, increment;
always @(*)
begin
increment = 0;
if (i_burst != 0)
begin
// verilator lint_off WIDTH
case(i_size)
0: increment = 1;
1: increment = 2;
2: increment = 4;
3: increment = 8;
4: increment = 16;
5: increment = 32;
6: increment = 64;
7: increment = 128;
default: increment = 0;
endcase
// verilator lint_on WIDTH
end
end
always @(*)
begin
wrap_mask = 0;
if (i_burst == 2'b10)
begin
if (i_len == 1)
wrap_mask = (1<<(i_size+1));
else if (i_len == 3)
wrap_mask = (1<<(i_size+2));
else if (i_len == 7)
wrap_mask = (1<<(i_size+3));
else if (i_len == 15)
wrap_mask = (1<<(i_size+4));
wrap_mask = wrap_mask - 1;
end
end
always @(*)
begin
o_next_addr = i_last_addr + increment;
if (i_burst != 2'b00)
begin
// Align any subsequent address
// verilator lint_off SELRANGE
if(i_size == 1)
o_next_addr[0] = 0;
else if ((i_size == 2)&&(AW>=2))
o_next_addr[1:0] = 0;
else if ((i_size == 3)&&(AW>=3))
o_next_addr[2:0] = 0;
else if ((i_size == 4)&&(AW>=4))
o_next_addr[3:0] = 0;
else if ((i_size == 5)&&(AW>=5))
o_next_addr[4:0] = 0;
else if ((i_size == 6)&&(AW>=6))
o_next_addr[((AW>6)?5:AW-1):0] = 0;
else if ((i_size == 7)&&(AW>=7))
o_next_addr[((AW>7)?6:AW-1):0] = 0;
// verilator lint_on SELRANGE
end
if (i_burst == 2'b10)
begin
// WRAP!
o_next_addr[AW-1:0] = (i_last_addr & ~wrap_mask)
| (o_next_addr & wrap_mask);;
end
end
always @(*)
begin
o_incr = 0;
o_incr[((AW>7)?7:AW-1):0] = increment[((AW>7)?7:AW-1):0];
end
endmodule