mor1kx-bemicrocv/ip/altera/ddr3/altera_avalon_mm_bridge.v

301 lines
11 KiB
Verilog

// (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_avalon_mm_bridge/altera_avalon_mm_bridge.v#1 $
// $Revision: #1 $
// $Date: 2015/08/09 $
// $Author: swbranch $
// --------------------------------------
// Avalon-MM pipeline bridge
//
// Optionally registers Avalon-MM command and response signals
// --------------------------------------
`timescale 1 ns / 1 ns
module altera_avalon_mm_bridge
#(
parameter DATA_WIDTH = 32,
parameter SYMBOL_WIDTH = 8,
parameter RESPONSE_WIDTH = 2,
parameter HDL_ADDR_WIDTH = 10,
parameter BURSTCOUNT_WIDTH = 1,
parameter PIPELINE_COMMAND = 1,
parameter PIPELINE_RESPONSE = 1,
// --------------------------------------
// Derived parameters
// --------------------------------------
parameter BYTEEN_WIDTH = DATA_WIDTH / SYMBOL_WIDTH
)
(
input clk,
input reset,
output s0_waitrequest,
output [DATA_WIDTH-1:0] s0_readdata,
output s0_readdatavalid,
output [RESPONSE_WIDTH-1:0] s0_response,
input [BURSTCOUNT_WIDTH-1:0] s0_burstcount,
input [DATA_WIDTH-1:0] s0_writedata,
input [HDL_ADDR_WIDTH-1:0] s0_address,
input s0_write,
input s0_read,
input [BYTEEN_WIDTH-1:0] s0_byteenable,
input s0_debugaccess,
input m0_waitrequest,
input [DATA_WIDTH-1:0] m0_readdata,
input m0_readdatavalid,
input [RESPONSE_WIDTH-1:0] m0_response,
output [BURSTCOUNT_WIDTH-1:0] m0_burstcount,
output [DATA_WIDTH-1:0] m0_writedata,
output [HDL_ADDR_WIDTH-1:0] m0_address,
output m0_write,
output m0_read,
output [BYTEEN_WIDTH-1:0] m0_byteenable,
output m0_debugaccess
);
// --------------------------------------
// Registers & signals
// --------------------------------------
reg [BURSTCOUNT_WIDTH-1:0] cmd_burstcount;
reg [DATA_WIDTH-1:0] cmd_writedata;
reg [HDL_ADDR_WIDTH-1:0] cmd_address;
reg cmd_write;
reg cmd_read;
reg [BYTEEN_WIDTH-1:0] cmd_byteenable;
wire cmd_waitrequest;
reg cmd_debugaccess;
reg [BURSTCOUNT_WIDTH-1:0] wr_burstcount;
reg [DATA_WIDTH-1:0] wr_writedata;
reg [HDL_ADDR_WIDTH-1:0] wr_address;
reg wr_write;
reg wr_read;
reg [BYTEEN_WIDTH-1:0] wr_byteenable;
reg wr_debugaccess;
reg [BURSTCOUNT_WIDTH-1:0] wr_reg_burstcount;
reg [DATA_WIDTH-1:0] wr_reg_writedata;
reg [HDL_ADDR_WIDTH-1:0] wr_reg_address;
reg wr_reg_write;
reg wr_reg_read;
reg [BYTEEN_WIDTH-1:0] wr_reg_byteenable;
reg wr_reg_waitrequest;
reg wr_reg_debugaccess;
reg use_reg;
wire wait_rise;
reg [DATA_WIDTH-1:0] rsp_readdata;
reg rsp_readdatavalid;
reg [RESPONSE_WIDTH-1:0] rsp_response;
// --------------------------------------
// Command pipeline
//
// Registers all command signals, including waitrequest
// --------------------------------------
generate if (PIPELINE_COMMAND == 1) begin
// --------------------------------------
// Waitrequest Pipeline Stage
//
// Output waitrequest is delayed by one cycle, which means
// that a master will see waitrequest assertions one cycle
// too late.
//
// Solution: buffer the command when waitrequest transitions
// from low->high. As an optimization, we can safely assume
// waitrequest is low by default because downstream logic
// in the bridge ensures this.
//
// Note: this implementation buffers idle cycles should
// waitrequest transition on such cycles. This is a potential
// cause for throughput loss, but ye olde pipeline bridge did
// the same for years and no one complained. Not buffering idle
// cycles costs logic on the waitrequest path.
// --------------------------------------
assign s0_waitrequest = wr_reg_waitrequest;
assign wait_rise = ~wr_reg_waitrequest & cmd_waitrequest;
always @(posedge clk, posedge reset) begin
if (reset) begin
wr_reg_waitrequest <= 1'b1;
// --------------------------------------
// Bit of trickiness here, deserving of a long comment.
//
// On the first cycle after reset, the pass-through
// must not be used or downstream logic may sample
// the same command twice because of the delay in
// transmitting a falling waitrequest.
//
// Using the registered command works on the condition
// that downstream logic deasserts waitrequest
// immediately after reset, which is true of the
// next stage in this bridge.
// --------------------------------------
use_reg <= 1'b1;
wr_reg_burstcount <= 1'b1;
wr_reg_writedata <= 0;
wr_reg_byteenable <= {BYTEEN_WIDTH{1'b1}};
wr_reg_address <= 0;
wr_reg_write <= 1'b0;
wr_reg_read <= 1'b0;
wr_reg_debugaccess <= 1'b0;
end else begin
wr_reg_waitrequest <= cmd_waitrequest;
if (wait_rise) begin
wr_reg_writedata <= s0_writedata;
wr_reg_byteenable <= s0_byteenable;
wr_reg_address <= s0_address;
wr_reg_write <= s0_write;
wr_reg_read <= s0_read;
wr_reg_burstcount <= s0_burstcount;
wr_reg_debugaccess <= s0_debugaccess;
end
// stop using the buffer when waitrequest is low
if (~cmd_waitrequest)
use_reg <= 1'b0;
else if (wait_rise) begin
use_reg <= 1'b1;
end
end
end
always @* begin
wr_burstcount = s0_burstcount;
wr_writedata = s0_writedata;
wr_address = s0_address;
wr_write = s0_write;
wr_read = s0_read;
wr_byteenable = s0_byteenable;
wr_debugaccess = s0_debugaccess;
if (use_reg) begin
wr_burstcount = wr_reg_burstcount;
wr_writedata = wr_reg_writedata;
wr_address = wr_reg_address;
wr_write = wr_reg_write;
wr_read = wr_reg_read;
wr_byteenable = wr_reg_byteenable;
wr_debugaccess = wr_reg_debugaccess;
end
end
// --------------------------------------
// Master-Slave Signal Pipeline Stage
//
// One notable detail is that cmd_waitrequest is deasserted
// when this stage is idle. This allows us to make logic
// optimizations in the waitrequest pipeline stage.
//
// Also note that cmd_waitrequest is deasserted during reset,
// which is not spec-compliant, but is ok for an internal
// signal.
// --------------------------------------
wire no_command;
assign no_command = ~(cmd_read || cmd_write);
assign cmd_waitrequest = m0_waitrequest & ~no_command;
always @(posedge clk, posedge reset) begin
if (reset) begin
cmd_burstcount <= 1'b1;
cmd_writedata <= 0;
cmd_byteenable <= {BYTEEN_WIDTH{1'b1}};
cmd_address <= 0;
cmd_write <= 1'b0;
cmd_read <= 1'b0;
cmd_debugaccess <= 1'b0;
end
else begin
if (~cmd_waitrequest) begin
cmd_writedata <= wr_writedata;
cmd_byteenable <= wr_byteenable;
cmd_address <= wr_address;
cmd_write <= wr_write;
cmd_read <= wr_read;
cmd_burstcount <= wr_burstcount;
cmd_debugaccess <= wr_debugaccess;
end
end
end
end // conditional command pipeline
else begin
assign s0_waitrequest = m0_waitrequest;
always @* begin
cmd_burstcount = s0_burstcount;
cmd_writedata = s0_writedata;
cmd_address = s0_address;
cmd_write = s0_write;
cmd_read = s0_read;
cmd_byteenable = s0_byteenable;
cmd_debugaccess = s0_debugaccess;
end
end
endgenerate
assign m0_burstcount = cmd_burstcount;
assign m0_writedata = cmd_writedata;
assign m0_address = cmd_address;
assign m0_write = cmd_write;
assign m0_read = cmd_read;
assign m0_byteenable = cmd_byteenable;
assign m0_debugaccess = cmd_debugaccess;
// --------------------------------------
// Response pipeline
//
// Registers all response signals
// --------------------------------------
generate if (PIPELINE_RESPONSE == 1) begin
always @(posedge clk, posedge reset) begin
if (reset) begin
rsp_readdatavalid <= 1'b0;
rsp_readdata <= 0;
rsp_response <= 0;
end
else begin
rsp_readdatavalid <= m0_readdatavalid;
rsp_readdata <= m0_readdata;
rsp_response <= m0_response;
end
end
end // conditional response pipeline
else begin
always @* begin
rsp_readdatavalid = m0_readdatavalid;
rsp_readdata = m0_readdata;
rsp_response = m0_response;
end
end
endgenerate
assign s0_readdatavalid = rsp_readdatavalid;
assign s0_readdata = rsp_readdata;
assign s0_response = rsp_response;
endmodule