123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- // (C) 2001-2018 Intel Corporation. All rights reserved.
- // Your use of Intel Corporation's design tools, logic functions and other
- // software and tools, and its AMPP partner logic functions, and any output
- // files from 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 Intel Program License Subscription
- // Agreement, Intel FPGA IP License Agreement, or other applicable
- // license agreement, including, without limitation, that your use is for the
- // sole purpose of programming logic devices manufactured by Intel and sold by
- // Intel or its authorized distributors. Please refer to the applicable
- // agreement for further details.
- // $Id: //acds/rel/18.1std/ip/merlin/altera_merlin_slave_translator/altera_merlin_slave_translator.sv#1 $
- // $Revision: #1 $
- // $Date: 2018/07/18 $
- // $Author: psgswbuild $
- // -------------------------------------
- // Merlin Slave Translator
- //
- // Translates Universal Avalon MM Slave
- // to any Avalon MM Slave
- // -------------------------------------
- //
- //Notable Note: 0 AV_READLATENCY is not allowed and will be converted to a 1 cycle readlatency in all cases but one
- //If you declare a slave with fixed read timing requirements, the readlatency of such a slave will be allowed to be zero
- //The key feature here is that no same cycle turnaround data is processed through the fabric.
- //import avalon_utilities_pkg::*;
- `timescale 1 ns / 1 ns
- module altera_merlin_slave_translator #(
- parameter
- //Widths
- AV_ADDRESS_W = 32,
- AV_DATA_W = 32,
- AV_BURSTCOUNT_W = 4,
- AV_BYTEENABLE_W = 4,
- UAV_BYTEENABLE_W = 4,
- //Read Latency
- AV_READLATENCY = 1,
- //Timing
- AV_READ_WAIT_CYCLES = 0,
- AV_WRITE_WAIT_CYCLES = 0,
- AV_SETUP_WAIT_CYCLES = 0,
- AV_DATA_HOLD_CYCLES = 0,
- //Optional Port Declarations
- USE_READDATAVALID = 1,
- USE_WAITREQUEST = 1,
- USE_READRESPONSE = 0,
- USE_WRITERESPONSE = 0,
- //Variable Addressing
- AV_SYMBOLS_PER_WORD = 4,
- AV_ADDRESS_SYMBOLS = 0,
- AV_BURSTCOUNT_SYMBOLS = 0,
- BITS_PER_WORD = clog2_plusone(AV_SYMBOLS_PER_WORD - 1),
- UAV_ADDRESS_W = 38,
- UAV_BURSTCOUNT_W = 10,
- UAV_DATA_W = 32,
- AV_CONSTANT_BURST_BEHAVIOR = 0,
- UAV_CONSTANT_BURST_BEHAVIOR = 0,
- CHIPSELECT_THROUGH_READLATENCY = 0,
- // Tightly-Coupled Options
- USE_UAV_CLKEN = 0,
- AV_REQUIRE_UNALIGNED_ADDRESSES = 0
- ) (
- // -------------------
- // Clock & Reset
- // -------------------
- input wire clk,
- input wire reset,
- // -------------------
- // Universal Avalon Slave
- // -------------------
- input wire [UAV_ADDRESS_W - 1 : 0] uav_address,
- input wire [UAV_DATA_W - 1 : 0] uav_writedata,
- input wire uav_write,
- input wire uav_read,
- input wire [UAV_BURSTCOUNT_W - 1 : 0] uav_burstcount,
- input wire [UAV_BYTEENABLE_W - 1 : 0] uav_byteenable,
- input wire uav_lock,
- input wire uav_debugaccess,
- input wire uav_clken,
- output logic uav_readdatavalid,
- output logic uav_waitrequest,
- output logic [UAV_DATA_W - 1 : 0] uav_readdata,
- output logic [1:0] uav_response,
- // input wire uav_writeresponserequest,
- output logic uav_writeresponsevalid,
- // -------------------
- // Customizable Avalon Master
- // -------------------
- output logic [AV_ADDRESS_W - 1 : 0] av_address,
- output logic [AV_DATA_W - 1 : 0] av_writedata,
- output logic av_write,
- output logic av_read,
- output logic [AV_BURSTCOUNT_W - 1 : 0] av_burstcount,
- output logic [AV_BYTEENABLE_W - 1 : 0] av_byteenable,
- output logic [AV_BYTEENABLE_W - 1 : 0] av_writebyteenable,
- output logic av_begintransfer,
- output wire av_chipselect,
- output logic av_beginbursttransfer,
- output logic av_lock,
- output wire av_clken,
- output wire av_debugaccess,
- output wire av_outputenable,
- input logic [AV_DATA_W - 1 : 0] av_readdata,
- input logic av_readdatavalid,
- input logic av_waitrequest,
- input logic [1:0] av_response,
- // output logic av_writeresponserequest,
- input wire av_writeresponsevalid
- );
- function integer clog2_plusone;
- input [31:0] Depth;
- integer i;
- begin
- i = Depth;
- for(clog2_plusone = 0; i > 0; clog2_plusone = clog2_plusone + 1)
- i = i >> 1;
- end
- endfunction
- function integer max;
- //returns the larger of two passed arguments
- input [31:0] one;
- input [31:0] two;
- if(one > two)
- max=one;
- else
- max=two;
- endfunction // int
- localparam AV_READ_WAIT_INDEXED = (AV_SETUP_WAIT_CYCLES + AV_READ_WAIT_CYCLES);
- localparam AV_WRITE_WAIT_INDEXED = (AV_SETUP_WAIT_CYCLES + AV_WRITE_WAIT_CYCLES);
- localparam AV_DATA_HOLD_INDEXED = (AV_WRITE_WAIT_INDEXED + AV_DATA_HOLD_CYCLES);
- localparam LOG2_OF_LATENCY_SUM = max(clog2_plusone(AV_READ_WAIT_INDEXED + 1),clog2_plusone(AV_DATA_HOLD_INDEXED + 1));
- localparam BURSTCOUNT_SHIFT_SELECTOR = AV_BURSTCOUNT_SYMBOLS ? 0 : BITS_PER_WORD;
- localparam ADDRESS_SHIFT_SELECTOR = AV_ADDRESS_SYMBOLS ? 0 : BITS_PER_WORD;
- localparam ADDRESS_HIGH = ( UAV_ADDRESS_W > AV_ADDRESS_W + ADDRESS_SHIFT_SELECTOR ) ?
- AV_ADDRESS_W :
- UAV_ADDRESS_W - ADDRESS_SHIFT_SELECTOR;
- localparam BURSTCOUNT_HIGH = ( UAV_BURSTCOUNT_W > AV_BURSTCOUNT_W + BURSTCOUNT_SHIFT_SELECTOR ) ?
- AV_BURSTCOUNT_W :
- UAV_BURSTCOUNT_W - BURSTCOUNT_SHIFT_SELECTOR;
- localparam BYTEENABLE_ADDRESS_BITS = ( clog2_plusone(UAV_BYTEENABLE_W) - 1 ) >= 1 ? clog2_plusone(UAV_BYTEENABLE_W) - 1 : 1;
- // Calculate the symbols per word as the power of 2 extended symbols per word
- wire [31 : 0] symbols_per_word_int = 2**(clog2_plusone(AV_SYMBOLS_PER_WORD[UAV_BURSTCOUNT_W : 0] - 1));
- wire [UAV_BURSTCOUNT_W-1 : 0] symbols_per_word = symbols_per_word_int[UAV_BURSTCOUNT_W-1 : 0];
- // +--------------------------------
- // |Backwards Compatibility Signals
- // +--------------------------------
- assign av_clken = (USE_UAV_CLKEN) ? uav_clken : 1'b1;
- assign av_debugaccess = uav_debugaccess;
- // +-------------------
- // |Passthru Signals
- // +-------------------
- reg [1 : 0] av_response_delayed;
- always @(posedge clk, posedge reset) begin
- if (reset) begin
- av_response_delayed <= 2'b0;
- end else begin
- av_response_delayed <= av_response;
- end
- end
- always_comb
- begin
- if (!USE_READRESPONSE && !USE_WRITERESPONSE) begin
- uav_response = '0;
- end else begin
- if (AV_READLATENCY != 0 || USE_READDATAVALID) begin
- uav_response = av_response;
- end else begin
- uav_response = av_response_delayed;
- end
- end
- end
- // assign av_writeresponserequest = uav_writeresponserequest;
- assign uav_writeresponsevalid = av_writeresponsevalid;
- //-------------------------
- //Writedata and Byteenable
- //-------------------------
- always@* begin
- av_byteenable = '0;
- av_byteenable = uav_byteenable[AV_BYTEENABLE_W - 1 : 0];
- end
- always@* begin
- av_writedata = '0;
- av_writedata = uav_writedata[AV_DATA_W - 1 : 0];
- end
- // +-------------------
- // |Calculated Signals
- // +-------------------
- logic [UAV_ADDRESS_W - 1 : 0 ] real_uav_address;
- function [BYTEENABLE_ADDRESS_BITS - 1 : 0 ] decode_byteenable;
- input [UAV_BYTEENABLE_W - 1 : 0 ] byteenable;
- for(int i = 0 ; i < UAV_BYTEENABLE_W; i++ ) begin
- if(byteenable[i] == 1) begin
- return i;
- end
- end
- return '0;
- endfunction
- reg [AV_BURSTCOUNT_W - 1 : 0] burstcount_reg;
- reg [AV_ADDRESS_W - 1 : 0] address_reg;
- always@(posedge clk, posedge reset) begin
- if(reset) begin
- burstcount_reg <= '0;
- address_reg <= '0;
- end else begin
- burstcount_reg <= burstcount_reg;
- address_reg <= address_reg;
- if(av_beginbursttransfer) begin
- burstcount_reg <= uav_burstcount [ BURSTCOUNT_HIGH - 1 + BURSTCOUNT_SHIFT_SELECTOR : BURSTCOUNT_SHIFT_SELECTOR ];
- address_reg <= real_uav_address [ ADDRESS_HIGH - 1 + ADDRESS_SHIFT_SELECTOR : ADDRESS_SHIFT_SELECTOR ];
- end
- end
- end
- logic [BYTEENABLE_ADDRESS_BITS-1:0] temp_wire;
- always@* begin
- if( AV_REQUIRE_UNALIGNED_ADDRESSES == 1) begin
- temp_wire = decode_byteenable(uav_byteenable);
- real_uav_address = { uav_address[UAV_ADDRESS_W - 1 : BYTEENABLE_ADDRESS_BITS ], temp_wire[BYTEENABLE_ADDRESS_BITS - 1 : 0 ] };
- end else begin
- real_uav_address = uav_address;
- end
- av_address = real_uav_address[ADDRESS_HIGH - 1 + ADDRESS_SHIFT_SELECTOR : ADDRESS_SHIFT_SELECTOR ];
- if( AV_CONSTANT_BURST_BEHAVIOR && !UAV_CONSTANT_BURST_BEHAVIOR && ~av_beginbursttransfer )
- av_address = address_reg;
- end
- always@* begin
- av_burstcount=uav_burstcount[BURSTCOUNT_HIGH - 1 + BURSTCOUNT_SHIFT_SELECTOR : BURSTCOUNT_SHIFT_SELECTOR ];
- if( AV_CONSTANT_BURST_BEHAVIOR && !UAV_CONSTANT_BURST_BEHAVIOR && ~av_beginbursttransfer )
- av_burstcount = burstcount_reg;
- end
- always@* begin
- av_lock = uav_lock;
- end
- // -------------------
- // Writebyteenable Assignment
- // -------------------
- always@* begin
- av_writebyteenable = { (AV_BYTEENABLE_W){uav_write} } & uav_byteenable[AV_BYTEENABLE_W - 1 : 0];
- end
- // -------------------
- // Waitrequest Assignment
- // -------------------
- reg av_waitrequest_generated;
- reg av_waitrequest_generated_read;
- reg av_waitrequest_generated_write;
- reg waitrequest_reset_override;
- reg [ ( LOG2_OF_LATENCY_SUM ? LOG2_OF_LATENCY_SUM - 1 : 0 ) : 0 ] wait_latency_counter;
- always@(posedge reset, posedge clk) begin
- if(reset) begin
- wait_latency_counter <= '0;
- waitrequest_reset_override <= 1'h1;
- end else begin
- waitrequest_reset_override <= 1'h0;
- wait_latency_counter <= '0;
- if( ~uav_waitrequest | waitrequest_reset_override )
- wait_latency_counter <= '0;
- else if( uav_read | uav_write )
- wait_latency_counter <= wait_latency_counter + 1'h1;
- end
- end
- always @* begin
- av_read = uav_read;
- av_write = uav_write;
- av_waitrequest_generated = 1'h1;
- av_waitrequest_generated_read = 1'h1;
- av_waitrequest_generated_write = 1'h1;
- if(LOG2_OF_LATENCY_SUM == 1)
- av_waitrequest_generated = 0;
- if(LOG2_OF_LATENCY_SUM > 1 && !USE_WAITREQUEST) begin
- av_read = wait_latency_counter >= AV_SETUP_WAIT_CYCLES && uav_read;
- av_write = wait_latency_counter >= AV_SETUP_WAIT_CYCLES && uav_write && wait_latency_counter <= AV_WRITE_WAIT_INDEXED;
- av_waitrequest_generated_read = wait_latency_counter != AV_READ_WAIT_INDEXED;
- av_waitrequest_generated_write = wait_latency_counter != AV_DATA_HOLD_INDEXED;
- if(uav_write)
- av_waitrequest_generated = av_waitrequest_generated_write;
- else
- av_waitrequest_generated = av_waitrequest_generated_read;
- end
- if(USE_WAITREQUEST) begin
- uav_waitrequest = av_waitrequest;
- end else begin
- uav_waitrequest = av_waitrequest_generated | waitrequest_reset_override;
- end
- end
- // --------------
- // Readdata Assignment
- // --------------
- reg[(AV_DATA_W ? AV_DATA_W -1 : 0 ): 0] av_readdata_pre;
- always@(posedge clk, posedge reset) begin
- if(reset)
- av_readdata_pre <= 'b0;
- else
- av_readdata_pre <= av_readdata;
- end
- always@* begin
- uav_readdata = {UAV_DATA_W{1'b0}};
- if( AV_READLATENCY != 0 || USE_READDATAVALID ) begin
- uav_readdata[AV_DATA_W-1:0] = av_readdata;
- end else begin
- uav_readdata[AV_DATA_W-1:0] = av_readdata_pre;
- end
- end
-
- // -------------------
- // Readdatavalid Assigment
- // -------------------
- reg[(AV_READLATENCY>0 ? AV_READLATENCY-1:0) :0] read_latency_shift_reg;
- reg top_read_latency_shift_reg;
- always@* begin
- uav_readdatavalid=top_read_latency_shift_reg;
- if(USE_READDATAVALID) begin
- uav_readdatavalid = av_readdatavalid;
- end
- end
- always@* begin
- top_read_latency_shift_reg = uav_read & ~uav_waitrequest & ~waitrequest_reset_override;
- if(AV_READLATENCY == 1 || AV_READLATENCY == 0 ) begin
- top_read_latency_shift_reg=read_latency_shift_reg;
- end
- if (AV_READLATENCY > 1) begin
- top_read_latency_shift_reg = read_latency_shift_reg[(AV_READLATENCY ? AV_READLATENCY-1 : 0)];
- end
- end
- always@(posedge reset, posedge clk) begin
- if (reset) begin
- read_latency_shift_reg <= '0;
- end else if (av_clken) begin
- read_latency_shift_reg[0] <= uav_read && ~uav_waitrequest & ~waitrequest_reset_override;
- for (int i=0; i+1 < AV_READLATENCY ; i+=1 ) begin
- read_latency_shift_reg[i+1] <= read_latency_shift_reg[i];
- end
- end
- end
- // ------------
- // Chipselect and OutputEnable
- // ------------
- reg av_chipselect_pre;
- wire cs_extension;
- reg av_outputenable_pre;
-
- assign av_chipselect = (uav_read | uav_write) ? 1'b1 : av_chipselect_pre;
- assign cs_extension = ( (^ read_latency_shift_reg) & ~top_read_latency_shift_reg ) | ((| read_latency_shift_reg) & ~(^ read_latency_shift_reg));
- assign av_outputenable = uav_read ? 1'b1 : av_outputenable_pre;
- always@(posedge reset, posedge clk) begin
- if(reset)
- av_outputenable_pre <= 1'b0;
- else if( AV_READLATENCY == 0 && AV_READ_WAIT_INDEXED != 0 )
- av_outputenable_pre <= 0;
- else
- av_outputenable_pre <= cs_extension | uav_read;
- end
- always@(posedge reset, posedge clk) begin
- if(reset) begin
- av_chipselect_pre <= 1'b0;
- end else begin
- av_chipselect_pre <= 1'b0;
- if(AV_READLATENCY != 0 && CHIPSELECT_THROUGH_READLATENCY == 1) begin
- //The AV_READLATENCY term is only here to prevent chipselect from remaining asserted while read and write fall.
- //There is no functional impact as 0 cycle transactions are treated as 1 cycle on the other side of the translator.
- if(uav_read) begin
- av_chipselect_pre <= 1'b1;
- end else if(cs_extension == 1) begin
- av_chipselect_pre <= 1'b1;
- end
- end
- end
- end
- // -------------------
- // Begintransfer Assigment
- // -------------------
- reg end_begintransfer;
- always@* begin
- av_begintransfer = ( uav_write | uav_read ) & ~end_begintransfer;
- end
- always@ ( posedge clk or posedge reset ) begin
- if(reset) begin
- end_begintransfer <= 1'b0;
- end else begin
- if(av_begintransfer == 1 && uav_waitrequest && ~waitrequest_reset_override)
- end_begintransfer <= 1'b1;
- else if(uav_waitrequest)
- end_begintransfer <= end_begintransfer;
- else
- end_begintransfer <= 1'b0;
- end
- end
- // -------------------
- // Beginbursttransfer Assigment
- // -------------------
- reg end_beginbursttransfer;
- reg in_transfer;
- always@* begin
- av_beginbursttransfer = uav_read ? av_begintransfer : (av_begintransfer && ~end_beginbursttransfer && ~in_transfer);
- end
- always@ ( posedge clk or posedge reset ) begin
- if(reset) begin
- end_beginbursttransfer <= 1'b0;
- in_transfer <= 1'b0;
- end else begin
- end_beginbursttransfer <= uav_write & ( uav_burstcount != symbols_per_word );
- if(uav_write && uav_burstcount == symbols_per_word)
- in_transfer <=1'b0;
- else if(uav_write)
- in_transfer <=1'b1;
- end
- end
- endmodule
|