mor1kx-bemicrocv/ip/altera/ddr3/altera_merlin_width_adapter.sv
2016-08-04 19:22:38 +02:00

1207 lines
56 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_width_adapter/altera_merlin_width_adapter.sv#1 $
// $Revision: #1 $
// $Date: 2015/08/09 $
// $Author: swbranch $
// -----------------------------------------------------
// Merlin Width Adapter
// -----------------------------------------------------
`timescale 1 ns / 1 ns
module altera_merlin_width_adapter
#(
parameter IN_PKT_ADDR_L = 0,
parameter IN_PKT_ADDR_H = 31,
parameter IN_PKT_DATA_L = 32,
parameter IN_PKT_DATA_H = 63,
parameter IN_PKT_BYTEEN_L = 64,
parameter IN_PKT_BYTEEN_H = 67,
parameter IN_PKT_TRANS_COMPRESSED_READ = 72,
parameter IN_PKT_BYTE_CNT_L = 73,
parameter IN_PKT_BYTE_CNT_H = 77,
parameter IN_PKT_BURSTWRAP_L = 78,
parameter IN_PKT_BURSTWRAP_H = 82,
parameter IN_PKT_BURST_SIZE_L = 83,
parameter IN_PKT_BURST_SIZE_H = 85,
parameter IN_PKT_RESPONSE_STATUS_L = 86,
parameter IN_PKT_RESPONSE_STATUS_H = 87,
parameter IN_PKT_TRANS_EXCLUSIVE = 88,
parameter IN_PKT_BURST_TYPE_L = 89,
parameter IN_PKT_BURST_TYPE_H = 90,
parameter IN_PKT_ORI_BURST_SIZE_L = 91,
parameter IN_PKT_ORI_BURST_SIZE_H = 93,
parameter IN_PKT_TRANS_WRITE = 94,
parameter IN_ST_DATA_W = 110,
parameter OUT_PKT_ADDR_L = 0,
parameter OUT_PKT_ADDR_H = 31,
parameter OUT_PKT_DATA_L = 32,
parameter OUT_PKT_DATA_H = 47,
parameter OUT_PKT_BYTEEN_L = 48,
parameter OUT_PKT_BYTEEN_H = 49,
parameter OUT_PKT_TRANS_COMPRESSED_READ = 54,
parameter OUT_PKT_BYTE_CNT_L = 55,
parameter OUT_PKT_BYTE_CNT_H = 59,
parameter OUT_PKT_BURST_SIZE_L = 60,
parameter OUT_PKT_BURST_SIZE_H = 62,
parameter OUT_PKT_RESPONSE_STATUS_L = 63,
parameter OUT_PKT_RESPONSE_STATUS_H = 64,
parameter OUT_PKT_TRANS_EXCLUSIVE = 65,
parameter OUT_PKT_BURST_TYPE_L = 66,
parameter OUT_PKT_BURST_TYPE_H = 67,
parameter OUT_PKT_ORI_BURST_SIZE_L = 68,
parameter OUT_PKT_ORI_BURST_SIZE_H = 70,
parameter OUT_ST_DATA_W = 92,
parameter ST_CHANNEL_W = 32,
parameter OPTIMIZE_FOR_RSP = 0,
parameter PACKING = 1, // 1: Enables packing in Avalon systems
parameter CONSTANT_BURST_SIZE = 1, // 1: Optimizes for Avalon-only systems as those always have full size transactions
parameter RESPONSE_PATH = 0, // 0: This adapter is on command path, 1: This adapter is on response path
// Address alignment can be turned off (an optimisation) if all connected
// masters only issue aligned addresses.
parameter ENABLE_ADDRESS_ALIGNMENT = 1
)
(
input clk,
input reset,
output reg in_ready,
input in_valid,
input [ST_CHANNEL_W-1:0] in_channel,
input [IN_ST_DATA_W-1:0] in_data,
input in_startofpacket,
input in_endofpacket,
input out_ready,
output reg out_valid,
output reg [ST_CHANNEL_W-1:0] out_channel,
output reg [OUT_ST_DATA_W-1:0] out_data,
output reg out_startofpacket,
output reg out_endofpacket,
input [2:0] in_command_size_data
);
// ------------------------------------------------------------
// Local Parameters
// ------------------------------------------------------------
localparam IN_NUMSYMBOLS = IN_PKT_BYTEEN_H - IN_PKT_BYTEEN_L + 1;
localparam IN_DATA_W = IN_PKT_DATA_H - IN_PKT_DATA_L + 1;
localparam IN_BYTEEN_W = IN_NUMSYMBOLS;
localparam OUT_NUMSYMBOLS = OUT_PKT_BYTEEN_H - OUT_PKT_BYTEEN_L + 1;
localparam OUT_DATA_W = OUT_PKT_DATA_H - OUT_PKT_DATA_L + 1;
localparam OUT_BYTEEN_W = OUT_NUMSYMBOLS;
localparam BURST_TYPE_W = IN_PKT_BURST_TYPE_H - IN_PKT_BURST_TYPE_L + 1;
localparam BURST_SIZE_W = IN_PKT_BURST_SIZE_H - IN_PKT_BURST_SIZE_L + 1;
localparam RESPONSE_STATUS_W = IN_PKT_RESPONSE_STATUS_H - IN_PKT_RESPONSE_STATUS_L + 1;
localparam SYMBOL_W = IN_DATA_W / IN_NUMSYMBOLS;
localparam ADDRESS_W = IN_PKT_ADDR_H - IN_PKT_ADDR_L + 1;
localparam BYTE_CNT_W = IN_PKT_BYTE_CNT_H - IN_PKT_BYTE_CNT_L + 1;
localparam OUT_BYTE_CNT_W = OUT_PKT_BYTE_CNT_H - OUT_PKT_BYTE_CNT_L + 1;
localparam BWRAP_W = IN_PKT_BURSTWRAP_H - IN_PKT_BURSTWRAP_L + 1;
localparam SIZE_W = 2 ** BURST_SIZE_W;
localparam RATIO = (IN_NUMSYMBOLS > OUT_NUMSYMBOLS ?
IN_NUMSYMBOLS / OUT_NUMSYMBOLS :
OUT_NUMSYMBOLS / IN_NUMSYMBOLS );
localparam WIDE_NUMSYMBOLS = (IN_NUMSYMBOLS > OUT_NUMSYMBOLS ?
IN_NUMSYMBOLS : OUT_NUMSYMBOLS );
localparam WIDE_DATA = (IN_NUMSYMBOLS > OUT_NUMSYMBOLS ?
IN_DATA_W - (OUT_NUMSYMBOLS*SYMBOL_W) :
OUT_DATA_W - (IN_NUMSYMBOLS*SYMBOL_W));
localparam OUT_SEGMENT_W = OUT_NUMSYMBOLS * SYMBOL_W;
localparam NW_BITFORSELECT_R = clogb2(IN_NUMSYMBOLS);
localparam NW_BITFORSELECT_L = clogb2(OUT_NUMSYMBOLS) - 1;
localparam ALIGNED_BITS_L = clogb2(OUT_NUMSYMBOLS) - 1;
localparam WN_ADDR_LSBS = clogb2(RATIO);
localparam WN_ADDR_SELECT = clogb2(IN_NUMSYMBOLS);
localparam LOG_OUT_NUMSYMBOLS = clogb2(OUT_NUMSYMBOLS);
// ------------------------------------------------------------
// Utility Functions
// ------------------------------------------------------------
function integer clogb2;
input [63:0] value;
begin
clogb2 = 0;
while (value>0) begin
value = value >> 1;
clogb2 = clogb2 + 1;
end
clogb2 = clogb2 - 1;
end
endfunction // clogb2
function integer min;
input [31:0] a;
input [31:0] b;
begin
return (a < b) ? a : b;
end
endfunction
function integer max;
input [31:0] a;
input [31:0] b;
begin
return (a > b) ? a : b;
end
endfunction
function reg [clogb2(RATIO)-1:0] mask_to_select_correct_segments_for_size;
input [clogb2(RATIO)-1:0] select_output_segment;
input [9:0] size_ratio;
input int msb_select_bit;
integer i;
mask_to_select_correct_segments_for_size = '1;
for (i=0; i < msb_select_bit; i = i +1'b1 ) begin
if (clogb2(size_ratio) > i)
mask_to_select_correct_segments_for_size[i] = select_output_segment[i];
end
endfunction
function reg [ADDRESS_W-1:0] choose_packed_address_base_on_size;
input [9:0] size_ratio;
input int msb_select_bit;
integer i;
choose_packed_address_base_on_size = '1;
for (i=0; i < msb_select_bit; i = i +1'b1 ) begin
if (clogb2(size_ratio) > i)
choose_packed_address_base_on_size[i + NW_BITFORSELECT_R] = 1'b0;
end
endfunction
// ------------------------------------------------------------
// Computes how many bytes are in this transfer, based on the size
// encoding.
// ------------------------------------------------------------
function reg[9:0] bytes_in_transfer;
input [BURST_SIZE_W-1:0] axsize;
case (axsize)
4'b0000: bytes_in_transfer = 10'b0000000001;
4'b0001: bytes_in_transfer = 10'b0000000010;
4'b0010: bytes_in_transfer = 10'b0000000100;
4'b0011: bytes_in_transfer = 10'b0000001000;
4'b0100: bytes_in_transfer = 10'b0000010000;
4'b0101: bytes_in_transfer = 10'b0000100000;
4'b0110: bytes_in_transfer = 10'b0001000000;
4'b0111: bytes_in_transfer = 10'b0010000000;
4'b1000: bytes_in_transfer = 10'b0100000000;
4'b1001: bytes_in_transfer = 10'b1000000000;
default: bytes_in_transfer = 10'b0000000001;
endcase
endfunction
// ------------------------------------------------------------
// Pseudo-field Parameters
//
// The width adapter widens the data and byteenable fields in the
// output packet, thus changing the output packet format. By using
// pseudo-fields, we can avoid remapping each individual field to
// the output, which is a non-scalable solution.
//
// How? Assume the packet format is { FIRST, byteen, MID, data, LAST },
// where byteen and data positions are interchangeable. FIRST, MID and
// LAST are pseudo-fields that represent the collection of fields in
// those positions.
//
// Not all the pseudo-fields may exist for a given packet format. A
// non-existent field has reversed indices, so we have to be careful
// when using them.
// ------------------------------------------------------------
localparam IN_FIRST_L = 0,
IN_FIRST_H = min(IN_PKT_BYTEEN_L, IN_PKT_DATA_L) - 1,
IN_MID_L = min(IN_PKT_DATA_H, IN_PKT_BYTEEN_H) + 1,
IN_MID_H = max(IN_PKT_DATA_L, IN_PKT_BYTEEN_L) - 1,
IN_LAST_L = max(IN_PKT_BYTEEN_H, IN_PKT_DATA_H) + 1,
IN_LAST_H = IN_ST_DATA_W - 1,
FIRST_EXISTS = (IN_FIRST_H >= IN_FIRST_L),
MID_EXISTS = (IN_MID_H >= IN_MID_L),
LAST_EXISTS = (IN_LAST_H >= IN_LAST_L),
FIRST_W = IN_FIRST_H - IN_FIRST_L + 1,
MID_W = IN_MID_H - IN_MID_L + 1,
LAST_W = IN_LAST_H - IN_LAST_L + 1,
// -------------------------------------------------
// We cannot split the output map into generate blocks as we
// do for the inputs because address and size are mapped over
// the pseudo-fields. We ensure that the indices are always
// legal, even if the field is unused later on.
OUT_FIRST_L = 0,
OUT_FIRST_H = FIRST_EXISTS ?
min(OUT_PKT_BYTEEN_L, OUT_PKT_DATA_L) - 1 :
OUT_FIRST_L,
OUT_MID_L = min(OUT_PKT_DATA_H, OUT_PKT_BYTEEN_H) + 1,
OUT_MID_H = MID_EXISTS ?
max(OUT_PKT_DATA_L, OUT_PKT_BYTEEN_L) - 1 :
OUT_MID_L,
OUT_LAST_L = max(OUT_PKT_BYTEEN_H, OUT_PKT_DATA_H) + 1,
OUT_LAST_H = LAST_EXISTS ?
OUT_ST_DATA_W - 1 :
OUT_LAST_L;
// ------------------------------------------------------------
// Signals
// ------------------------------------------------------------
reg [BURST_SIZE_W-1:0] in_size_field;
reg [IN_DATA_W-1:0] in_data_field;
reg [IN_BYTEEN_W-1:0] in_byteen_field;
reg [ADDRESS_W-1:0] in_address_field;
reg [ADDRESS_W-1:0] address_from_packet;
reg [BYTE_CNT_W-1:0] in_byte_cnt_field;
reg [BWRAP_W-1:0] in_burstwrap_field;
reg [RESPONSE_STATUS_W-1:0] in_response_status_field;
reg in_cmpr_read;
reg in_lock_field;
reg in_write;
reg [BURST_TYPE_W-1:0] in_burst_type_field;
reg [BYTE_CNT_W-1:0] quantized_byte_cnt_field;
reg [BURST_SIZE_W-1:0] out_size_field;
reg [OUT_DATA_W-1:0] out_data_field;
reg [OUT_BYTEEN_W-1:0] out_byteen_field;
reg [ADDRESS_W-1:0] out_address_field;
reg out_cmpr_read;
reg [BYTE_CNT_W-1:0] out_byte_cnt_field;
reg out_lock_field;
reg [BURST_TYPE_W-1:0] out_burst_type_field;
reg [RESPONSE_STATUS_W-1:0] out_response_status_field;
reg [FIRST_W-1:0] in_first_field;
reg [FIRST_W-1:0] out_first_field;
reg [MID_W-1:0] in_mid_field;
reg [MID_W-1:0] out_mid_field;
reg [LAST_W-1:0] in_last_field;
reg [LAST_W-1:0] out_last_field;
reg [WIDE_DATA-1:0] data_reg;
reg [WIDE_NUMSYMBOLS-1:0] byteen_reg;
reg [ADDRESS_W-1:0] address_reg;
reg [BYTE_CNT_W-1:0] byte_cnt_reg;
reg use_reg;
reg startofpacket_reg;
reg endofpacket_reg;
reg [OUT_SEGMENT_W-1:0] mask;
reg [RESPONSE_STATUS_W-1:0] response_status_reg;
reg [ADDRESS_W-1:0] int_output_sel;
reg [clogb2(RATIO)-1:0] output_sel;
reg [OUT_SEGMENT_W-1:0] data_array [0:RATIO-1];
reg [OUT_NUMSYMBOLS-1:0] byteen_array [0:RATIO-1];
// In narrow-to-wide adaptation, each input datum/byteenable bit maps to
// one of OUT_NUMSYMBOLS/IN_NUMSYMBOLS subfields in the wider output
// packet. (Call these subfields "segments".) A subfield of the input
// address, in_bitforselect, selects the segment. Examples:
// 8-16 adaptation: in_bitforselect = in_address_field[0]
// 8-32 adaptation: in_bitforselect = in_address_field[1:0]
// 8-64 adaptation: in_bitforselect = in_address_field[2:0]
// 16-32 adaptation: in_bitforselect = in_address_field[1]
// 32-64 adaptation: in_bitforselect = in_address_field[2]
// The width of in_bitforselect is
// log2(OUT_NUM_SYMBOLS) - log2(IN_NUM_SYMBOLS) =
// log2(RATIO)
// The msb of in_bitforselect is driven by
// in_adress_field[log2(OUT_NUMSYMBOLS) - 1]
// The lsb of in_adress_field is driven by
// in_adress_field[log2(IN_NUMSYMBOLS)]
reg [clogb2(RATIO)-1:0] in_bitforselect;
integer i, j;
// ----------------------------------------
// Input Field Mapping
// ----------------------------------------
reg [ADDRESS_W-1:0] address_for_adaptation;
always @* begin
in_size_field = in_data[IN_PKT_BURST_SIZE_H :IN_PKT_BURST_SIZE_L ];
in_data_field = in_data[IN_PKT_DATA_H :IN_PKT_DATA_L ];
in_byteen_field = in_data[IN_PKT_BYTEEN_H :IN_PKT_BYTEEN_L ];
address_from_packet = in_data[IN_PKT_ADDR_H :IN_PKT_ADDR_L ];
in_byte_cnt_field = in_data[IN_PKT_BYTE_CNT_H :IN_PKT_BYTE_CNT_L ];
in_cmpr_read = in_data[IN_PKT_TRANS_COMPRESSED_READ];
in_write = in_data[IN_PKT_TRANS_WRITE];
in_lock_field = in_data[IN_PKT_TRANS_EXCLUSIVE];
in_burst_type_field = in_data[IN_PKT_BURST_TYPE_H :IN_PKT_BURST_TYPE_L ];
in_response_status_field = in_data[IN_PKT_RESPONSE_STATUS_H :IN_PKT_RESPONSE_STATUS_L];
end
// ----------------------------------------
// Process unaligned address for first address of the burst
// ----------------------------------------
generate
if (IN_NUMSYMBOLS > OUT_NUMSYMBOLS && ENABLE_ADDRESS_ALIGNMENT) begin
reg [ADDRESS_W + (BWRAP_W-1) + BURST_SIZE_W + BURST_TYPE_W - 1 :0] address_for_alignment;
reg [ADDRESS_W + clogb2(IN_NUMSYMBOLS)-1:0] address_after_aligned;
assign address_for_alignment = {address_from_packet, in_size_field};
assign address_for_adaptation = address_after_aligned[ADDRESS_W-1:0];
altera_merlin_address_alignment
#(
.ADDR_W (ADDRESS_W),
.BURSTWRAP_W (BWRAP_W),
.INCREMENT_ADDRESS (0),
.NUMSYMBOLS (IN_NUMSYMBOLS),
.SIZE_W (BURST_SIZE_W)
) check_and_align_address_to_size
(
.clk (clk),
.reset (reset),
.in_data (address_for_alignment),
.out_data (address_after_aligned),
.in_valid (),
.in_sop (),
.in_eop (),
.out_ready ()
);
end else begin
assign address_for_adaptation = address_from_packet;
end
endgenerate
generate begin
if (FIRST_EXISTS) begin
always @* begin
in_first_field = in_data[IN_FIRST_H:IN_FIRST_L];
end
end else begin
always @* begin
in_first_field = '0;
end
end
if (MID_EXISTS) begin
always @* begin
in_mid_field = in_data[IN_MID_H:IN_MID_L];
end
end else begin
always @* begin
in_mid_field = '0;
end
end
if (LAST_EXISTS) begin
always @* begin
in_last_field = in_data[IN_LAST_H:IN_LAST_L];
end
end
end
endgenerate
generate
//-------------------------------------------------------
//-------------------------------------------------------
// Wide-to-Narrow
//
// For every input cycle, we drive out a bunch'o'output
// cycles. Nothing fancier. Yes, it could be more
// optimal, but we'll leave that for another day.
//-------------------------------------------------------
//-------------------------------------------------------
if (IN_NUMSYMBOLS > OUT_NUMSYMBOLS) begin
wire [31:0] cmd_burst_size = CONSTANT_BURST_SIZE ? IN_NUMSYMBOLS : bytes_in_transfer(in_size_field);
// Below mess is just to avoid Quartus warnings about mis-sized assignments.
wire [31:0] int_out_numsymbols = OUT_NUMSYMBOLS;
wire [clogb2(OUT_NUMSYMBOLS):0] sized_out_numsymbols = int_out_numsymbols[clogb2(OUT_NUMSYMBOLS):0];
wire [31:0] int_out_size = (cmd_burst_size < OUT_NUMSYMBOLS) ? cmd_burst_size : OUT_NUMSYMBOLS;
wire [SIZE_W-1:0] sized_out_size = int_out_size[SIZE_W-1:0];
wire [31:0] int_ratio_minus_1 = (cmd_burst_size / OUT_NUMSYMBOLS) - 1;
wire [clogb2(RATIO)-1:0] sized_ratio_minus_1 = int_ratio_minus_1[clogb2(RATIO)-1:0];
wire [31:0] int_log2_out_numsymbols = clogb2(OUT_NUMSYMBOLS);
wire [BURST_SIZE_W-1:0] log2_out_numsymbols = int_log2_out_numsymbols[BURST_SIZE_W-1:0];
wire [31:0] int_byte_cnt_factor = (in_size_field < log2_out_numsymbols) ? log2_out_numsymbols : in_size_field;
wire [BURST_SIZE_W-1:0] sized_byte_cnt_factor = int_byte_cnt_factor[BURST_SIZE_W-1:0];
reg single_response_expected;
reg only_one_segment_asserted;
reg [RATIO-1:0] segments_with_be_asserted;
reg [clogb2(RATIO)-1:0] count;
assign single_response_expected = (RESPONSE_PATH && ((only_one_segment_asserted && in_startofpacket && in_endofpacket) || in_write));
always @(posedge clk, posedge reset) begin
if (reset) begin
address_reg <= '0;
byte_cnt_reg <= '0;
count <= '0;
use_reg <= '0;
endofpacket_reg <= '0;
data_reg <= '0;
byteen_reg <= '0;
end else begin
// If we're not working on a wide datum,
// then wait until one arrives.
if (~use_reg) begin
if (CONSTANT_BURST_SIZE) begin // when the system contains ONLY Avalon masters and slaves
address_reg[ADDRESS_W -1 : WN_ADDR_SELECT] <= in_address_field[ADDRESS_W -1 : WN_ADDR_SELECT];
address_reg[WN_ADDR_SELECT - 1 : 0] <= sized_out_numsymbols;
data_reg <= in_data_field[IN_DATA_W-1:OUT_NUMSYMBOLS*SYMBOL_W];
byteen_reg <= in_byteen_field >> OUT_NUMSYMBOLS;
byte_cnt_reg <= in_byte_cnt_field - sized_out_numsymbols;
end else begin
address_reg <= in_address_field + sized_out_size;
byte_cnt_reg <= (in_byte_cnt_field >> clogb2(IN_NUMSYMBOLS) << sized_byte_cnt_factor) - sized_out_numsymbols;
end
endofpacket_reg <= in_endofpacket;
if (in_valid && out_ready && !in_cmpr_read && (cmd_burst_size > OUT_NUMSYMBOLS) && !single_response_expected) begin
// Data has arrived!
count <= sized_ratio_minus_1;
use_reg <= 1'b1;
end
end else begin // if (count == 0)
// We have a wide datum in progress. Just wait until
// the previous datum is taken, and then set
// up the next transfer.
if (out_ready) begin
if (CONSTANT_BURST_SIZE) begin
address_reg[ADDRESS_W -1 : WN_ADDR_SELECT] <= in_address_field[ADDRESS_W -1 : WN_ADDR_SELECT];
address_reg[WN_ADDR_SELECT - 1 : 0] <= address_reg[WN_ADDR_SELECT - 1 : 0] + sized_out_numsymbols;
data_reg <= data_reg >> (OUT_NUMSYMBOLS * SYMBOL_W);
byteen_reg <= byteen_reg >> (OUT_NUMSYMBOLS);
end else begin
address_reg <= address_reg + sized_out_size;
end
byte_cnt_reg <= byte_cnt_reg - sized_out_numsymbols;
count <= count - 1'b1;
if (count == 1'b1)
// We're at the end of this word.
use_reg <= '0;
end // if (out_ready)
end // else: !if(count == 0)
end // if (posedge clk)
end // always @ (clk, reset)
always @* begin
// Calculate in_ready.
// If count is 0, then we don't have data underway, and we
// definitely won't be ready for it the first time 'round.
// If count is '1', then we're finishing a set, and we're
// ready if the output is.
// If count > 1, then we're mid set, and certainly
// not ready.
in_ready = 0;
if ( (cmd_burst_size <= OUT_NUMSYMBOLS) || count == 1 || in_cmpr_read )
in_ready = out_ready;
out_valid = in_valid;
out_channel = in_channel;
out_startofpacket = in_startofpacket;
out_endofpacket = 0;
out_size_field = (cmd_burst_size < OUT_NUMSYMBOLS) ? in_size_field : log2_out_numsymbols;
if (CONSTANT_BURST_SIZE) begin // For Avalon only
out_byteen_field = in_byteen_field[OUT_NUMSYMBOLS-1:0];
out_data_field = in_data_field[OUT_NUMSYMBOLS * SYMBOL_W-1:0];
out_byte_cnt_field = in_byte_cnt_field;
end else begin
out_byte_cnt_field = in_byte_cnt_field >> clogb2(IN_NUMSYMBOLS) << sized_byte_cnt_factor;
end
out_first_field = in_first_field;
out_mid_field = in_mid_field;
out_last_field = in_last_field;
out_cmpr_read = in_cmpr_read;
out_lock_field = in_lock_field;
out_burst_type_field = in_burst_type_field;
out_response_status_field = in_response_status_field;
// Case when command size <= OUT_NUMSYMBOLS: pass the cycle
// through, unmodified
if (cmd_burst_size <= OUT_NUMSYMBOLS) begin
out_endofpacket = in_endofpacket;
in_address_field = address_from_packet;
end // (cmd_burst_size <= OUT_NUMSYMBOLS)
else begin
// Case when we need to bus size data (size > OUT_NUMSYMBOLS).
out_lock_field = 0;
// Change fixed burst type opcodes to the repeated wrap
// opcode.
if (in_burst_type_field == 2'b00) begin
out_burst_type_field = 2'b11;
end
// On the first address of the burst, align and send this
// address to the network
in_address_field = address_for_adaptation;
end // (cmd_burst_size > OUT_NUMSYMBOLS)
out_address_field = in_address_field;
int_output_sel = in_address_field >> log2_out_numsymbols ;
if (in_cmpr_read)
out_endofpacket = 1;
if (use_reg) begin
out_startofpacket = 0;
// If it's the last cycle, or if there's no more data,
// we can allow an endofpacket.
if (count == 1)
out_endofpacket = endofpacket_reg;
out_byte_cnt_field = byte_cnt_reg;
out_address_field = address_reg;
if (CONSTANT_BURST_SIZE) begin // Avalon system
out_data_field = data_reg[(OUT_NUMSYMBOLS * SYMBOL_W)-1:0];
out_byteen_field = byteen_reg[OUT_NUMSYMBOLS-1:0];
byteen_array = '{RATIO {0} };
data_array = '{RATIO {0} };
end
int_output_sel = address_reg >> log2_out_numsymbols;
end
output_sel = int_output_sel[WN_ADDR_LSBS-1:0];
if (!CONSTANT_BURST_SIZE) begin
out_byteen_field = byteen_array[output_sel];
out_data_field = data_array[output_sel];
end
// Check each output-sized segment to see whether it
// is enabled (byteenables)
segments_with_be_asserted = 0;
for (i = 0; i < RATIO; i=i+1) begin
segments_with_be_asserted[i] = |in_byteen_field[i*OUT_BYTEEN_W +: OUT_BYTEEN_W];
end
// Determine whether only one segment is asserted. This code detects a power of two,
// i.e. only 1 bit is asserted.
only_one_segment_asserted = (segments_with_be_asserted && !(segments_with_be_asserted & (segments_with_be_asserted - 1)));
//-----------------------------------------
// Optimization for non-bursting wide-narrow response.
//
// Only one segment of the wide word will have asserted
// byteenables. Just pass that segment through and drop
// the rest. This should synthesize to an and-or mux.
//-----------------------------------------
if (OPTIMIZE_FOR_RSP | single_response_expected) begin
out_startofpacket = in_startofpacket;
out_endofpacket = in_endofpacket;
in_ready = out_ready;
//-----------------------------------------
// Not correct, but nothing in the response path looks
// at these today (10.1). Must be corrected when we allow
// multiple width adapters on a path.
//-----------------------------------------
out_address_field = in_address_field;
out_byte_cnt_field = in_byte_cnt_field;
out_data_field = '0;
out_byteen_field = '0;
for (i = 0; i < RATIO; i=i+1) begin
mask = '0;
for (j = 0; j < OUT_NUMSYMBOLS; j=j+1) begin
mask |= {SYMBOL_W{in_byteen_field[i*OUT_NUMSYMBOLS+j]}} << (j*SYMBOL_W);
end
out_data_field |= mask & in_data_field[i*OUT_SEGMENT_W +: OUT_SEGMENT_W];
out_byteen_field |= in_byteen_field[i*OUT_NUMSYMBOLS +: OUT_NUMSYMBOLS];
end
end
else begin // to prevent latches
j = 0;
mask = '0;
end
end // always @ *
//-------------------------------------------------------
// Configuration Error Checking
//-------------------------------------------------------
// synthesis translate_off
initial begin
if (RATIO * OUT_NUMSYMBOLS != IN_NUMSYMBOLS) begin
$display("%m : The ratio of input symbols to output symbols must be an integer.");
$stop();
end
end
// synthesis translate_on
if (!CONSTANT_BURST_SIZE) begin
integer ibyte;
always @* begin
for(ibyte=0; ibyte<RATIO; ibyte=ibyte+1) begin: mux_mapping
data_array[ibyte] = in_data_field[(ibyte*OUT_NUMSYMBOLS*SYMBOL_W)+:OUT_NUMSYMBOLS*SYMBOL_W];
byteen_array[ibyte] = in_byteen_field[(ibyte*OUT_NUMSYMBOLS)+:OUT_NUMSYMBOLS];
end
end
end
end // if (IN_NUMSYMBOLS > OUT_NUMSYMBOLS)
//-------------------------------------------------------
//-------------------------------------------------------
// Narrow-to-Wide
//-------------------------------------------------------
//-------------------------------------------------------
if (OUT_NUMSYMBOLS > IN_NUMSYMBOLS) begin
wire p0_valid;
reg p0_startofpacket;
reg p0_endofpacket;
reg [IN_DATA_W-1:0] p0_data_field;
reg [IN_BYTEEN_W-1:0] p0_byteen_field;
reg [ADDRESS_W-1:0] p0_address_field;
reg [BWRAP_W-1:0] p0_bwrap_field;
reg [BYTE_CNT_W-1:0] p0_byte_cnt_field;
reg [clogb2(RATIO)-1:0] p0_bitforselect;
reg p0_cmpr_read;
reg [FIRST_W-1:0] p0_first_field;
reg [MID_W-1:0] p0_mid_field;
reg [LAST_W-1:0] p0_last_field;
reg p0_use_reg;
reg [ST_CHANNEL_W-1:0] p0_channel;
reg [BURST_SIZE_W-1:0] p0_burst_size;
reg [BURST_SIZE_W-1:0] p0_ori_burst_size;
reg p0_out_lock_field;
reg [BURST_TYPE_W-1:0] p0_burst_type_field;
reg [RESPONSE_STATUS_W-1:0] p0_response_status_field;
reg p0_reg_startofpacket;
reg p0_reg_endofpacket;
reg [IN_DATA_W-1:0] p0_reg_data_field;
reg [IN_BYTEEN_W-1:0] p0_reg_byteen_field;
reg [ADDRESS_W-1:0] p0_reg_address_field;
reg [BWRAP_W-1:0] p0_reg_bwrap_field;
reg [BYTE_CNT_W-1:0] p0_reg_byte_cnt_field;
reg [clogb2(RATIO)-1:0] p0_reg_bitforselect;
reg p0_reg_cmpr_read;
reg [FIRST_W-1:0] p0_reg_first_field;
reg [MID_W-1:0] p0_reg_mid_field;
reg [LAST_W-1:0] p0_reg_last_field;
reg [ST_CHANNEL_W-1:0] p0_reg_channel;
reg [BURST_SIZE_W-1:0] p0_reg_burst_size;
reg [BURST_SIZE_W-1:0] p0_reg_ori_burst_size;
reg [BURST_TYPE_W-1:0] p0_reg_burst_type_field;
reg [RESPONSE_STATUS_W-1:0] p0_reg_response_status_field;
reg p0_reg_out_lock_field;
wire p1_valid;
reg p1_ready;
reg p1_startofpacket;
reg p1_endofpacket;
reg [IN_DATA_W-1:0] p1_data_field;
reg [IN_BYTEEN_W-1:0] p1_byteen_field;
reg [ADDRESS_W-1:0] p1_address_field;
reg [ADDRESS_W-1:0] out_address_field_mask;
reg [BYTE_CNT_W-1:0] p1_byte_cnt_field;
reg [BURST_SIZE_W-1:0] p1_burst_size;
reg [BYTE_CNT_W-1:0] p1_byte_cnt_unpack_field;
wire response_data_packing;
reg [clogb2(RATIO)-1:0] p1_shift_correct_ouput_segments;
reg [clogb2(RATIO)-1:0] p1_push_data_to_output;
reg p1_cmpr_read;
reg [RESPONSE_STATUS_W-1:0] p1_response_status_field;
reg unc_sink_valid;
wire unc_sink_ready;
wire unc_src_startofpacket;
wire unc_src_endofpacket;
wire unc_src_valid;
wire [ADDRESS_W-1:0] unc_src_addr;
wire [BYTE_CNT_W-1:0] unc_src_byte_cnt;
wire aligned_addr;
wire aligned_byte_cnt;
wire unaligned_read;
reg [BYTE_CNT_W-1:0] count;
reg count_eq_zero;
wire [31:0] int_in_numsymbols = IN_NUMSYMBOLS;
wire [BYTE_CNT_W-1:0] byte_cnt_sized_in_num_symbols =
int_in_numsymbols[BYTE_CNT_W-1:0];
reg [9:0] cmd_burst_size;
wire [31:0] out_numsymbols_wire = LOG_OUT_NUMSYMBOLS;
wire [31:0] int_encoded_burstsize = NW_BITFORSELECT_R; //NW_BITFORSELECT_R is the log2 of IN_NUMSYMBOLS
wire [BURST_SIZE_W-1:0] encoded_burstsize = int_encoded_burstsize[BURST_SIZE_W-1:0];
// Care about burstwrap on command path only
if (RESPONSE_PATH == 0) begin
assign in_burstwrap_field = in_data[IN_PKT_BURSTWRAP_H:IN_PKT_BURSTWRAP_L];
end
else begin
assign in_burstwrap_field = {BWRAP_W{1'b1}};
end
// To use "read response merging" the Width adapter need to know the size of the command
// to check if downside happen. For AXI system, the fifo will store this number (non-packing: we use "combined width adapter")
// but in case system without AXI, the system use stand alone width adapter and it cannot read this value
// Make a condition incase we see stand alone WA, set this in_command_burst_size to input size
//wire [2:0] in_command_burst_size = out_numsymbols_wire[2:0];
//if (!((PACKING == 1) & (CONSTANT_BURST_SIZE == 1))) // stand alone WA
// begin
// assign in_command_burst_size = in_command_size_data;
// end
reg [BURST_SIZE_W-1:0] in_ori_size_field;
always @* begin
in_ori_size_field = in_data[IN_PKT_ORI_BURST_SIZE_H :IN_PKT_ORI_BURST_SIZE_L ];
end
reg [9:0] size_ratio;
// --------------------------------------------
// Stage 0: buffer the input cycle if read burst
// uncompression is going to happen.
//
// This avoids the possibility of a master receiving a premature
// response while its read burst is still being waitrequested.
// --------------------------------------------
always @(posedge clk, posedge reset) begin
if (reset) begin
p0_use_reg <= 1'b0;
p0_reg_startofpacket <= 1'b0;
p0_reg_endofpacket <= 1'b0;
p0_reg_data_field <= '0;
p0_reg_bwrap_field <= '0;
p0_reg_byteen_field <= '0;
p0_reg_address_field <= '0;
p0_reg_byte_cnt_field <= '0;
p0_reg_cmpr_read <= 1'b0;
p0_reg_first_field <= '0;
p0_reg_mid_field <= '0;
p0_reg_last_field <= '0;
p0_reg_channel <= '0;
p0_reg_burst_size <= '0;
p0_reg_ori_burst_size <= '0;
p0_reg_out_lock_field <= '0;
p0_reg_burst_type_field <= '0;
p0_reg_response_status_field <= '0;
end else begin
if (unaligned_read & in_valid)
p0_use_reg <= 1'b1;
if (unc_src_endofpacket & p1_ready)
p0_use_reg <= 1'b0;
if (unaligned_read) begin
p0_reg_startofpacket <= p0_startofpacket;
p0_reg_endofpacket <= p0_endofpacket;
p0_reg_data_field <= p0_data_field;
p0_reg_bwrap_field <= p0_bwrap_field;
p0_reg_byteen_field <= p0_byteen_field;
p0_reg_address_field <= p0_address_field;
p0_reg_byte_cnt_field <= p0_byte_cnt_field;
p0_reg_cmpr_read <= p0_cmpr_read;
p0_reg_first_field <= p0_first_field;
p0_reg_mid_field <= p0_mid_field;
p0_reg_last_field <= p0_last_field;
p0_reg_channel <= p0_channel;
p0_reg_burst_size <= p0_burst_size;
p0_reg_ori_burst_size <= p0_ori_burst_size;
p0_reg_out_lock_field <= p0_out_lock_field;
p0_reg_burst_type_field <= p0_burst_type_field;
p0_reg_response_status_field <= p0_response_status_field;
end
end
end
always @* begin
in_ready = p1_ready;
// accept on the first cycle
if (unaligned_read & in_valid & ~p0_use_reg)
in_ready = 1;
if (p0_use_reg)
in_ready = 0;
end
always @* begin
p0_startofpacket = in_startofpacket;
p0_endofpacket = in_endofpacket;
p0_data_field = in_data_field;
p0_bwrap_field = in_burstwrap_field;
p0_byteen_field = in_byteen_field;
//p0_address_field = in_address_field;
p0_address_field = address_for_adaptation; // read address from oacket
p0_byte_cnt_field = in_byte_cnt_field;
p0_cmpr_read = in_cmpr_read;
p0_first_field = in_first_field;
p0_mid_field = in_mid_field;
p0_last_field = in_last_field;
p0_channel = in_channel;
p0_burst_size = in_size_field;
p0_ori_burst_size = in_ori_size_field;
p0_out_lock_field = in_lock_field;
p0_burst_type_field = in_burst_type_field;
p0_response_status_field = in_response_status_field;
if (p0_use_reg) begin
p0_startofpacket = p0_reg_startofpacket;
p0_endofpacket = p0_reg_endofpacket;
p0_data_field = p0_reg_data_field;
p0_bwrap_field = p0_reg_bwrap_field;
p0_byteen_field = p0_reg_byteen_field;
p0_address_field = p0_reg_address_field;
p0_byte_cnt_field = p0_reg_byte_cnt_field;
p0_cmpr_read = p0_reg_cmpr_read;
p0_first_field = p0_reg_first_field;
p0_mid_field = p0_reg_mid_field;
p0_last_field = p0_reg_last_field;
p0_channel = p0_reg_channel;
p0_burst_size = p0_reg_burst_size;
p0_ori_burst_size = p0_reg_ori_burst_size;
p0_out_lock_field = p0_reg_out_lock_field;
p0_burst_type_field = p0_reg_burst_type_field;
p0_response_status_field = p0_reg_response_status_field;
end
end
assign p0_valid = in_valid | p0_use_reg;
// --------------------------------------------
// Stage 1: uncompress the input packet if necessary
// --------------------------------------------
assign p1_valid = (unaligned_read) ? unc_src_valid : p0_valid;
assign aligned_addr = (p0_address_field[ALIGNED_BITS_L:0] == 0);
assign aligned_byte_cnt = (p0_byte_cnt_field[ALIGNED_BITS_L:0] == 0);
if ((RESPONSE_PATH == 0) && (PACKING == 1)) begin // if this is avalon then checking on aligned,
assign unaligned_read = p0_cmpr_read & (~aligned_addr || ~aligned_byte_cnt);
end else begin
assign unaligned_read = '0;
end
always @* begin
p1_data_field = p0_data_field;
p1_byteen_field = p0_byteen_field;
p1_startofpacket = p0_startofpacket;
p1_endofpacket = p0_endofpacket;
p1_address_field = p0_address_field;
p1_byte_cnt_field = p0_byte_cnt_field;
p1_cmpr_read = p0_cmpr_read;
p1_response_status_field = p0_response_status_field;
p1_burst_size = p0_burst_size;
unc_sink_valid = 0;
if (unaligned_read) begin
unc_sink_valid = p0_valid;
p1_startofpacket = unc_src_startofpacket;
p1_endofpacket = unc_src_endofpacket;
p1_address_field = unc_src_addr;
p1_byte_cnt_field = unc_src_byte_cnt;
p1_cmpr_read = 0;
end
end
altera_merlin_burst_uncompressor
#(
.ADDR_W (ADDRESS_W),
.BURSTWRAP_W (BWRAP_W),
.BYTE_CNT_W (BYTE_CNT_W),
.PKT_SYMBOLS (IN_NUMSYMBOLS),
.BURST_SIZE_W(BURST_SIZE_W)
) uncompressor (
.clk (clk),
.reset (reset),
.sink_startofpacket (p0_startofpacket),
.sink_endofpacket (p0_endofpacket),
.sink_valid (unc_sink_valid),
.sink_ready (unc_sink_ready),
.sink_addr (p0_address_field),
.sink_burstwrap (p0_bwrap_field),
.sink_byte_cnt (p0_byte_cnt_field),
.sink_is_compressed (1'b1), // should always be compressed
.sink_burstsize (encoded_burstsize),
.source_startofpacket (unc_src_startofpacket),
.source_endofpacket (unc_src_endofpacket),
.source_valid (unc_src_valid),
.source_ready (p1_ready),
.source_addr (unc_src_addr),
.source_burstwrap (),
.source_byte_cnt (unc_src_byte_cnt),
.source_is_compressed (),
.source_burstsize ()
);
// --------------------------------------------
// Stage 2: perform narrow to wide adaptation on the beats
// --------------------------------------------
always @(posedge clk, posedge reset) begin
if (reset) begin
data_reg <= '0;
byteen_reg <= '0;
startofpacket_reg <= '0;
count <= '0;
count_eq_zero <= '1;
response_status_reg <= '0;
end else begin
if (p1_valid && (out_ready || ~out_valid)) begin
// Lay input data & input byte enables into
// the temp registers
data_reg <= data_reg | (p1_data_field << (p1_shift_correct_ouput_segments *IN_NUMSYMBOLS*SYMBOL_W));
byteen_reg <= byteen_reg | (p1_byteen_field << (p1_shift_correct_ouput_segments *IN_NUMSYMBOLS));
response_status_reg <= out_response_status_field;
// Capture the stuff that's to be held constant
if (count_eq_zero) begin
startofpacket_reg <= p1_startofpacket;
if (~p1_endofpacket) begin
count <= p1_byte_cnt_field - byte_cnt_sized_in_num_symbols;
count_eq_zero <=
~|(p1_byte_cnt_field - byte_cnt_sized_in_num_symbols);
end
end else begin
count <= count - byte_cnt_sized_in_num_symbols;
count_eq_zero <= ~|(count - byte_cnt_sized_in_num_symbols);
end
//if (p1_endofpacket || (p1_shift_correct_ouput_segments == '1)) begin
if (p1_endofpacket || (p1_push_data_to_output == '1)) begin
data_reg <= '0;
byteen_reg <= '0;
response_status_reg <= '0;
end
if (out_valid && out_ready) begin
startofpacket_reg <= '0;
end
end // if (p1_valid && (out_ready || ~out_valid))
end // if (posedge clk)
end // always @ (clk, reset)
always @* begin
// Handle narrow-size transaction from the master:
// The width of in_bitforselect is
// log2(OUT_NUM_SYMBOLS) - log2(IN_NUM_SYMBOLS) =
// log2(RATIO)
// The msb of in_bitforselect is driven by: in_adress_field[log2(OUT_NUMSYMBOLS) - 1]
// The lsb of in_adress_field is driven by: in_adress_field[log2(IN_NUMSYMBOLS)]
// The function: mask_to_select_segments_for_size: is used to build a mask that changed at run-time
// when narrow-size transaction, It recaculates the width of in_bitforselect base on size ratio
// EX: Full-size transaction (2 bytes)N-W: in_bitforselect = in_address[1:0]
// Narrow-size transaction(1 byte)N-W: in_bitforselect = {1, in_address[0]}
p1_shift_correct_ouput_segments = p1_address_field[NW_BITFORSELECT_L:NW_BITFORSELECT_R];
// size ratio betwen command size and response size
//cmd_burst_size = bytes_in_transfer(in_command_burst_size);
cmd_burst_size = bytes_in_transfer(p0_ori_burst_size);
size_ratio = cmd_burst_size >> in_size_field;
if (RESPONSE_PATH == 0) begin
// if the WA is on command path, Avalon interconnect default
// bitselectfor data packing and push out data are same, compile time
p1_push_data_to_output = p1_shift_correct_ouput_segments;
end else begin
// the WA is on reponse path and default: PACKING = 1
// on response path, need based on size, run-time, to determinite output segment
p1_push_data_to_output = mask_to_select_correct_segments_for_size(p1_shift_correct_ouput_segments, size_ratio, clogb2(RATIO));
out_address_field_mask = choose_packed_address_base_on_size(size_ratio, clogb2(RATIO));
end
// We push data to the output whenever the input is
// an endofpacket, or the input drives the most-significant
// segment of the wider output word.
out_valid = 0;
if (PACKING == 1) begin
if (p1_endofpacket || (p1_push_data_to_output == '1)) begin
out_valid = p1_valid;
end
end else begin
out_valid = p1_valid;
end
out_startofpacket = p1_startofpacket || startofpacket_reg;
out_endofpacket = p1_endofpacket;
// Compressed read with byte_cnt > input interface width:
// this is a read burst spanning more than the originating
// interface of data, so all byteenables must be asserted.
if (p1_cmpr_read && (p1_byte_cnt_field > IN_NUMSYMBOLS)) begin
out_byteen_field = '1;
end else begin
if (PACKING == 1) begin // byteenable only affect on command path
out_byteen_field = byteen_reg |
(p1_byteen_field << (p1_shift_correct_ouput_segments*IN_NUMSYMBOLS));
end else begin // non-packing: shift input byteenable to correct position
out_byteen_field = (p1_byteen_field << (p1_shift_correct_ouput_segments*IN_NUMSYMBOLS));
end
end
// caculate bytecnt "unpack" according to OUTNUMSYMBOLS
p1_byte_cnt_unpack_field = p1_byte_cnt_field << clogb2(RATIO);
out_address_field = p1_address_field;
if (RESPONSE_PATH == 0) begin
if (PACKING == 1) begin // if the WA is on command path, Avalon interconnect default
out_data_field = data_reg | (p1_data_field << (p1_shift_correct_ouput_segments *IN_NUMSYMBOLS*SYMBOL_W));
out_byte_cnt_field = quantized_byte_cnt_field;
out_address_field[NW_BITFORSELECT_L:0] = 0;
out_size_field = out_numsymbols_wire[BURST_SIZE_W-1:0]; // for Avalon the size is converted to slave side
end else begin
out_data_field = (p1_data_field << (p1_shift_correct_ouput_segments *IN_NUMSYMBOLS*SYMBOL_W));
out_byte_cnt_field = p1_byte_cnt_unpack_field;
out_size_field = p1_burst_size;
end
end else begin // the WA is on reponse path and default: PACKING = 1
//if (in_size_field < in_command_burst_size) begin // downsize happen on command path, the response need packing
if (in_size_field < in_ori_size_field) begin // downsize happen on command path, the response need packing
out_data_field = data_reg
| (p1_data_field << (p1_shift_correct_ouput_segments *IN_NUMSYMBOLS*SYMBOL_W));
out_address_field = p1_address_field & out_address_field_mask;
out_size_field = p1_burst_size;
out_byte_cnt_field = p1_byte_cnt_field;
end else begin // narrow transaction on command path, reponse packet will not packed
out_data_field = (p1_data_field << (p1_shift_correct_ouput_segments *IN_NUMSYMBOLS*SYMBOL_W));
out_byte_cnt_field = p1_byte_cnt_field;
out_size_field = p1_burst_size;
end
end
//if (in_size_field < in_command_burst_size) begin // downsize happen on command path, the response need packing
if (in_size_field < in_ori_size_field) begin // downsize happen on command path, the response need packing
// Response merging: rules: DECERR(11) > SLVERR (10) > OKAY (00)
// EXOKAY will not happen on merging
out_response_status_field = '0;
if (response_status_reg >= p1_response_status_field) begin
out_response_status_field = response_status_reg;
end else begin
out_response_status_field = p1_response_status_field;
end
end else begin // narrow transaction on command path, reponse packet will not packed
out_response_status_field = p1_response_status_field;
end
out_cmpr_read = p1_cmpr_read;
// nothing touches these fields, so assign them
// directly from the input fields
out_first_field = p0_first_field;
out_mid_field = p0_mid_field;
out_last_field = p0_last_field;
out_lock_field = p0_out_lock_field;
out_channel = p0_channel;
out_burst_type_field = p0_burst_type_field;
end // always @ *
//-------------------------------------------------------
// output byte_cnt, rounded up to alignment with the output-side
// address map footprint implied by the input-side access.
//
// See "option 3" in Appendix C of
// merlin_interconnect_architecture_fd_91.doc.
//-------------------------------------------------------
reg [NW_BITFORSELECT_L:0] low_addr_bits;
always @* begin
low_addr_bits = p1_address_field[NW_BITFORSELECT_L:0];
quantized_byte_cnt_field = low_addr_bits +
p1_byte_cnt_field +
{clogb2(OUT_NUMSYMBOLS){1'b1}};
quantized_byte_cnt_field[NW_BITFORSELECT_L:0] = '0;
end
//-------------------------------------------------------
// Backpressure
//-------------------------------------------------------
always @ * begin
p1_ready = out_ready || ~out_valid;
end
end // if (OUT_NUMSYMBOLS > IN_NUMSYMBOLS)
//-------------------------------------------------------
//-------------------------------------------------------
// Same Width. Seems kind of silly, but let's be complete.
//-------------------------------------------------------
//-------------------------------------------------------
if (OUT_NUMSYMBOLS == IN_NUMSYMBOLS) begin
always @* begin
in_ready = out_ready;
out_valid = in_valid;
out_channel = in_channel;
out_startofpacket = in_startofpacket;
out_endofpacket = in_endofpacket;
out_size_field = in_size_field;
out_data_field = in_data_field;
out_byteen_field = in_byteen_field;
out_address_field = in_address_field;
out_byte_cnt_field = in_byte_cnt_field;
out_response_status_field = in_response_status_field;
out_lock_field = in_lock_field;
out_burst_type_field = in_burst_type_field;
out_cmpr_read = in_cmpr_read;
out_first_field = in_first_field;
out_mid_field = in_mid_field;
out_last_field = in_last_field;
end // always @ *
end // if (OUT_NUMSYMBOLS == IN_NUMSYMBOLS)
endgenerate
// ---------------------------------------
// Output Field Mapping
//
// Conditionally assign the pseudo-fields. Assign address and size
// last, because they partly override the pseudo-fields.
// ---------------------------------------
always @* begin
if (FIRST_EXISTS)
out_data[OUT_FIRST_H:OUT_FIRST_L] = out_first_field;
if (MID_EXISTS)
out_data[OUT_MID_H:OUT_MID_L] = out_mid_field;
if (LAST_EXISTS)
out_data[OUT_LAST_H:OUT_LAST_L] = out_last_field;
out_data[OUT_PKT_BURST_SIZE_H : OUT_PKT_BURST_SIZE_L ] = out_size_field;
out_data[OUT_PKT_DATA_H : OUT_PKT_DATA_L ] = out_data_field;
out_data[OUT_PKT_BYTEEN_H : OUT_PKT_BYTEEN_L ] = out_byteen_field;
out_data[OUT_PKT_ADDR_H : OUT_PKT_ADDR_L ] = out_address_field;
out_data[OUT_PKT_BYTE_CNT_H : OUT_PKT_BYTE_CNT_L ] = out_byte_cnt_field;
out_data[OUT_PKT_TRANS_COMPRESSED_READ ] = out_cmpr_read;
out_data[OUT_PKT_TRANS_EXCLUSIVE ] = out_lock_field;
out_data[OUT_PKT_BURST_TYPE_H : OUT_PKT_BURST_TYPE_L ] = out_burst_type_field;
out_data[OUT_PKT_RESPONSE_STATUS_H : OUT_PKT_RESPONSE_STATUS_L] = out_response_status_field;
end // always @ *
endmodule // width_adapter