blob: b9e138bb33853ce0f68abad1a89799ea6dc630ec [file] [log] [blame]
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_ram_arbiter.v
//
// *Module Description:
// RAM arbiter for LUT and VIDEO memories
// LUT-RAM arbitration:
//
// - Software interface: fixed highest priority
// - Refresh interface: fixed lowest priority
//
// Video-RAM arbitration:
//
// - Software interface: fixed highest priority
// - Refresh interface: round-robin with GPIO if
// - GPU interface: round-robin with Refresh if
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
module ogfx_ram_arbiter (
mclk, // Main system clock
puc_rst, // Main system reset
//------------------------------------------------------------
// SW interface, fixed highest priority
lut_ram_sw_addr_i, // LUT-RAM Software address
lut_ram_sw_din_i, // LUT-RAM Software data
lut_ram_sw_wen_i, // LUT-RAM Software write strobe (active low)
lut_ram_sw_cen_i, // LUT-RAM Software chip enable (active low)
lut_ram_sw_dout_o, // LUT-RAM Software data input
// Refresh-backend, fixed lowest priority
lut_ram_refr_addr_i, // LUT-RAM Refresh address
lut_ram_refr_din_i, // LUT-RAM Refresh data
lut_ram_refr_wen_i, // LUT-RAM Refresh write strobe (active low)
lut_ram_refr_cen_i, // LUT-RAM Refresh enable (active low)
lut_ram_refr_dout_o, // LUT-RAM Refresh data output
lut_ram_refr_dout_rdy_nxt_o, // LUT-RAM Refresh data output ready during next cycle
// LUT Memory interface
lut_ram_addr_o, // LUT-RAM address
lut_ram_din_o, // LUT-RAM data
lut_ram_wen_o, // LUT-RAM write strobe (active low)
lut_ram_cen_o, // LUT-RAM chip enable (active low)
lut_ram_dout_i, // LUT-RAM data input
//------------------------------------------------------------
// SW interface, fixed highest priority
vid_ram_sw_addr_i, // Video-RAM Software address
vid_ram_sw_din_i, // Video-RAM Software data
vid_ram_sw_wen_i, // Video-RAM Software write strobe (active low)
vid_ram_sw_cen_i, // Video-RAM Software chip enable (active low)
vid_ram_sw_dout_o, // Video-RAM Software data input
// GPU interface (round-robin with refresh-backend)
vid_ram_gpu_addr_i, // Video-RAM GPU address
vid_ram_gpu_din_i, // Video-RAM GPU data
vid_ram_gpu_wen_i, // Video-RAM GPU write strobe (active low)
vid_ram_gpu_cen_i, // Video-RAM GPU chip enable (active low)
vid_ram_gpu_dout_o, // Video-RAM GPU data input
vid_ram_gpu_dout_rdy_nxt_o, // Video-RAM GPU data output ready during next cycle
// Refresh-backend (round-robin with GPU interface)
vid_ram_refr_addr_i, // Video-RAM Refresh address
vid_ram_refr_din_i, // Video-RAM Refresh data
vid_ram_refr_wen_i, // Video-RAM Refresh write strobe (active low)
vid_ram_refr_cen_i, // Video-RAM Refresh enable (active low)
vid_ram_refr_dout_o, // Video-RAM Refresh data output
vid_ram_refr_dout_rdy_nxt_o, // Video-RAM Refresh data output ready during next cycle
// Video Memory interface
vid_ram_addr_o, // Video-RAM address
vid_ram_din_o, // Video-RAM data
vid_ram_wen_o, // Video-RAM write strobe (active low)
vid_ram_cen_o, // Video-RAM chip enable (active low)
vid_ram_dout_i // Video-RAM data input
//------------------------------------------------------------
);
// CLOCK/RESET
//=============
input mclk; // Main system clock
input puc_rst; // Main system reset
// LUT MEMORY
//=============
// SW interface, fixed highest priority
input [`LRAM_MSB:0] lut_ram_sw_addr_i; // LUT-RAM Software address
input [15:0] lut_ram_sw_din_i; // LUT-RAM Software data
input lut_ram_sw_wen_i; // LUT-RAM Software write strobe (active low)
input lut_ram_sw_cen_i; // LUT-RAM Software chip enable (active low)
output [15:0] lut_ram_sw_dout_o; // LUT-RAM Software data input
// Refresh-backend, fixed lowest priority
input [`LRAM_MSB:0] lut_ram_refr_addr_i; // LUT-RAM Refresh address
input [15:0] lut_ram_refr_din_i; // LUT-RAM Refresh data
input lut_ram_refr_wen_i; // LUT-RAM Refresh write strobe (active low)
input lut_ram_refr_cen_i; // LUT-RAM Refresh enable (active low)
output [15:0] lut_ram_refr_dout_o; // LUT-RAM Refresh data output
output lut_ram_refr_dout_rdy_nxt_o; // LUT-RAM Refresh data output ready during next cycle
// LUT Memory interface
output [`LRAM_MSB:0] lut_ram_addr_o; // LUT-RAM address
output [15:0] lut_ram_din_o; // LUT-RAM data
output lut_ram_wen_o; // LUT-RAM write strobe (active low)
output lut_ram_cen_o; // LUT-RAM chip enable (active low)
input [15:0] lut_ram_dout_i; // LUT-RAM data input
// VIDEO MEMORY
//==============
// SW interface, fixed highest priority
input [`VRAM_MSB:0] vid_ram_sw_addr_i; // Video-RAM Software address
input [15:0] vid_ram_sw_din_i; // Video-RAM Software data
input vid_ram_sw_wen_i; // Video-RAM Software write strobe (active low)
input vid_ram_sw_cen_i; // Video-RAM Software chip enable (active low)
output [15:0] vid_ram_sw_dout_o; // Video-RAM Software data input
// GPU interface (round-robin with refresh-backend)
input [`VRAM_MSB:0] vid_ram_gpu_addr_i; // Video-RAM GPU address
input [15:0] vid_ram_gpu_din_i; // Video-RAM GPU data
input vid_ram_gpu_wen_i; // Video-RAM GPU write strobe (active low)
input vid_ram_gpu_cen_i; // Video-RAM GPU chip enable (active low)
output [15:0] vid_ram_gpu_dout_o; // Video-RAM GPU data input
output vid_ram_gpu_dout_rdy_nxt_o; // Video-RAM GPU data output ready during next cycle
// Refresh-backend (round-robin with GPU interface)
input [`VRAM_MSB:0] vid_ram_refr_addr_i; // Video-RAM Refresh address
input [15:0] vid_ram_refr_din_i; // Video-RAM Refresh data
input vid_ram_refr_wen_i; // Video-RAM Refresh write strobe (active low)
input vid_ram_refr_cen_i; // Video-RAM Refresh enable (active low)
output [15:0] vid_ram_refr_dout_o; // Video-RAM Refresh data output
output vid_ram_refr_dout_rdy_nxt_o; // Video-RAM Refresh data output ready during next cycle
// Video Memory interface
output [`VRAM_MSB:0] vid_ram_addr_o; // Video-RAM address
output [15:0] vid_ram_din_o; // Video-RAM data
output vid_ram_wen_o; // Video-RAM write strobe (active low)
output vid_ram_cen_o; // Video-RAM chip enable (active low)
input [15:0] vid_ram_dout_i; // Video-RAM data input
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
reg gpu_is_last_owner;
//=============================================================================
// 2) LUT MEMORY ARBITER
//=============================================================================
// Arbitration signals
wire sw_lram_access_granted = ~lut_ram_sw_cen_i;
wire refr_lram_access_granted = ~sw_lram_access_granted & ~lut_ram_refr_cen_i;
// LUT RAM signal muxing
assign lut_ram_sw_dout_o = lut_ram_dout_i;
assign lut_ram_refr_dout_o = lut_ram_dout_i;
assign lut_ram_refr_dout_rdy_nxt_o = refr_lram_access_granted;
assign lut_ram_addr_o = ({`LRAM_AWIDTH{ sw_lram_access_granted }} & lut_ram_sw_addr_i ) |
({`LRAM_AWIDTH{ refr_lram_access_granted}} & lut_ram_refr_addr_i) ;
assign lut_ram_din_o = ({ 16{ sw_lram_access_granted }} & lut_ram_sw_din_i ) |
({ 16{ refr_lram_access_granted}} & lut_ram_refr_din_i ) ;
assign lut_ram_wen_o = ( ~sw_lram_access_granted | lut_ram_sw_wen_i ) &
( ~refr_lram_access_granted | lut_ram_refr_wen_i ) ;
assign lut_ram_cen_o = lut_ram_sw_cen_i & lut_ram_refr_cen_i;
//=============================================================================
// 3) VIDEO MEMORY ARBITER
//=============================================================================
// Arbitration signals
wire sw_vram_access_granted = ~vid_ram_sw_cen_i;
wire gpu_vram_access_granted = ~sw_vram_access_granted & // No SW access
((~vid_ram_gpu_cen_i & vid_ram_refr_cen_i) | // GPU requests alone
(~vid_ram_gpu_cen_i & ~vid_ram_refr_cen_i & ~gpu_is_last_owner)) ; // GPU & REFR both requests (arbitration required)
wire refr_vram_access_granted = ~sw_vram_access_granted & // No SW access
(( vid_ram_gpu_cen_i & ~vid_ram_refr_cen_i) | // GPU requests alone
(~vid_ram_gpu_cen_i & ~vid_ram_refr_cen_i & gpu_is_last_owner)) ; // GPU & REFR both requests (arbitration required)
// Detect who was the last to own the RAM between the GPU and Refresh interface
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) gpu_is_last_owner <= 1'b0;
else if (gpu_vram_access_granted ) gpu_is_last_owner <= 1'b1;
else if (refr_vram_access_granted) gpu_is_last_owner <= 1'b0;
// Video RAM signal muxing
assign vid_ram_sw_dout_o = vid_ram_dout_i;
assign vid_ram_gpu_dout_o = vid_ram_dout_i;
assign vid_ram_gpu_dout_rdy_nxt_o = gpu_vram_access_granted;
assign vid_ram_refr_dout_o = vid_ram_dout_i;
assign vid_ram_refr_dout_rdy_nxt_o = refr_vram_access_granted;
assign vid_ram_addr_o = ({`VRAM_AWIDTH{ sw_vram_access_granted }} & vid_ram_sw_addr_i ) |
({`VRAM_AWIDTH{ gpu_vram_access_granted }} & vid_ram_gpu_addr_i ) |
({`VRAM_AWIDTH{ refr_vram_access_granted}} & vid_ram_refr_addr_i) ;
assign vid_ram_din_o = ({ 16{ sw_vram_access_granted }} & vid_ram_sw_din_i ) |
({ 16{ gpu_vram_access_granted }} & vid_ram_gpu_din_i ) |
({ 16{ refr_vram_access_granted}} & vid_ram_refr_din_i ) ;
assign vid_ram_wen_o = ( ~sw_vram_access_granted | vid_ram_sw_wen_i ) &
( ~gpu_vram_access_granted | vid_ram_gpu_wen_i ) &
( ~refr_vram_access_granted | vid_ram_refr_wen_i ) ;
assign vid_ram_cen_o = vid_ram_sw_cen_i & vid_ram_gpu_cen_i & vid_ram_refr_cen_i;
endmodule // ogfx_ram_arbiter
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif