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

304 lines
11 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_master_agent/altera_merlin_master_agent.sv#1 $
// $Revision: #1 $
// $Date: 2015/08/09 $
// $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,
PKT_ORI_BURST_SIZE_L = 112,
PKT_ORI_BURST_SIZE_H = 114,
ST_DATA_W = 115,
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,
PKT_BURST_SIZE_W = PKT_BURST_SIZE_H - PKT_BURST_SIZE_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,
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 [PKT_BURST_SIZE_W-1 : 0] burstsize_sig = BURST_SIZE[PKT_BURST_SIZE_W-1 : 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_comb begin
cp_data = '0;
cp_data[PKT_PROTECTION_L] = av_debugaccess;
cp_data[PKT_PROTECTION_L+1] = SECURE_ACCESS_BIT[0]; // secure cache bit
cp_data[PKT_PROTECTION_L+2] = 1'b0; // instruction/data cache bit
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;
cp_data[PKT_TRANS_POSTED] = av_write & !USE_WRITERESPONSE;
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_ORI_BURST_SIZE_H : PKT_ORI_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_comb 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_comb begin
rp_ready = 1;
av_readdatavalid = 0;
av_writeresponsevalid = 0;
av_waitrequest = hold_waitrequest | !cp_ready;
if (USE_WRITERESPONSE && (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