301 lines
11 KiB
Verilog
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
|