blob: 5e9aafdb2a803de0b0aa4967fa3ebb409c82911a [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_gpu_dma_addr.v
//
// *Module Description:
// Compute next Video-Ram address
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
module ogfx_gpu_dma_addr (
// OUTPUTs
vid_ram_addr_nxt_o, // Next Video-RAM address
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
display_width_i, // Display width
gfx_mode_1_bpp_i, // Graphic mode 1 bpp resolution
gfx_mode_2_bpp_i, // Graphic mode 2 bpp resolution
gfx_mode_4_bpp_i, // Graphic mode 4 bpp resolution
gfx_mode_8_bpp_i, // Graphic mode 8 bpp resolution
gfx_mode_16_bpp_i, // Graphic mode 16 bpp resolution
vid_ram_addr_i, // Video-RAM address
vid_ram_addr_init_i, // Video-RAM address initialization
vid_ram_addr_step_i, // Video-RAM address step
vid_ram_width_i, // Video-RAM width
vid_ram_win_x_swap_i, // Video-RAM X-Swap configuration
vid_ram_win_y_swap_i, // Video-RAM Y-Swap configuration
vid_ram_win_cl_swap_i // Video-RAM CL-Swap configuration
);
// OUTPUTs
//=========
output [`APIX_MSB:0] vid_ram_addr_nxt_o; // Next Video-RAM address
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
input [`LPIX_MSB:0] display_width_i; // Display width
input gfx_mode_1_bpp_i; // Graphic mode 1 bpp resolution
input gfx_mode_2_bpp_i; // Graphic mode 2 bpp resolution
input gfx_mode_4_bpp_i; // Graphic mode 4 bpp resolution
input gfx_mode_8_bpp_i; // Graphic mode 8 bpp resolution
input gfx_mode_16_bpp_i; // Graphic mode 16 bpp resolution
input [`APIX_MSB:0] vid_ram_addr_i; // Video-RAM address
input vid_ram_addr_init_i; // Video-RAM address initialization
input vid_ram_addr_step_i; // Video-RAM address step
input [`LPIX_MSB:0] vid_ram_width_i; // Video-RAM width
input vid_ram_win_x_swap_i; // Video-RAM X-Swap configuration
input vid_ram_win_y_swap_i; // Video-RAM Y-Swap configuration
input vid_ram_win_cl_swap_i; // Video-RAM CL-Swap configuration
//=============================================================================
// 1) COMPUTE NEXT MEMORY ACCESS
//=============================================================================
reg [`APIX_MSB:0] vid_ram_line_addr;
reg [`LPIX_MSB:0] vid_ram_column_count;
// Detect when the current line refresh is done
wire vid_ram_line_done = vid_ram_addr_step_i & (vid_ram_column_count==(vid_ram_width_i-{{`LPIX_MSB{1'b0}}, 1'b1}));
// Mux between initialization value and display width
wire [`LPIX_MSB:0] vid_ram_length_mux = vid_ram_addr_init_i ? vid_ram_width_i : display_width_i ;
// Align depending on graphic mode
wire [`LPIX_MSB+4:0] vid_ram_length_align = {`LPIX_MSB+5{gfx_mode_1_bpp_i }} & {4'b0000, vid_ram_length_mux[`LPIX_MSB:0] } |
{`LPIX_MSB+5{gfx_mode_2_bpp_i }} & {3'b000, vid_ram_length_mux[`LPIX_MSB:0], 1'b0 } |
{`LPIX_MSB+5{gfx_mode_4_bpp_i }} & {2'b00, vid_ram_length_mux[`LPIX_MSB:0], 2'b00 } |
{`LPIX_MSB+5{gfx_mode_8_bpp_i }} & {1'b0, vid_ram_length_mux[`LPIX_MSB:0], 3'b000 } |
{`LPIX_MSB+5{gfx_mode_16_bpp_i}} & { vid_ram_length_mux[`LPIX_MSB:0], 4'b0000} ;
wire [`APIX_MSB:0] plus_one_val = {`APIX_MSB+1{gfx_mode_1_bpp_i }} & {4'b0000, {{`VRAM_MSB{1'b0}}, 1'b1} } |
{`APIX_MSB+1{gfx_mode_2_bpp_i }} & {3'b000, {{`VRAM_MSB{1'b0}}, 1'b1}, 1'b0 } |
{`APIX_MSB+1{gfx_mode_4_bpp_i }} & {2'b00, {{`VRAM_MSB{1'b0}}, 1'b1}, 2'b00 } |
{`APIX_MSB+1{gfx_mode_8_bpp_i }} & {1'b0, {{`VRAM_MSB{1'b0}}, 1'b1}, 3'b000 } |
{`APIX_MSB+1{gfx_mode_16_bpp_i}} & { {{`VRAM_MSB{1'b0}}, 1'b1}, 4'b0000} ;
// Zero extension for LINT cleanup
wire [`APIX_MSB*3:0] vid_ram_length_norm = {{`APIX_MSB*3-`LPIX_MSB-4{1'b0}}, vid_ram_length_align};
// Select base address for next calculation
wire [`APIX_MSB:0] next_base_addr = (vid_ram_addr_init_i | ~vid_ram_line_done) ? vid_ram_addr_i :
vid_ram_line_addr ;
// Compute next address
wire [`APIX_MSB:0] next_addr = next_base_addr
+ (vid_ram_length_norm[`APIX_MSB:0] & {`APIX_MSB+1{~vid_ram_addr_init_i ? (~vid_ram_win_y_swap_i & (vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}})
- (vid_ram_length_norm[`APIX_MSB:0] & {`APIX_MSB+1{~vid_ram_addr_init_i ? ( vid_ram_win_y_swap_i & (vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}})
+ (plus_one_val & {`APIX_MSB+1{~vid_ram_addr_init_i ? (~vid_ram_win_x_swap_i & ~(vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}})
- (plus_one_val & {`APIX_MSB+1{~vid_ram_addr_init_i ? ( vid_ram_win_x_swap_i & ~(vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}});
wire update_line_addr = vid_ram_addr_init_i | vid_ram_line_done;
wire update_pixel_addr = update_line_addr | vid_ram_addr_step_i;
// Start RAM address of currentely refreshed line
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_line_addr <= {`APIX_MSB+1{1'b0}};
else if (update_line_addr) vid_ram_line_addr <= next_addr;
// Current RAM address of the currentely refreshed pixel
assign vid_ram_addr_nxt_o = update_pixel_addr ? next_addr : vid_ram_addr_i;
// Count the pixel number in the current line
// (used to detec the end of a line)
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_addr_init_i) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_line_done) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_addr_step_i) vid_ram_column_count <= vid_ram_column_count + {{`LPIX_MSB{1'b0}}, 1'b1};
endmodule // ogfx_calc_vram_addr
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif