URL
https://opencores.org/ocsvn/openmsp430/openmsp430/trunk
Subversion Repositories openmsp430
[/] [openmsp430/] [trunk/] [fpga/] [altera_de0_nano_soc/] [doc/] [Terasic/] [DE0_NANO_SOC/] [Demonstrations/] [FPGA/] [DE0_NANO_SOC_ADC/] [DE0_NANO_SOC_QSYS/] [synthesis/] [submodules/] [altera_merlin_master_translator.sv] - Rev 221
Compare with Previous | Blame | View Log
// (C) 2001-2014 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/14.0/ip/merlin/altera_merlin_master_translator/altera_merlin_master_translator.sv#1 $
// $Revision: #1 $
// $Date: 2014/02/16 $
// $Author: swbranch $
// --------------------------------------
// Merlin Master Translator
//
// Converts Avalon-MM Master Interfaces into
// Avalon-MM Universal Master Interfaces
// --------------------------------------
`timescale 1 ns / 1 ns
module altera_merlin_master_translator #(
parameter
AV_ADDRESS_W = 32,
AV_DATA_W = 32,
AV_BURSTCOUNT_W = 4,
AV_BYTEENABLE_W = 4,
//Optional Port Declarations
USE_BURSTCOUNT = 1,
USE_BEGINBURSTTRANSFER = 0,
USE_BEGINTRANSFER = 0,
USE_CHIPSELECT = 0,
USE_READ = 1,
USE_READDATAVALID = 1,
USE_WRITE = 1,
USE_WAITREQUEST = 1,
USE_WRITERESPONSE = 0,
USE_READRESPONSE = 0,
AV_REGISTERINCOMINGSIGNALS = 0,
AV_SYMBOLS_PER_WORD = 4,
AV_ADDRESS_SYMBOLS = 0,
AV_CONSTANT_BURST_BEHAVIOR = 1,
AV_BURSTCOUNT_SYMBOLS = 0,
AV_LINEWRAPBURSTS = 0,
UAV_ADDRESS_W = 38,
UAV_BURSTCOUNT_W = 10,
UAV_CONSTANT_BURST_BEHAVIOR = 0
)(
//Universal Avalon Master
input wire clk,
input wire reset,
output reg uav_write,
output reg uav_read,
output reg [UAV_ADDRESS_W -1 : 0] uav_address,
output reg [UAV_BURSTCOUNT_W -1 : 0] uav_burstcount,
output wire [AV_BYTEENABLE_W -1 : 0] uav_byteenable,
output wire [AV_DATA_W -1 : 0] uav_writedata,
output wire uav_lock,
output wire uav_debugaccess,
output wire uav_clken,
input wire [ AV_DATA_W -1 : 0] uav_readdata,
input wire uav_readdatavalid,
input wire uav_waitrequest,
input wire [1:0] uav_response,
output reg uav_writeresponserequest,
input wire uav_writeresponsevalid,
//Avalon-MM !Master
input reg av_write,
input reg av_read,
input wire [AV_ADDRESS_W -1 : 0] av_address,
input wire [AV_BYTEENABLE_W -1 : 0] av_byteenable,
input wire [AV_BURSTCOUNT_W -1 : 0] av_burstcount,
input wire [AV_DATA_W -1 : 0] av_writedata,
input wire av_begintransfer,
input wire av_beginbursttransfer,
input wire av_lock,
input wire av_chipselect,
input wire av_debugaccess,
input wire av_clken,
output wire [AV_DATA_W -1 : 0] av_readdata,
output wire av_readdatavalid,
output reg av_waitrequest,
output reg [1:0] av_response,
input wire av_writeresponserequest,
output reg av_writeresponsevalid
);
localparam BITS_PER_WORD = clog2(AV_SYMBOLS_PER_WORD - 1);
localparam AV_MAX_SYMBOL_BURST = flog2( pow2(AV_BURSTCOUNT_W - 1) * (AV_BURSTCOUNT_SYMBOLS ? 1 : (AV_SYMBOLS_PER_WORD)) );
localparam AV_MAX_SYMBOL_BURST_MINUS_ONE = AV_MAX_SYMBOL_BURST ? AV_MAX_SYMBOL_BURST - 1 : 0 ;
localparam UAV_BURSTCOUNT_W_OR_32 = UAV_BURSTCOUNT_W > 32 ? 31 : UAV_BURSTCOUNT_W -1;
localparam UAV_ADDRESS_W_OR_32 = UAV_ADDRESS_W > 32 ? 31 : UAV_ADDRESS_W -1;
// -1 for burstcount restriction 2^(n-1)
localparam BITS_PER_WORD_BURSTCOUNT = UAV_BURSTCOUNT_W == 1 ? 0 : BITS_PER_WORD;
localparam BITS_PER_WORD_ADDRESS = UAV_ADDRESS_W == 1 ? 0 : BITS_PER_WORD;
localparam ADDRESS_LOW = AV_ADDRESS_SYMBOLS ? 0 : BITS_PER_WORD_ADDRESS;
localparam BURSTCOUNT_LOW = AV_BURSTCOUNT_SYMBOLS ? 0 : BITS_PER_WORD_BURSTCOUNT;
localparam ADDRESS_HIGH = UAV_ADDRESS_W > AV_ADDRESS_W + ADDRESS_LOW ? AV_ADDRESS_W : UAV_ADDRESS_W - ADDRESS_LOW;
localparam BURSTCOUNT_HIGH = UAV_BURSTCOUNT_W > AV_BURSTCOUNT_W + BURSTCOUNT_LOW ? AV_BURSTCOUNT_W : UAV_BURSTCOUNT_W - BURSTCOUNT_LOW;
function integer flog2;
input [31:0] Depth;
integer i;
begin
i = Depth;
if ( i <= 0 ) flog2 = 0;
else begin
for(flog2 = -1; i > 0; flog2 = flog2 + 1)
i = i >> 1;
end
end
endfunction // flog2
function integer clog2;
input [31:0] Depth;
integer i;
begin
i = Depth;
for(clog2 = 0; i > 0; clog2 = clog2 + 1)
i = i >> 1;
end
endfunction
function integer pow2;
input [31:0] toShift;
begin
pow2=1;
pow2= pow2 << toShift;
end
endfunction // pow2
// -------------------------------------------------
// Assign some constants to appropriately-sized signals to
// avoid synthesis warnings. This also helps some simulators
// with their inferred sensitivity lists.
// -------------------------------------------------
// Calculate the symbols per word as the power of 2 extended symbols per word
wire [31:0] symbols_per_word_int = 2**(clog2(AV_SYMBOLS_PER_WORD[UAV_BURSTCOUNT_W_OR_32 : 0] - 1));
wire [UAV_BURSTCOUNT_W_OR_32 : 0] symbols_per_word = symbols_per_word_int[UAV_BURSTCOUNT_W_OR_32 : 0];
reg internal_beginbursttransfer;
reg internal_begintransfer;
reg [UAV_ADDRESS_W - 1: 0 ] uav_address_pre;
reg [UAV_BURSTCOUNT_W - 1 : 0 ] uav_burstcount_pre;
reg uav_read_pre;
reg uav_write_pre;
reg read_accepted;
//Passthru assignmenst
assign uav_writedata = av_writedata;
assign av_readdata = uav_readdata;
assign uav_byteenable = av_byteenable;
assign uav_lock = av_lock;
assign av_readdatavalid = uav_readdatavalid;
assign uav_debugaccess = av_debugaccess;
assign uav_clken = av_clken;
//Response signals
always_comb
begin
if (!USE_READRESPONSE && !USE_WRITERESPONSE)
av_response = '0;
else
av_response = uav_response;
if (USE_WRITERESPONSE) begin
uav_writeresponserequest = av_writeresponserequest;
av_writeresponsevalid = uav_writeresponsevalid;
end else begin
uav_writeresponserequest = '0;
av_writeresponsevalid = '0;
end
end
//address + burstcount assignment
reg [UAV_ADDRESS_W - 1 : 0] address_register;
wire [UAV_BURSTCOUNT_W - 1 : 0] burstcount_register;
reg [UAV_BURSTCOUNT_W : 0] burstcount_register_lint;
assign burstcount_register = burstcount_register_lint [UAV_BURSTCOUNT_W - 1 : 0];
always @* begin
uav_address=uav_address_pre;
uav_burstcount=uav_burstcount_pre;
if(AV_CONSTANT_BURST_BEHAVIOR && !UAV_CONSTANT_BURST_BEHAVIOR && ~internal_beginbursttransfer) begin
uav_address=address_register;
uav_burstcount=burstcount_register;
end
end
reg first_burst_stalled;
reg burst_stalled;
wire[UAV_ADDRESS_W-1:0] combi_burst_addr_reg;
wire [UAV_ADDRESS_W-1:0] combi_addr_reg;
generate
if(AV_LINEWRAPBURSTS && AV_MAX_SYMBOL_BURST!=0) begin
if(AV_MAX_SYMBOL_BURST > UAV_ADDRESS_W - 1) begin
assign combi_burst_addr_reg = { uav_address_pre[UAV_ADDRESS_W-1:0] + AV_SYMBOLS_PER_WORD[UAV_ADDRESS_W-1:0] };
assign combi_addr_reg = { address_register[UAV_ADDRESS_W-1:0] + AV_SYMBOLS_PER_WORD[UAV_ADDRESS_W-1:0] };
end
else begin
assign combi_burst_addr_reg = { uav_address_pre[UAV_ADDRESS_W - 1 : AV_MAX_SYMBOL_BURST], uav_address_pre[AV_MAX_SYMBOL_BURST_MINUS_ONE:0] + AV_SYMBOLS_PER_WORD[AV_MAX_SYMBOL_BURST_MINUS_ONE:0] };
assign combi_addr_reg = { address_register[UAV_ADDRESS_W - 1 : AV_MAX_SYMBOL_BURST], address_register[AV_MAX_SYMBOL_BURST_MINUS_ONE:0] + AV_SYMBOLS_PER_WORD[AV_MAX_SYMBOL_BURST_MINUS_ONE:0] };
end
end
else begin
assign combi_burst_addr_reg =
uav_address_pre + AV_SYMBOLS_PER_WORD[UAV_ADDRESS_W_OR_32:0];
assign combi_addr_reg =
address_register + AV_SYMBOLS_PER_WORD[UAV_ADDRESS_W_OR_32:0];
end
endgenerate
always@(posedge clk, posedge reset) begin
if(reset) begin
address_register <= '0;
burstcount_register_lint <= '0;
first_burst_stalled <= 1'b0;
burst_stalled <= 1'b0;
end
else begin
address_register <= address_register;
burstcount_register_lint <= burstcount_register_lint;
if(internal_beginbursttransfer||first_burst_stalled) begin
if(av_waitrequest) begin
first_burst_stalled <= 1'b1;
address_register <= uav_address_pre;
burstcount_register_lint [UAV_BURSTCOUNT_W - 1 : 0] <= uav_burstcount_pre;
end else begin
first_burst_stalled <= 1'b0;
address_register <= combi_burst_addr_reg;
burstcount_register_lint <= uav_burstcount_pre - symbols_per_word;
end
end
else if(internal_begintransfer || burst_stalled) begin
if(~av_waitrequest) begin
burst_stalled <= 1'b0;
address_register <= combi_addr_reg;
burstcount_register_lint <= burstcount_register - symbols_per_word;
end else
burst_stalled<=1'b1;
end
end
end
//Address
always @* begin
uav_address_pre = {UAV_ADDRESS_W{1'b0}};
if(AV_ADDRESS_SYMBOLS)
uav_address_pre[ ( ADDRESS_HIGH ? ADDRESS_HIGH - 1 : 0 ) : 0 ] =av_address[ ( ADDRESS_HIGH ? ADDRESS_HIGH - 1 : 0 ) : 0 ];
else begin
uav_address_pre[ ADDRESS_LOW + ADDRESS_HIGH - 1 : ADDRESS_LOW ] = av_address[( ADDRESS_HIGH ? ADDRESS_HIGH - 1 : 0) : 0 ];
end
end
//Burstcount
always@* begin
uav_burstcount_pre = symbols_per_word; // default to a single transfer
if(USE_BURSTCOUNT) begin
uav_burstcount_pre = {UAV_BURSTCOUNT_W{1'b0}};
if(AV_BURSTCOUNT_SYMBOLS)
uav_burstcount_pre[( BURSTCOUNT_HIGH ? BURSTCOUNT_HIGH - 1 : 0 ) :0 ] = av_burstcount[( BURSTCOUNT_HIGH ? BURSTCOUNT_HIGH - 1 : 0 ) :0 ];
else begin
uav_burstcount_pre[ UAV_BURSTCOUNT_W - 1 : BURSTCOUNT_LOW] = av_burstcount[( BURSTCOUNT_HIGH ? BURSTCOUNT_HIGH - 1 : 0 ) : 0 ];
end
end
end
//waitrequest translation
always@(posedge clk, posedge reset) begin
if(reset)
read_accepted <= 1'b0;
else begin
read_accepted <= read_accepted;
if(read_accepted == 0)
read_accepted<=av_waitrequest ? uav_read_pre & ~uav_waitrequest : 1'b0;
else if(read_accepted == 1 && uav_readdatavalid == 1) // reset acceptance only when rdv arrives
read_accepted <= 1'b0;
end
end
reg write_accepted = 0;
generate if (AV_REGISTERINCOMINGSIGNALS) begin
always@(posedge clk, posedge reset) begin
if(reset)
write_accepted <= 1'b0;
else begin
write_accepted <=
~av_waitrequest ? 1'b0 :
uav_write & ~uav_waitrequest? 1'b1 :
write_accepted;
end
end
end endgenerate
always@* begin
av_waitrequest = uav_waitrequest;
if(USE_READDATAVALID == 0 ) begin
av_waitrequest = uav_read_pre ? ~uav_readdatavalid : uav_waitrequest;
end
if (AV_REGISTERINCOMINGSIGNALS) begin
av_waitrequest =
uav_read_pre ? ~uav_readdatavalid :
uav_write_pre ? (internal_begintransfer | uav_waitrequest) & ~write_accepted :
1'b1;
end
if(USE_WAITREQUEST == 0) begin
av_waitrequest = 0;
end
end
//read/write generation
always@* begin
uav_write = 1'b0;
uav_write_pre = 1'b0;
uav_read = 1'b0;
uav_read_pre = 1'b0;
if(!USE_CHIPSELECT) begin
if (USE_READ) begin
uav_read_pre=av_read;
end
if (USE_WRITE) begin
uav_write_pre=av_write;
end
end
else begin
if(!USE_WRITE && USE_READ) begin
uav_read_pre=av_read;
uav_write_pre=av_chipselect & ~av_read;
end
else if(!USE_READ && USE_WRITE) begin
uav_write_pre=av_write;
uav_read_pre = av_chipselect & ~av_write;
end
else if (USE_READ && USE_WRITE) begin
uav_write_pre=av_write;
uav_read_pre=av_read;
end
end
if(USE_READDATAVALID == 0)
uav_read = uav_read_pre & ~read_accepted;
else
uav_read = uav_read_pre;
if(AV_REGISTERINCOMINGSIGNALS == 0)
uav_write=uav_write_pre;
else
uav_write=uav_write_pre & ~write_accepted;
end
// -------------------
// Begintransfer Assigment
// -------------------
reg end_begintransfer;
always@* begin
if(USE_BEGINTRANSFER) begin
internal_begintransfer = av_begintransfer;
end else begin
internal_begintransfer = ( uav_write | uav_read ) & ~end_begintransfer;
end
end
always@ ( posedge clk or posedge reset ) begin
if(reset) begin
end_begintransfer <= 1'b0;
end
else begin
if(internal_begintransfer == 1 && uav_waitrequest)
end_begintransfer <= 1'b1;
else if(uav_waitrequest)
end_begintransfer <= end_begintransfer;
else
end_begintransfer <= 1'b0;
end
end
// -------------------
// Beginbursttransfer Assigment
// -------------------
reg end_beginbursttransfer;
wire last_burst_transfer_pre;
wire last_burst_transfer_reg;
wire last_burst_transfer;
// compare values before the mux to shorten critical path; benchmark before changing
assign last_burst_transfer_pre = (uav_burstcount_pre == symbols_per_word);
assign last_burst_transfer_reg = (burstcount_register == symbols_per_word);
assign last_burst_transfer = (internal_beginbursttransfer) ? last_burst_transfer_pre : last_burst_transfer_reg;
always@* begin
if(USE_BEGINBURSTTRANSFER) begin
internal_beginbursttransfer = av_beginbursttransfer;
end else begin
internal_beginbursttransfer = uav_read ? internal_begintransfer : internal_begintransfer && ~end_beginbursttransfer;
end
end
always@ ( posedge clk or posedge reset ) begin
if(reset) begin
end_beginbursttransfer <= 1'b0;
end
else begin
end_beginbursttransfer <= end_beginbursttransfer;
if( last_burst_transfer && internal_begintransfer || uav_read ) begin
end_beginbursttransfer <= 1'b0;
end
else if(uav_write && internal_begintransfer) begin
end_beginbursttransfer <= 1'b1;
end
end
end
// synthesis translate_off
// ------------------------------------------------
// check_1 : for waitrequest signal violation
// Ensure that when waitreqeust is asserted, the master is not allowed to change its controls
// Exception : begintransfer / beginbursttransfer
// : previously not in any transaction (idle)
// Note : Not checking clken which is not exactly part of Avalon controls/inputs
// : Not using system verilog assertions (seq/prop) since it is not supported if using Modelsim_SE
// ------------------------------------------------
reg av_waitrequest_r;
reg av_write_r,av_writeresponserequest_r,av_read_r,av_lock_r,av_chipselect_r,av_debugaccess_r;
reg [AV_ADDRESS_W-1:0] av_address_r;
reg [AV_BYTEENABLE_W-1:0] av_byteenable_r;
reg [AV_BURSTCOUNT_W-1:0] av_burstcount_r;
reg [AV_DATA_W-1:0] av_writedata_r;
always @(posedge clk or posedge reset) begin
if (reset) begin
av_waitrequest_r <= '0;
av_write_r <= '0;
av_writeresponserequest_r <= '0;
av_read_r <= '0;
av_lock_r <= '0;
av_chipselect_r <= '0;
av_debugaccess_r <= '0;
av_address_r <= '0;
av_byteenable_r <= '0;
av_burstcount_r <= '0;
av_writedata_r <= '0;
end
else begin
av_waitrequest_r <= av_waitrequest;
av_write_r <= av_write;
av_writeresponserequest_r <= av_writeresponserequest;
av_read_r <= av_read;
av_lock_r <= av_lock;
av_chipselect_r <= av_chipselect;
av_debugaccess_r <= av_debugaccess;
av_address_r <= av_address;
av_byteenable_r <= av_byteenable;
av_burstcount_r <= av_burstcount;
av_writedata_r <= av_writedata;
if ( av_waitrequest_r && // When waitrequest is asserted
( (av_write != av_write_r) || // Checks that : Input controls/data does not change
(av_writeresponserequest != av_writeresponserequest_r) ||
(av_read != av_read_r) ||
(av_lock != av_lock_r) ||
(av_debugaccess != av_debugaccess_r) ||
(av_address != av_address_r) ||
(av_byteenable != av_byteenable_r) ||
(av_burstcount != av_burstcount_r)
) &&
(av_write_r | av_read_r) && // Check only when : previously initiated a write/read
(!USE_CHIPSELECT | av_chipselect_r) // and chipselect was asserted (or unused)
)
$display("%t: %m: Error: Input controls/data changed while av_waitrequest is asserted.\nav_address %x --> %x\nav_byteenable %x --> %x\nav_burstcount %x --> %x\nav_writedata %x --> %x\nav_writeresponserequest %x --> %x\nav_write %x --> %x\nav_read %x --> %x\nav_lock %x --> %x\nav_chipselect %x --> %x\nav_debugaccess %x --> %x ", $time(),
av_address_r , av_address,
av_byteenable_r , av_byteenable,
av_burstcount_r , av_burstcount,
av_writedata_r , av_writedata,
av_writeresponserequest_r, av_writeresponserequest,
av_write_r , av_write,
av_read_r , av_read,
av_lock_r , av_lock,
av_chipselect_r, av_chipselect,
av_debugaccess_r, av_debugaccess);
end
// end check_1
end
// synthesis translate_on
endmodule