OpenCores
URL https://opencores.org/ocsvn/orsoc_graphics_accelerator/orsoc_graphics_accelerator/trunk

Subversion Repositories orsoc_graphics_accelerator

[/] [orsoc_graphics_accelerator/] [trunk/] [rtl/] [verilog/] [gfx/] [gfx_clip.v] - Rev 6

Compare with Previous | Blame | View Log

/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
CLIPPING/SCISSORING MODULE
 
 This file is part of orgfx.
 
 orgfx 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 3 of the License, or
 (at your option) any later version. 
 
 orgfx 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 orgfx.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 
/*
This module performs clipping by applying the current cliprect and the target size.
 
This module also performs z-buffer culling (requires reading from memory)
*/
module gfx_clip(clk_i, rst_i,
  clipping_enable_i, zbuffer_enable_i,
  zbuffer_base_i, target_size_x_i, target_size_y_i,
  clip_pixel0_x_i, clip_pixel0_y_i, clip_pixel1_x_i, clip_pixel1_y_i,                              //clip pixel 0 and pixel 1
  raster_pixel_x_i, raster_pixel_y_i, raster_u_i, raster_v_i, flat_color_i, raster_write_i, ack_o, // from raster
  cuvz_pixel_x_i, cuvz_pixel_y_i, cuvz_pixel_z_i, cuvz_u_i, cuvz_v_i, cuvz_color_i, cuvz_write_i,  // from cuvz
  cuvz_a_i,                                                                                        // from cuvz
  z_ack_i, z_addr_o, z_data_i, z_sel_o, z_request_o, wbm_busy_i,                                   // from/to wbm reader
  pixel_x_o, pixel_y_o, pixel_z_o, u_o, v_o, a_o,                                                  // to fragment
  bezier_factor0_i, bezier_factor1_i, bezier_factor0_o, bezier_factor1_o,                          // bezier calculations
  color_o, write_o, ack_i                                                                          // from/to fragment
  );
 
parameter point_width = 16;
 
input                   clk_i;
input                   rst_i;
 
input                   clipping_enable_i;
input                   zbuffer_enable_i;
input            [31:2] zbuffer_base_i;
input [point_width-1:0] target_size_x_i;
input [point_width-1:0] target_size_y_i;
//clip pixels
input [point_width-1:0] clip_pixel0_x_i;
input [point_width-1:0] clip_pixel0_y_i;
input [point_width-1:0] clip_pixel1_x_i;
input [point_width-1:0] clip_pixel1_y_i;
 
// From cuvz
input [point_width-1:0] cuvz_pixel_x_i;
input [point_width-1:0] cuvz_pixel_y_i;
input signed [point_width-1:0] cuvz_pixel_z_i;
input [point_width-1:0] cuvz_u_i;
input [point_width-1:0] cuvz_v_i;
input             [7:0] cuvz_a_i;
input            [31:0] cuvz_color_i;
input                   cuvz_write_i;
// From raster
input [point_width-1:0] raster_pixel_x_i;
input [point_width-1:0] raster_pixel_y_i;
input [point_width-1:0] raster_u_i;
input [point_width-1:0] raster_v_i;
input            [31:0] flat_color_i;
input                   raster_write_i;
output reg              ack_o;
 
// Interface against wishbone master (reader)
input             z_ack_i;
output     [31:2] z_addr_o;
input      [31:0] z_data_i;
output reg  [3:0] z_sel_o;
output reg        z_request_o;
input             wbm_busy_i;
 
// To fragment
output reg [point_width-1:0] pixel_x_o;
output reg [point_width-1:0] pixel_y_o;
output reg [point_width-1:0] pixel_z_o;
output reg [point_width-1:0] u_o;
output reg [point_width-1:0] v_o;
output reg             [7:0] a_o;
input      [point_width-1:0] bezier_factor0_i;
input      [point_width-1:0] bezier_factor1_i;
output reg [point_width-1:0] bezier_factor0_o;
output reg [point_width-1:0] bezier_factor1_o;
output reg            [31:0] color_o;
output reg write_o;
input ack_i;
 
// 
 
// State machine
reg [1:0] state;
parameter wait_state = 2'b00, z_read_state = 2'b01, write_pixel_state = 2'b10;
 
// Calculate address of target pixel
// Addr[31:2] = Base + (Y*width + X) * ppb
wire [31:0] pixel_offset = (target_size_x_i*cuvz_pixel_y_i   + {16'h0,   cuvz_pixel_x_i}) << 1; // 16 bit
assign z_addr_o = zbuffer_base_i + pixel_offset[31:2];
 
wire [31:0] z_value_at_target32;
wire signed [point_width-1:0] z_value_at_target = z_value_at_target32[point_width-1:0];
 
// Memory to color converter
memory_to_color memory_proc(
.color_depth_i (2'b01),
.mem_i         (z_data_i),
.mem_lsb_i     (cuvz_pixel_x_i[1:0]),
.color_o       (z_value_at_target32),
.sel_o         ()
);
 
// Forward texture coordinates, color, alpha etc
always @(posedge clk_i or posedge rst_i)
if(rst_i)
begin
  u_o              <= 1'b0;
  v_o              <= 1'b0;
  bezier_factor0_o <= 1'b0;
  bezier_factor1_o <= 1'b0;
  pixel_x_o        <= 1'b0;
  pixel_y_o        <= 1'b0;
  pixel_z_o        <= 1'b0;
  color_o          <= 1'b0;
  a_o              <= 1'b0;
  z_sel_o          <= 4'b1111;
end
else
begin
  // Implement a MUX, send data from either the raster or from the cuvz module to the fragment processor
  if(raster_write_i)
  begin
    u_o              <= raster_u_i;
    v_o              <= raster_v_i;
    a_o              <= 8'hff;
    color_o          <= flat_color_i;
    pixel_x_o        <= raster_pixel_x_i;
    pixel_y_o        <= raster_pixel_y_i;
    pixel_z_o        <= 1'b0;
  end
  // If the cuvz module is being used, more parameters needs to be forwarded
  else if(cuvz_write_i)
  begin
    u_o              <= cuvz_u_i;
    v_o              <= cuvz_v_i;
    a_o              <= cuvz_a_i;
    color_o          <= cuvz_color_i;
    pixel_x_o        <= cuvz_pixel_x_i;
    pixel_y_o        <= cuvz_pixel_y_i;
    pixel_z_o        <= cuvz_pixel_z_i;
    bezier_factor0_o <= bezier_factor0_i;
    bezier_factor1_o <= bezier_factor1_i;
  end
end
 
// Check if we should discard this pixel due to failing depth check
wire fail_z_check   = z_value_at_target > cuvz_pixel_z_i;
 
// Check if we should discard this pixel due to falling outside render target/clip rect
wire outside_target = raster_write_i ? (raster_pixel_x_i >= target_size_x_i) | (raster_pixel_y_i >= target_size_y_i) :
                      (cuvz_pixel_x_i >= target_size_x_i) | (cuvz_pixel_y_i >= target_size_y_i);
wire outside_clip   = raster_write_i ? (raster_pixel_x_i < clip_pixel0_x_i) | (raster_pixel_y_i < clip_pixel0_y_i) | (raster_pixel_x_i >= clip_pixel1_x_i) | (raster_pixel_y_i >= clip_pixel1_y_i) :
                      (cuvz_pixel_x_i < clip_pixel0_x_i) | (cuvz_pixel_y_i < clip_pixel0_y_i) | (cuvz_pixel_x_i >= clip_pixel1_x_i) | (cuvz_pixel_y_i >= clip_pixel1_y_i);
wire discard_pixel  = outside_target | (clipping_enable_i & outside_clip);
 
// Check if there is a write signal
wire write_i        = raster_write_i | cuvz_write_i;
 
// Acknowledge when a command has completed
always @(posedge clk_i or posedge rst_i)
// reset, init component
if(rst_i)
begin
  ack_o            <= 1'b0;
  write_o          <= 1'b0;
  z_request_o      <= 1'b0;
  z_sel_o          <= 4'b1111;
end
// Else, set outputs for next cycle
else
begin
  case (state)
 
    wait_state:
    begin
      if(write_i)
        ack_o         <= discard_pixel;
      else
        ack_o         <= 1'b0;
 
      if(write_i & zbuffer_enable_i)
        z_request_o   <= ~discard_pixel;
      else if(write_i)
        write_o       <= ~discard_pixel;
 
    end
 
    // Do a depth check. If it fails, discard pixel, ack and go back to wait. If it succeeds, go to write state
    z_read_state:
      if(z_ack_i)
      begin
        write_o     <= ~fail_z_check;
        ack_o       <= fail_z_check;
        z_request_o <= 1'b0;
      end
      else
        z_request_o <= ~wbm_busy_i | z_request_o;
 
    // ack, then go back to wait state when the next module is ready
    write_pixel_state:
    begin
      write_o <= 1'b0;
      if(ack_i)
        ack_o <= 1'b1;    
    end
 
  endcase
 
end
 
// State machine
always @(posedge clk_i or posedge rst_i)
// reset, init component
if(rst_i)
  state <= wait_state;
// Move in statemachine
else
  case (state)
 
    wait_state:
      if(write_i & ~discard_pixel)
      begin
        if(zbuffer_enable_i)
          state <= z_read_state;
        else 
          state <= write_pixel_state;
      end
 
    z_read_state:
      if(z_ack_i)
        state <= fail_z_check ? wait_state : write_pixel_state;
 
    write_pixel_state:
      if(ack_i)
        state <= wait_state;
 
  endcase
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.