190 lines
6.8 KiB
Systemverilog
190 lines
6.8 KiB
Systemverilog
|
// (C) 2001-2015 Altera Corporation. All rights reserved.
|
||
|
// Your use of Altera Corporation's design tools, logic functions and other
|
||
|
// software and tools, and its AMPP partner logic functions, and any output
|
||
|
// files any of the foregoing (including device programming or simulation
|
||
|
// files), and any associated documentation or information are expressly subject
|
||
|
// to the terms and conditions of the Altera Program License Subscription
|
||
|
// Agreement, Altera MegaCore Function License Agreement, or other applicable
|
||
|
// license agreement, including, without limitation, that your use is for the
|
||
|
// sole purpose of programming logic devices manufactured by Altera and sold by
|
||
|
// Altera or its authorized distributors. Please refer to the applicable
|
||
|
// agreement for further details.
|
||
|
|
||
|
|
||
|
// $Id: //acds/rel/15.1/ip/merlin/altera_merlin_burst_adapter/new_source/altera_default_burst_converter.sv#1 $
|
||
|
// $Revision: #1 $
|
||
|
// $Date: 2015/08/09 $
|
||
|
// $Author: swbranch $
|
||
|
|
||
|
// --------------------------------------------
|
||
|
// Default Burst Converter
|
||
|
// Notes:
|
||
|
// 1) If burst type FIXED and slave is AXI,
|
||
|
// passthrough the transaction.
|
||
|
// 2) Else, converts burst into non-bursting
|
||
|
// transactions (length of 1).
|
||
|
// --------------------------------------------
|
||
|
|
||
|
`timescale 1 ns / 1 ns
|
||
|
|
||
|
module altera_default_burst_converter
|
||
|
#(
|
||
|
parameter PKT_BURST_TYPE_W = 2,
|
||
|
parameter PKT_BURSTWRAP_W = 5,
|
||
|
parameter PKT_ADDR_W = 12,
|
||
|
parameter PKT_BURST_SIZE_W = 3,
|
||
|
parameter IS_AXI_SLAVE = 0,
|
||
|
parameter LEN_W = 2
|
||
|
)
|
||
|
(
|
||
|
input clk,
|
||
|
input reset,
|
||
|
input enable,
|
||
|
|
||
|
input [PKT_BURST_TYPE_W - 1 : 0] in_bursttype,
|
||
|
input [PKT_BURSTWRAP_W - 1 : 0] in_burstwrap_reg,
|
||
|
input [PKT_BURSTWRAP_W - 1 : 0] in_burstwrap_value,
|
||
|
input [PKT_ADDR_W - 1 : 0] in_addr,
|
||
|
input [PKT_ADDR_W - 1 : 0] in_addr_reg,
|
||
|
input [LEN_W - 1 : 0] in_len,
|
||
|
input [PKT_BURST_SIZE_W - 1 : 0] in_size_value,
|
||
|
|
||
|
input in_is_write,
|
||
|
|
||
|
output reg [PKT_ADDR_W - 1 : 0] out_addr,
|
||
|
output reg [LEN_W - 1 : 0] out_len,
|
||
|
|
||
|
output reg new_burst
|
||
|
);
|
||
|
|
||
|
// ---------------------------------------------------
|
||
|
// AXI Burst Type Encoding
|
||
|
// ---------------------------------------------------
|
||
|
typedef enum bit [1:0]
|
||
|
{
|
||
|
FIXED = 2'b00,
|
||
|
INCR = 2'b01,
|
||
|
WRAP = 2'b10,
|
||
|
RESERVED = 2'b11
|
||
|
} AxiBurstType;
|
||
|
|
||
|
// -------------------------------------------
|
||
|
// Internal Signals
|
||
|
// -------------------------------------------
|
||
|
wire [LEN_W - 1 : 0] unit_len = {{LEN_W - 1 {1'b0}}, 1'b1};
|
||
|
reg [LEN_W - 1 : 0] next_len;
|
||
|
reg [LEN_W - 1 : 0] remaining_len;
|
||
|
reg [PKT_ADDR_W - 1 : 0] next_incr_addr;
|
||
|
reg [PKT_ADDR_W - 1 : 0] incr_wrapped_addr;
|
||
|
reg [PKT_ADDR_W - 1 : 0] extended_burstwrap_value;
|
||
|
reg [PKT_ADDR_W - 1 : 0] addr_incr_variable_size_value;
|
||
|
|
||
|
// -------------------------------------------
|
||
|
// Byte Count Converter
|
||
|
// -------------------------------------------
|
||
|
// Avalon Slave: Read/Write, the out_len is always 1 (unit_len).
|
||
|
// AXI Slave: Read/Write, the out_len is always the in_len (pass through) of a given cycle.
|
||
|
// If bursttype RESERVED, out_len is always 1 (unit_len).
|
||
|
generate if (IS_AXI_SLAVE == 1)
|
||
|
begin : axi_slave_out_len
|
||
|
always_ff @(posedge clk, posedge reset) begin
|
||
|
if (reset) begin
|
||
|
out_len <= {LEN_W{1'b0}};
|
||
|
end
|
||
|
else if (enable) begin
|
||
|
out_len <= (in_bursttype == FIXED) ? in_len : unit_len;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
else // IS_AXI_SLAVE == 0
|
||
|
begin : non_axi_slave_out_len
|
||
|
always_comb begin
|
||
|
out_len = unit_len;
|
||
|
end
|
||
|
end
|
||
|
endgenerate
|
||
|
|
||
|
|
||
|
always_comb begin : proc_extend_burstwrap
|
||
|
extended_burstwrap_value = {{(PKT_ADDR_W - PKT_BURSTWRAP_W){in_burstwrap_reg[PKT_BURSTWRAP_W - 1]}}, in_burstwrap_value};
|
||
|
addr_incr_variable_size_value = {{(PKT_ADDR_W - 1){1'b0}}, 1'b1} << in_size_value;
|
||
|
end
|
||
|
|
||
|
// -------------------------------------------
|
||
|
// Address Converter
|
||
|
// -------------------------------------------
|
||
|
// Write: out_addr = in_addr at every cycle (pass through).
|
||
|
// Read: out_addr = in_addr at every new_burst. Subsequent addresses calculated by converter.
|
||
|
|
||
|
always_ff @(posedge clk, posedge reset) begin
|
||
|
if (reset) begin
|
||
|
next_incr_addr <= {PKT_ADDR_W{1'b0}};
|
||
|
out_addr <= {PKT_ADDR_W{1'b0}};
|
||
|
end
|
||
|
else if (enable) begin
|
||
|
next_incr_addr <= next_incr_addr + addr_incr_variable_size_value;
|
||
|
if (new_burst) begin
|
||
|
next_incr_addr <= in_addr + addr_incr_variable_size_value;
|
||
|
end
|
||
|
out_addr <= incr_wrapped_addr;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always_comb begin
|
||
|
incr_wrapped_addr = in_addr;
|
||
|
if (!new_burst) begin
|
||
|
// This formula calculates addresses of WRAP bursts and works perfectly fine for other burst types too.
|
||
|
incr_wrapped_addr = (in_addr_reg & ~extended_burstwrap_value) | (next_incr_addr & extended_burstwrap_value);
|
||
|
end
|
||
|
end
|
||
|
|
||
|
// -------------------------------------------
|
||
|
// Control Signals
|
||
|
// -------------------------------------------
|
||
|
|
||
|
// Determine the min_len.
|
||
|
// 1) FIXED read to AXI slave: One-time passthrough, therefore the min_len == in_len.
|
||
|
// 2) FIXED write to AXI slave: min_len == 1.
|
||
|
// 3) FIXED read/write to Avalon slave: min_len == 1.
|
||
|
// 4) RESERVED read/write to AXI/Avalon slave: min_len == 1.
|
||
|
wire [LEN_W - 1 : 0] min_len;
|
||
|
generate if (IS_AXI_SLAVE == 1)
|
||
|
begin : axi_slave_min_len
|
||
|
assign min_len = (!in_is_write && (in_bursttype == FIXED)) ? in_len : unit_len;
|
||
|
end
|
||
|
else // IS_AXI_SLAVE == 0
|
||
|
begin : non_axi_slave_min_len
|
||
|
assign min_len = unit_len;
|
||
|
end
|
||
|
endgenerate
|
||
|
|
||
|
// last_beat calculation.
|
||
|
wire last_beat = (remaining_len == min_len);
|
||
|
|
||
|
// next_len calculation.
|
||
|
always_comb begin
|
||
|
remaining_len = in_len;
|
||
|
if (!new_burst) remaining_len = next_len;
|
||
|
end
|
||
|
|
||
|
always_ff @(posedge clk, posedge reset) begin
|
||
|
if (reset) begin
|
||
|
next_len <= 1'b0;
|
||
|
end
|
||
|
else if (enable) begin
|
||
|
next_len <= remaining_len - unit_len;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
// new_burst calculation.
|
||
|
always_ff @(posedge clk, posedge reset) begin
|
||
|
if (reset) begin
|
||
|
new_burst <= 1'b1;
|
||
|
end
|
||
|
else if (enable) begin
|
||
|
new_burst <= last_beat;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
endmodule
|