// (C) 2001-2013 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/13.0sp1/ip/merlin/altera_merlin_master_agent/altera_merlin_master_agent.sv#1 $ // $Revision: #1 $ // $Date: 2013/03/07 $ // $Author: swbranch $ // -------------------------------------- // Merlin Master Agent // // Converts Avalon-MM transactions into // Merlin network packets. // -------------------------------------- `timescale 1 ns / 1 ns module altera_merlin_master_agent #( // ------------------- // Packet Format Parameters // ------------------- parameter PKT_QOS_H = 109, PKT_QOS_L = 106, PKT_DATA_SIDEBAND_H = 105, PKT_DATA_SIDEBAND_L = 98, PKT_ADDR_SIDEBAND_H = 97, PKT_ADDR_SIDEBAND_L = 93, PKT_CACHE_H = 92, PKT_CACHE_L = 89, PKT_THREAD_ID_H = 88, PKT_THREAD_ID_L = 87, PKT_BEGIN_BURST = 81, PKT_PROTECTION_H = 80, PKT_PROTECTION_L = 80, PKT_BURSTWRAP_H = 79, PKT_BURSTWRAP_L = 77, PKT_BYTE_CNT_H = 76, PKT_BYTE_CNT_L = 74, PKT_ADDR_H = 73, PKT_ADDR_L = 42, PKT_BURST_SIZE_H = 86, PKT_BURST_SIZE_L = 84, PKT_BURST_TYPE_H = 94, PKT_BURST_TYPE_L = 93, PKT_TRANS_EXCLUSIVE = 83, PKT_TRANS_LOCK = 82, PKT_TRANS_COMPRESSED_READ = 41, PKT_TRANS_POSTED = 40, PKT_TRANS_WRITE = 39, PKT_TRANS_READ = 38, PKT_DATA_H = 37, PKT_DATA_L = 6, PKT_BYTEEN_H = 5, PKT_BYTEEN_L = 2, PKT_SRC_ID_H = 1, PKT_SRC_ID_L = 1, PKT_DEST_ID_H = 0, PKT_DEST_ID_L = 0, PKT_RESPONSE_STATUS_L = 110, PKT_RESPONSE_STATUS_H = 111, ST_DATA_W = 112, ST_CHANNEL_W = 1, // ------------------- // Agent Parameters // ------------------- AV_BURSTCOUNT_W = 3, ID = 1, SUPPRESS_0_BYTEEN_RSP = 1, BURSTWRAP_VALUE = 4, CACHE_VALUE = 0, SECURE_ACCESS_BIT = 1, USE_READRESPONSE = 0, USE_WRITERESPONSE = 0, // ------------------- // Derived Parameters // ------------------- PKT_BURSTWRAP_W = PKT_BURSTWRAP_H - PKT_BURSTWRAP_L + 1, PKT_BYTE_CNT_W = PKT_BYTE_CNT_H - PKT_BYTE_CNT_L + 1, PKT_PROTECTION_W= PKT_PROTECTION_H - PKT_PROTECTION_L + 1, PKT_ADDR_W = PKT_ADDR_H - PKT_ADDR_L + 1, PKT_DATA_W = PKT_DATA_H - PKT_DATA_L + 1, PKT_BYTEEN_W = PKT_BYTEEN_H - PKT_BYTEEN_L + 1, PKT_SRC_ID_W = PKT_SRC_ID_H - PKT_SRC_ID_L + 1, PKT_DEST_ID_W = PKT_DEST_ID_H - PKT_DEST_ID_L + 1 ) ( // ------------------- // Clock & Reset // ------------------- input clk, input reset, // ------------------- // Avalon-MM Anti-Master // ------------------- input [PKT_ADDR_W-1 : 0] av_address, input av_write, input av_read, input [PKT_DATA_W-1 : 0] av_writedata, output reg [PKT_DATA_W-1 : 0] av_readdata, output reg av_waitrequest, output reg av_readdatavalid, input [PKT_BYTEEN_W-1 : 0] av_byteenable, input [AV_BURSTCOUNT_W-1 : 0] av_burstcount, input av_debugaccess, input av_lock, output reg [1:0] av_response, input av_writeresponserequest, output reg av_writeresponsevalid, // ------------------- // Command Source // ------------------- output reg cp_valid, output reg [ST_DATA_W-1 : 0] cp_data, output wire cp_startofpacket, output wire cp_endofpacket, input cp_ready, // ------------------- // Response Sink // ------------------- input rp_valid, input [ST_DATA_W-1 : 0] rp_data, input [ST_CHANNEL_W-1 : 0] rp_channel, input rp_startofpacket, input rp_endofpacket, output reg rp_ready ); // ------------------------------------------------------------ // Utility Functions // ------------------------------------------------------------ function integer clogb2; input [31:0] value; begin for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) value = value >> 1; clogb2 = clogb2 - 1; end endfunction // clogb2 localparam MAX_BURST = 1 << (AV_BURSTCOUNT_W - 1); localparam NUMSYMBOLS = PKT_BYTEEN_W; localparam BURSTING = (MAX_BURST > NUMSYMBOLS); localparam BITS_TO_ZERO = clogb2(NUMSYMBOLS); localparam BURST_SIZE = clogb2(NUMSYMBOLS); typedef enum bit [1:0] { FIXED = 2'b00, INCR = 2'b01, WRAP = 2'b10, OTHER_WRAP = 2'b11 } MerlinBurstType; // -------------------------------------- // Potential optimization: compare in words to save bits? // -------------------------------------- wire is_burst; assign is_burst = (BURSTING) & (av_burstcount > NUMSYMBOLS); wire [31:0] burstwrap_value_int = BURSTWRAP_VALUE; wire [31:0] id_int = ID; wire [2:0] burstsize_sig = BURST_SIZE[2:0]; wire [1:0] bursttype_value = burstwrap_value_int[PKT_BURSTWRAP_W-1] ? INCR : WRAP; // -------------------------------------- // Address alignment // // The packet format requires that addresses be aligned to // the transaction size. // -------------------------------------- wire [PKT_ADDR_W-1 : 0] av_address_aligned; generate if (NUMSYMBOLS > 1) begin assign av_address_aligned = {av_address[PKT_ADDR_W-1 : BITS_TO_ZERO], {BITS_TO_ZERO {1'b0}}}; end else begin assign av_address_aligned = av_address; end endgenerate // -------------------------------------- // Command & Response Construction // -------------------------------------- always @* begin cp_data = '0; // default assignment; override below as needed. cp_data[PKT_PROTECTION_L] = av_debugaccess; cp_data[PKT_PROTECTION_L+1] = SECURE_ACCESS_BIT[0]; // Default Non-secured (AXI) cp_data[PKT_PROTECTION_L+2] = 1'b0; // Default Data access (AXI) cp_data[PKT_BURSTWRAP_H:PKT_BURSTWRAP_L ] = burstwrap_value_int[PKT_BURSTWRAP_W-1:0]; cp_data[PKT_BYTE_CNT_H :PKT_BYTE_CNT_L ] = av_burstcount; cp_data[PKT_ADDR_H :PKT_ADDR_L ] = av_address_aligned; cp_data[PKT_TRANS_EXCLUSIVE ] = 1'b0; cp_data[PKT_TRANS_LOCK ] = av_lock; cp_data[PKT_TRANS_COMPRESSED_READ ] = av_read & is_burst; cp_data[PKT_TRANS_READ ] = av_read; cp_data[PKT_TRANS_WRITE ] = av_write; // posted and non-posted write avaiable now cp_data[PKT_TRANS_POSTED ] = av_write & !av_writeresponserequest; cp_data[PKT_DATA_H :PKT_DATA_L ] = av_writedata; cp_data[PKT_BYTEEN_H :PKT_BYTEEN_L ] = av_byteenable; cp_data[PKT_BURST_SIZE_H:PKT_BURST_SIZE_L] = burstsize_sig; cp_data[PKT_BURST_TYPE_H:PKT_BURST_TYPE_L] = bursttype_value; cp_data[PKT_SRC_ID_H :PKT_SRC_ID_L ] = id_int[PKT_SRC_ID_W-1:0]; cp_data[PKT_THREAD_ID_H:PKT_THREAD_ID_L ] = '0; cp_data[PKT_CACHE_H :PKT_CACHE_L ] = CACHE_VALUE[3:0]; cp_data[PKT_QOS_H : PKT_QOS_L] = '0; cp_data[PKT_ADDR_SIDEBAND_H:PKT_ADDR_SIDEBAND_L] = '0; cp_data[PKT_DATA_SIDEBAND_H :PKT_DATA_SIDEBAND_L] = '0; av_readdata = rp_data[PKT_DATA_H : PKT_DATA_L]; if (USE_WRITERESPONSE || USE_READRESPONSE) av_response = rp_data[PKT_RESPONSE_STATUS_H : PKT_RESPONSE_STATUS_L]; else av_response = '0; end // -------------------------------------- // Command Control // -------------------------------------- always @* begin cp_valid = 0; if (av_write || av_read) cp_valid = 1; end generate if (BURSTING) begin reg sop_enable; always @(posedge clk, posedge reset) begin if (reset) begin sop_enable <= 1'b1; end else begin if (cp_valid && cp_ready) begin sop_enable <= 1'b0; if (cp_endofpacket) sop_enable <= 1'b1; end end end assign cp_startofpacket = sop_enable; assign cp_endofpacket = (av_read) | (av_burstcount == NUMSYMBOLS); end else begin assign cp_startofpacket = 1'b1; assign cp_endofpacket = 1'b1; end endgenerate // -------------------------------------- // Backpressure & Readdatavalid // -------------------------------------- reg hold_waitrequest; always @ (posedge clk, posedge reset) begin if (reset) hold_waitrequest <= 1'b1; else hold_waitrequest <= 1'b0; end always @* begin rp_ready = 1; av_readdatavalid = 0; av_writeresponsevalid = 0; av_waitrequest = hold_waitrequest | !cp_ready; // -------------------------------------- // Currently, responses are _always_ read responses because // this Avalon agent only issues posted writes, which do // not have responses. -> not true for now // Now Avalon supports response, so based on type of transaction // return, assert correct thing // -------------------------------------- if (rp_data[PKT_TRANS_WRITE] == 1) av_writeresponsevalid = rp_valid; else av_readdatavalid = rp_valid; if (SUPPRESS_0_BYTEEN_RSP) begin if (rp_data[PKT_BYTEEN_H:PKT_BYTEEN_L] == 0) av_readdatavalid = 0; end end endmodule