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

Subversion Repositories orsoc_graphics_accelerator

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /orsoc_graphics_accelerator/tags/version1.0/rtl/verilog
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/gfx/gfx_line.v
0,0 → 1,138
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
Bresenham line algarithm
 
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/>.
 
*/
 
module bresenham_line(clk_i, rst_i,
pixel0_x_i, pixel0_y_i, pixel1_x_i, pixel1_y_i,
x_major_i, minor_slope_positive_i, delta_minor_i, delta_major_i, draw_line_i, read_pixel_i,
busy_o, major_o, minor_o
);
 
input clk_i;
input rst_i;
 
input [15:0] pixel0_x_i;
input [15:0] pixel1_x_i;
input [15:0] pixel0_y_i;
input [15:0] pixel1_y_i;
 
input [15:0] delta_major_i;
input [15:0] delta_minor_i;
 
input draw_line_i;
input read_pixel_i;
input x_major_i;
input minor_slope_positive_i;
 
output reg busy_o;
 
output reg [15:0] major_o;
output reg [15:0] minor_o;
 
reg [15:0] major_goal;
reg signed [31:0] eps;
wire signed [31:0] eps_delta_minor;
wire done;
 
assign eps_delta_minor = eps+delta_minor_i;
 
always@(posedge clk_i or posedge rst_i)
begin
if(rst_i)
begin
eps <= 1'b0;
major_o <= 1'b0;
minor_o <= 1'b0;
busy_o <= 1'b0;
major_goal <= 1'b0;
end
else
begin
//bresenham magic
if(draw_line_i | read_pixel_i)
begin
if((major_o < major_goal) & minor_slope_positive_i & busy_o) // if we are between endpoints and want to draw a line, continue
begin
major_o <= major_o + 1'b1; // major axis increeses
if((eps_delta_minor*2) >= $signed(delta_major_i))
begin
eps <= eps_delta_minor - delta_major_i;
minor_o <= minor_o + 1'b1; // minor axis increeses
end
else
eps <= eps_delta_minor;
end
else if((major_o > major_goal) & !minor_slope_positive_i & busy_o)// the slope is negative
begin
major_o <= major_o - 1'b1; // major axis decreeses
 
if((eps_delta_minor*2) >= $signed(delta_major_i))
begin
eps <= eps_delta_minor - delta_major_i;
minor_o <= minor_o + 1'b1; // minor axis increeses
end
else
eps <= eps_delta_minor;
end
else if((major_o < major_goal) & !minor_slope_positive_i & x_major_i & busy_o)// special to fix ocant 4 & 8.
begin
major_o <= major_o + 1'b1; // major axis increeses
 
if((eps_delta_minor*2) >= $signed(delta_major_i))
begin
eps <= eps_delta_minor - delta_major_i;
minor_o <= minor_o - 1'b1; // minor axis decreeses
end
else
eps <= eps_delta_minor;
end
 
 
// if we are done and are busy, stop being busy.
else if(busy_o)
busy_o <= 1'b0;
 
if(!busy_o & draw_line_i)
begin
if(x_major_i) // output as normal
begin
major_o <= pixel0_x_i;
minor_o <= pixel0_y_i;
major_goal <= pixel1_x_i;
end
else
begin
major_o <= pixel0_y_i;
minor_o <= pixel0_x_i;
major_goal <= pixel1_y_i;
end
 
eps <= 1'b0;
busy_o <= 1'b1;
end
end
end
end
 
endmodule
 
/gfx/gfx_wbm_read_arbiter.v
0,0 → 1,102
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
WBM reader arbiter
 
Loosely based on the arbiter_dbus.v (LGPL) in orpsocv2 by Julius Baxter, julius@opencores.org
 
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/>.
 
*/
 
// 2 Masters, one slave
module gfx_wbm_read_arbiter
(
master_busy_o,
// Interface against the wbm read module
read_request_o,
addr_o,
sel_o,
dat_i,
ack_i,
// Interface against masters (fragment processor)
m0_read_request_i,
m0_addr_i,
m0_sel_i,
m0_dat_o,
m0_ack_o,
// Interface against masters (blender)
m1_read_request_i,
m1_addr_i,
m1_sel_i,
m1_dat_o,
m1_ack_o
);
 
output master_busy_o;
// Interface against the wbm read module
output read_request_o;
output [31:2] addr_o;
output [3:0] sel_o;
input [31:0] dat_i;
input ack_i;
// Interface against masters (fragment processor)
input m0_read_request_i;
input [31:2] m0_addr_i;
input [3:0] m0_sel_i;
output [31:0] m0_dat_o;
output m0_ack_o;
// Interface against masters (blender)
input m1_read_request_i;
input [31:2] m1_addr_i;
input [3:0] m1_sel_i;
output [31:0] m1_dat_o;
output m1_ack_o;
 
// Master ins -> |MUX> -> these wires
wire rreq_w;
wire [31:2] addr_w;
wire [3:0] sel_w;
// Slave ins -> |MUX> -> these wires
wire [31:0] dat_w;
wire ack_w;
 
// Master select (MUX controls)
wire [1:0] master_sel;
 
assign master_busy_o = m0_read_request_i | m1_read_request_i;
 
// priority to wbm1, the blender master
assign master_sel[0] = m0_read_request_i & !m1_read_request_i;
assign master_sel[1] = m1_read_request_i;
 
// Master input mux, priority to blender master
assign m0_dat_o = dat_i;
assign m0_ack_o = ack_i & master_sel[0];
 
assign m1_dat_o = dat_i;
assign m1_ack_o = ack_i & master_sel[1];
 
assign read_request_o = master_sel[1] ? m1_read_request_i :
m0_read_request_i;
assign addr_o = master_sel[1] ? m1_addr_i :
m0_addr_i;
assign sel_o = master_sel[1] ? m1_sel_i :
m0_sel_i;
endmodule // gfx_wbm_read_arbiter
 
/gfx/gfx_rasterizer.v
0,0 → 1,385
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
RASTERIZER 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 takes a rect write or line write request and generates pixels in the span given by dest_pixel0-1.
 
The operation is clipped to the span given by clip_pixel0-1. Pixels outside the span are discarded.
 
If texturing is enabled, texture coordinates u (horizontal) and v (vertical) are emitted, offset and clipped by the span given by src_pixel0-1.
 
When all pixels have been generated and acked, the rasterizer acks the operation and returns to wait state.
*/
module gfx_rasterizer(clk_i, rst_i,
ack_i, ack_o,
rect_write_i, line_write_i, texture_enable_i,
src_pixel0_x_i, src_pixel0_y_i, src_pixel1_x_i, src_pixel1_y_i, //source pixel 0 and pixel 1
dest_pixel0_x_i, dest_pixel0_y_i, dest_pixel1_x_i, dest_pixel1_y_i, //destination pixel 0 and pixel 1
clip_pixel0_x_i, clip_pixel0_y_i, clip_pixel1_x_i, clip_pixel1_y_i, //clip pixel 0 and pixel 1
target_size_x_i, target_size_y_i,
x_counter_o, y_counter_o, u_o,v_o,
write_o
);
 
input clk_i;
input rst_i;
 
input ack_i;
output reg ack_o;
 
input rect_write_i;
input line_write_i;
input texture_enable_i;
 
//src pixels
input [15:0] src_pixel0_x_i;
input [15:0] src_pixel0_y_i;
input [15:0] src_pixel1_x_i;
input [15:0] src_pixel1_y_i;
 
//dest pixels
input [15:0] dest_pixel0_x_i;
input [15:0] dest_pixel0_y_i;
input [15:0] dest_pixel1_x_i;
input [15:0] dest_pixel1_y_i;
 
//clip pixels
input [15:0] clip_pixel0_x_i;
input [15:0] clip_pixel0_y_i;
input [15:0] clip_pixel1_x_i;
input [15:0] clip_pixel1_y_i;
 
input [15:0] target_size_x_i;
input [15:0] target_size_y_i;
 
// Generated pixel coordinates
output reg [15:0] x_counter_o;
output reg [15:0] y_counter_o;
// Generated texture coordinates
output reg [15:0] u_o;
output reg [15:0] v_o;
// Write pixel output signal
output reg write_o;
 
// Variables used in rect drawing
reg [15:0] rect_p0_x;
reg [15:0] rect_p0_y;
reg [15:0] rect_p1_x;
reg [15:0] rect_p1_y;
 
wire raster_rect_done;
 
//line drawing reg & wires
reg [15:0] xdiff; // dx
reg [15:0] ydiff; // dy
reg x_major_axis; // if x is the major axis (for each x, y changes less then x)
 
reg minor_slope_positive; // true if slope is in first quadrant
wire raster_line_busy; // busy, drawing a line.
reg draw_line; // trigger the line drawing.
 
wire [15:0] major_out; // the major axis
wire [15:0] minor_out; // the minor axis
 
reg [15:0] delta_major; // if x is major this value is xdiff, else ydiff
reg [15:0] delta_minor; // if x is minor this value is xdiff, else ydiff
 
reg [15:0] left_pixel_x; // this is the left most pixel of the two input pixels
reg [15:0] left_pixel_y;
reg [15:0] right_pixel_x; // this is the right most pixel of the two input pixels
reg [15:0] right_pixel_y;
 
wire request_next_pixel;
//########################
 
// State machine
reg [2:0] state;
parameter wait_state = 0, rect_state = 1, line_prep_state = 2, line_state = 3;
 
// Rect drawing variables
always @(posedge clk_i or posedge rst_i)
begin
if(rst_i)
begin
rect_p0_x <= 16'b0;
rect_p0_y <= 16'b0;
rect_p1_x <= 16'b0;
rect_p1_y <= 16'b0;
end
else
begin
// pixel0 x
if(dest_pixel0_x_i < clip_pixel0_x_i) // check if pixel is left of screen
rect_p0_x <= clip_pixel0_x_i;
else if(dest_pixel0_x_i > clip_pixel1_x_i) // check if pixel is right of screen
rect_p0_x <= clip_pixel1_x_i;
else
rect_p0_x <= dest_pixel0_x_i;
 
// pixel0 y
if(dest_pixel0_y_i < clip_pixel0_y_i) // check if pixel is above the screen
rect_p0_y <= clip_pixel0_y_i;
else if(dest_pixel0_y_i > clip_pixel1_y_i) // check if pixel is below the screen
rect_p0_y <= clip_pixel1_y_i;
else
rect_p0_y <= dest_pixel0_y_i;
 
// pixel1 x
if(dest_pixel1_x_i < clip_pixel0_x_i) // check if pixel is left of screen
rect_p1_x <= clip_pixel0_x_i;
else if(dest_pixel1_x_i > clip_pixel1_x_i -1'b1) // check if pixel is right of screen
rect_p1_x <= clip_pixel1_x_i -1'b1;
else
rect_p1_x <= dest_pixel1_x_i -1'b1;
 
// pixel1 y
if(dest_pixel1_y_i < clip_pixel0_y_i) // check if pixel is above the screen
rect_p1_y <= clip_pixel0_y_i;
else if(dest_pixel1_y_i > clip_pixel1_y_i -1'b1) // check if pixel is below the screen
rect_p1_y <= clip_pixel1_y_i -1'b1;
else
rect_p1_y <= dest_pixel1_y_i -1'b1;
end
end
 
// Checks if the current line in the rect being drawn is complete
wire raster_rect_line_done = (x_counter_o >= rect_p1_x) | (texture_enable_i && (u_o >= src_pixel1_x_i-1));
 
 
// Checks if the current rect is completely drawn
 
// TODO: ugly fix to prevent the an extra pixel being written when texturing is enabled. Ugly.
//assign raster_rect_done = ack_i & (x_counter_o >= rect_p1_x) & ((y_counter_o >= rect_p1_y) | (texture_enable_i && (v_o >= src_pixel1_y_i-1)));
assign raster_rect_done = (ack_i | texture_enable_i) & (x_counter_o >= rect_p1_x) & ((y_counter_o >= rect_p1_y) | (texture_enable_i && (v_o >= src_pixel1_y_i-1)));
 
// Special check if there are no pixels to draw at all (send ack immediately)
wire empty_raster = (rect_p0_x > rect_p1_x) | (rect_p0_y > rect_p1_y);
 
// Request wire for line drawing module
assign request_next_pixel = ack_i & raster_line_busy;
 
// Manage states
always @(posedge clk_i or posedge rst_i)
if(rst_i)
state <= wait_state;
else
case (state)
wait_state:
if(rect_write_i & !empty_raster) // if request for drawing a rect, go to rect drawing state
state <= rect_state;
else if(line_write_i)
state <= line_prep_state; // if request for drawing a line, go to line drawing state
rect_state:
if(raster_rect_done) // if we are done drawing a rect, go to wait state
state <= wait_state;
line_prep_state: // prep only takes 1 cycle
state <= line_state;
line_state:
if(!raster_line_busy & !draw_line) // if we are done drawing a line, go to wait state
state <= wait_state;
endcase
 
// Manage outputs (mealy machine)
always @(posedge clk_i or posedge rst_i)
begin
// Reset
if(rst_i)
begin
ack_o <= 1'b0;
x_counter_o <= 1'b0;
y_counter_o <= 1'b0;
write_o <= 1'b0;
u_o <= 1'b0;
v_o <= 1'b0;
 
//reset line regs
xdiff <= 1'b0;
ydiff <= 1'b0;
x_major_axis <= 1'b0;
minor_slope_positive <= 1'b0;
draw_line <= 1'b0;
delta_major <= 1'b0;
delta_minor <= 1'b0;
left_pixel_x <= 1'b0;
left_pixel_y <= 1'b0;
right_pixel_x <= 1'b0;
right_pixel_y <= 1'b0;
end
else
begin
case (state)
 
// Wait for incoming instructions
wait_state:
if(rect_write_i & !empty_raster) // Start a raster rectangle operation
begin
ack_o <= 1'b0;
write_o <= 1'b1;
// Generate pixel coordinates
x_counter_o <= rect_p0_x;
y_counter_o <= rect_p0_y;
// Generate texture coordinates
u_o <= ((clip_pixel0_x_i < dest_pixel0_x_i) ? 1'b0 : clip_pixel0_x_i - dest_pixel0_x_i) + src_pixel0_x_i;
v_o <= ((clip_pixel0_y_i < dest_pixel0_y_i) ? 1'b0 : clip_pixel0_y_i - dest_pixel0_y_i) + src_pixel0_y_i;
end
 
else if(rect_write_i & empty_raster & !ack_o) // Start a raster rectangle operation
ack_o <= 1'b1;
 
// Start a raster line operation
else if(line_write_i)
begin
ack_o <= 1'b0;
// check diff in x and y
if(dest_pixel0_x_i > dest_pixel1_x_i)
begin
xdiff <= dest_pixel0_x_i - dest_pixel1_x_i;
 
// pixel0 is grater then pixel1, pixel1 is left of pixel0.
left_pixel_x <= dest_pixel1_x_i;
left_pixel_y <= dest_pixel1_y_i;
right_pixel_x <= dest_pixel0_x_i;
right_pixel_y <= dest_pixel0_y_i;
 
// check diff for y axis (swapped)
if(dest_pixel1_y_i > dest_pixel0_y_i)
begin
ydiff <= dest_pixel1_y_i - dest_pixel0_y_i;
minor_slope_positive <= 1'b0;
end
else
begin
ydiff <= dest_pixel0_y_i - dest_pixel1_y_i;
minor_slope_positive <= 1'b1;
end
 
end
else
begin
xdiff <= dest_pixel1_x_i - dest_pixel0_x_i;
 
// pixel1 is grater then pixel0, pixel0 is left of pixel1.
left_pixel_x <= dest_pixel0_x_i;
left_pixel_y <= dest_pixel0_y_i;
right_pixel_x <= dest_pixel1_x_i;
right_pixel_y <= dest_pixel1_y_i;
 
// check diff for y axis
if(dest_pixel0_y_i > dest_pixel1_y_i)
begin
ydiff <= dest_pixel0_y_i - dest_pixel1_y_i;
minor_slope_positive <= 1'b0; // the slope is "\" negative
end
else
begin
ydiff <= dest_pixel1_y_i - dest_pixel0_y_i;
minor_slope_positive <= 1'b1; // the slope is "/" positive
end
end
end
else
ack_o <= 1'b0;
 
 
// Rasterize a rectangle between p0 and p1 (rasterize = generate the pixels)
rect_state:
begin
if(ack_i) // If our last coordinate was acknowledged by a fragment processor
begin
if(raster_rect_line_done) // iterate through width of rect
begin
x_counter_o <= rect_p0_x;
y_counter_o <= y_counter_o + 1'b1;
u_o <= ((clip_pixel0_x_i < dest_pixel0_x_i) ? 1'b0 : clip_pixel0_x_i - dest_pixel0_x_i) + src_pixel0_x_i;
v_o <= v_o + 1'b1;
end
else
begin
x_counter_o <= x_counter_o + 1'b1;
u_o <= u_o + 1'b1;
end
end
if(raster_rect_done) // iterate through height of rect (are we done?)
begin
write_o <= 1'b0; // Only send ack when we get ack_i (see wait state)
ack_o <= 1'b1;
end
end
 
 
// Prepare linedrawing
line_prep_state:
begin
if(xdiff > ydiff)
begin // x major axis
x_major_axis <= 1'b1;
delta_major <= xdiff;
delta_minor <= ydiff;
end
else
begin // y major axis
x_major_axis <= 1'b0;
delta_major <= ydiff;
delta_minor <= xdiff;
end
// start draw line next tick
draw_line <= 1'b1;
end
 
 
// Rasterize a line between dest_pixel0 and dest_pixel1 (rasterize = generate the pixels)
line_state:
begin
draw_line <= 1'b0;
write_o <= raster_line_busy;
x_counter_o <= x_major_axis ? major_out : minor_out;
y_counter_o <= x_major_axis ? minor_out : major_out;
ack_o <= !raster_line_busy & !draw_line;
end
 
endcase
end
end
 
// Instansiation of bresenham line drawing module
bresenham_line bresenham(
.clk_i ( clk_i ), //clock
.rst_i ( rst_i ), //rest
.pixel0_x_i ( left_pixel_x ), // left pixel x
.pixel0_y_i ( left_pixel_y ), // left pixel y
.pixel1_x_i ( right_pixel_x ), // right pixel x
.pixel1_y_i ( right_pixel_y ), // right pixel y
.x_major_i ( x_major_axis ), // is true if x is the major axis ( for every x, y changes less then x )
.minor_slope_positive_i ( minor_slope_positive ), // true, if the slope is positive "/"
.delta_minor_i ( delta_minor ), // difference in major axis p0 and p1
.delta_major_i ( delta_major ), // difference in mino axis p0 and p1
.draw_line_i ( draw_line ), // trigger for drawing a line
.read_pixel_i ( request_next_pixel ), // request next pixel
.busy_o ( raster_line_busy ), // is true while line is drawn
.major_o ( major_out ), // the major axis pixel coordinate
.minor_o ( minor_out ) // the minor axis pixel coordinate
);
 
endmodule
 
/gfx/gfx_blender.v
0,0 → 1,218
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
PER-PIXEL COLORING MODULE, alpha blending
 
 
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 alpha blending by fetching the pixel from the target and mixing it with the texel based on the current alpha value.
 
The exact formula is:
color_out = color_in * alpha + color_target * (1-alpha) , where alpha is defined from 0 to 1
 
alpha_i[7:0] is used, so the actual span is 0 (transparent) to 255 (opaque)
 
If alpha blending is disabled (blending_enable_i == 1'b0) the module just passes on the input pixel.
*/
module gfx_blender(clk_i, rst_i,
blending_enable_i, target_base_i, target_size_x_i, target_size_y_i, color_depth_i,
x_counter_i, y_counter_i, alpha_i, write_i, ack_o, // from fragment
target_ack_i, target_addr_o, target_data_i, target_sel_o, target_request_o, wbm_busy_i, // from/to wbm reader
pixel_x_o, pixel_y_o, pixel_color_i, pixel_color_o, write_o, ack_i // to render
);
 
input clk_i;
input rst_i;
 
input blending_enable_i;
input [31:2] target_base_i;
input [15:0] target_size_x_i;
input [15:0] target_size_y_i;
input [1:0] color_depth_i;
 
// from fragment
input [15:0] x_counter_i;
input [15:0] y_counter_i;
input [7:0] alpha_i;
input [31:0] pixel_color_i;
input write_i;
output reg ack_o;
 
// Interface against wishbone master (reader)
input target_ack_i;
output [31:2] target_addr_o;
input [31:0] target_data_i;
output reg [3:0] target_sel_o;
output reg target_request_o;
input wbm_busy_i;
 
//to render
output reg [15:0] pixel_x_o;
output reg [15:0] pixel_y_o;
output reg [31:0] pixel_color_o;
output reg write_o;
input ack_i;
 
// State machine
reg [1:0] state;
parameter wait_state = 2'b00, target_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;
assign pixel_offset = (color_depth_i == 2'b00) ? (target_size_x_i*y_counter_i + {16'h0, x_counter_i}) : // 8 bit
(color_depth_i == 2'b01) ? (target_size_x_i*y_counter_i + {16'h0, x_counter_i}) << 1 : // 16 bit
(target_size_x_i*y_counter_i + {16'h0, x_counter_i}) << 2 ; // 32 bit
assign target_addr_o = target_base_i + pixel_offset[31:2];
 
// Split colors for alpha blending (render color)
wire [15:0] blend_color_r = (color_depth_i == 2'b00) ? pixel_color_i[7:0] :
(color_depth_i == 2'b01) ? pixel_color_i[15:11] :
pixel_color_i[23:16];
wire [15:0] blend_color_g = (color_depth_i == 2'b00) ? pixel_color_i[7:0] :
(color_depth_i == 2'b01) ? pixel_color_i[10:5] :
pixel_color_i[15:8];
wire [15:0] blend_color_b = (color_depth_i == 2'b00) ? pixel_color_i[7:0] :
(color_depth_i == 2'b01) ? pixel_color_i[4:0] :
pixel_color_i[7:0];
 
// Split colors for alpha blending (from target surface)
wire [15:0] target_color_r = (color_depth_i == 2'b00) ? dest_color[7:0] :
(color_depth_i == 2'b01) ? dest_color[15:11] :
target_data_i[23:16];
wire [15:0] target_color_g = (color_depth_i == 2'b00) ? dest_color[7:0] :
(color_depth_i == 2'b01) ? dest_color[10:5] :
target_data_i[15:8];
wire [15:0] target_color_b = (color_depth_i == 2'b00) ? dest_color[7:0] :
(color_depth_i == 2'b01) ? dest_color[4:0] :
target_data_i[7:0];
 
// Alpha blending (per color channel):
// rgb = (alpha1)(rgb1) + (1-alpha1)(rgb2)
wire [15:0] alpha_color_r = blend_color_r * alpha_i + target_color_r * (8'hff - alpha_i);
wire [15:0] alpha_color_g = blend_color_g * alpha_i + target_color_g * (8'hff - alpha_i);
wire [15:0] alpha_color_b = blend_color_b * alpha_i + target_color_b * (8'hff - alpha_i);
 
wire [31:0] dest_color;
// Memory to color converter
memory_to_color memory_proc(
.color_depth_i (color_depth_i),
.mem_i (target_data_i),
.mem_lsb_i (x_counter_i[1:0]),
.color_o (dest_color),
.sel_o ()
);
 
// Acknowledge when a command has completed
always @(posedge clk_i or posedge rst_i)
begin
// reset, init component
if(rst_i)
begin
ack_o <= 1'b0;
write_o <= 1'b0;
pixel_x_o <= 1'b0;
pixel_y_o <= 1'b0;
pixel_color_o <= 1'b0;
target_request_o <= 1'b0;
target_sel_o <= 4'b1111;
end
// Else, set outputs for next cycle
else
begin
case (state)
 
wait_state:
begin
ack_o <= 1'b0;
 
if(write_i)
begin
if(!blending_enable_i)
begin
pixel_x_o <= x_counter_i;
pixel_y_o <= y_counter_i;
pixel_color_o <= pixel_color_i;
write_o <= 1'b1;
end
else
target_request_o <= !wbm_busy_i;
end
end
 
 
target_read_state:
if(target_ack_i)
begin
write_o <= 1'b1;
pixel_x_o <= x_counter_i;
pixel_y_o <= y_counter_i;
target_request_o <= 1'b0;
 
// Recombine colors
pixel_color_o <= (color_depth_i == 2'b00) ? {alpha_color_r[15:8]} : // 8 bit grayscale
(color_depth_i == 2'b01) ? {alpha_color_r[12:8], alpha_color_g[13:8], alpha_color_b[12:8]} : // 16 bit
{alpha_color_r[15:8], alpha_color_g[15:8], alpha_color_b[15:8]}; // 32 bit
end
else
target_request_o <= !wbm_busy_i | target_request_o;
 
 
write_pixel_state:
begin
write_o <= 1'b0;
if(ack_i)
ack_o <= 1'b1;
end
 
endcase
end
end
 
// State machine
always @(posedge clk_i or posedge rst_i)
begin
// reset, init component
if(rst_i)
state <= wait_state;
// Move in statemachine
else
case (state)
 
wait_state:
if(write_i & blending_enable_i)
state <= target_read_state;
else if(write_i)
state <= write_pixel_state;
 
target_read_state:
if(target_ack_i)
state <= write_pixel_state;
 
write_pixel_state:
if(ack_i)
state <= wait_state;
 
endcase
end
 
endmodule
 
/gfx/gfx_wbs.v
0,0 → 1,400
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
The Wishbone master component will interface with the video memory, writing outgoing pixels to it.
 
Loosely based on the vga lcds wishbone slave (LGPL) in orpsocv2 by Julius Baxter, julius@opencores.org
 
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/>.
 
*/
 
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
`include "vga_defines.v"
 
/*
This module acts as the main control interface of the orgfx core. It is built as a 32-bit wishbone slave interface with read and write capabilities.
 
The module has two states, wait and busy. The module enters busy state when a pipeline operation is triggered by a write to the control register.
 
In the busy state all incoming wishbone writes are queued up in a 64 item fifo. These will be processed in the order they were received when the module returns to wait state.
 
The module leaves the busy state and enters wait state when it receives an ack from the pipeline.
*/
module gfx_wbs(
clk_i, rst_i, adr_i, dat_i, dat_o, sel_i, we_i, stb_i, cyc_i, ack_o, rty_o, err_o, inta_o,
src_pixel0_x_o, src_pixel0_y_o, src_pixel1_x_o, src_pixel1_y_o, //src pixels
dest_pixel0_x_o, dest_pixel0_y_o, dest_pixel1_x_o, dest_pixel1_y_o, // dest pixels
clip_pixel0_x_o, clip_pixel0_y_o, clip_pixel1_x_o, clip_pixel1_y_o, // clip pixels
color_o,
target_base_o, target_size_x_o, target_size_y_o, tex0_base_o, tex0_size_x_o, tex0_size_y_o,
color_depth_o,
rect_write_o, line_write_o,
sint_i,
pipeline_ack_i,
texture_enable_o,
blending_enable_o,
global_alpha_o,
colorkey_enable_o,
colorkey_o
);
 
//
// inputs & outputs
//
 
// wishbone slave interface
input clk_i;
input rst_i;
input [9:0] adr_i;
input [31:0] dat_i;
output reg [31:0] dat_o;
input [ 3:0] sel_i;
input we_i;
input stb_i;
input cyc_i;
output reg ack_o;
output reg rty_o;
output reg err_o;
output reg inta_o;
// source pixel
output [15:0] src_pixel0_x_o;
output [15:0] src_pixel0_y_o;
output [15:0] src_pixel1_x_o;
output [15:0] src_pixel1_y_o;
// dest pixel
output [15:0] dest_pixel0_x_o;
output [15:0] dest_pixel0_y_o;
output [15:0] dest_pixel1_x_o;
output [15:0] dest_pixel1_y_o;
// clip pixel
output [15:0] clip_pixel0_x_o;
output [15:0] clip_pixel0_y_o;
output [15:0] clip_pixel1_x_o;
output [15:0] clip_pixel1_y_o;
 
output [31:0] color_o;
 
output [31:2] target_base_o;
output [15:0] target_size_x_o;
output [15:0] target_size_y_o;
output [31:2] tex0_base_o;
output [15:0] tex0_size_x_o;
output [15:0] tex0_size_y_o;
 
output [1:0] color_depth_o;
output rect_write_o;
output line_write_o;
 
// status register inputs
input sint_i; // system error interrupt request
 
// Pipeline feedback
input pipeline_ack_i; // operation done
 
// fragment
output texture_enable_o;
// blender
output blending_enable_o;
output [7:0] global_alpha_o;
output colorkey_enable_o;
output [31:0] colorkey_o;
 
//
// variable declarations
//
parameter REG_ADR_HIBIT = 7;
 
wire [REG_ADR_HIBIT:0] REG_ADR = adr_i[REG_ADR_HIBIT : 2];
 
// Declarations of register addresses:
parameter [REG_ADR_HIBIT : 0] CONTROL_ADR = 6'b00_0000;
parameter [REG_ADR_HIBIT : 0] STATUS_ADR = 6'b00_0100;
parameter [REG_ADR_HIBIT : 0] SRC_PIXEL0_ADR = 6'b00_1000;
parameter [REG_ADR_HIBIT : 0] SRC_PIXEL1_ADR = 6'b00_1100;
parameter [REG_ADR_HIBIT : 0] DEST_PIXEL0_ADR = 6'b01_0000;
parameter [REG_ADR_HIBIT : 0] DEST_PIXEL1_ADR = 6'b01_0100;
parameter [REG_ADR_HIBIT : 0] CLIP_PIXEL0_ADR = 6'b01_1000;
parameter [REG_ADR_HIBIT : 0] CLIP_PIXEL1_ADR = 6'b01_1100;
parameter [REG_ADR_HIBIT : 0] COLOR_ADR = 6'b10_0000;
parameter [REG_ADR_HIBIT : 0] TARGET_BASE_ADR = 6'b10_0100;
parameter [REG_ADR_HIBIT : 0] TARGET_SIZE_ADR = 6'b10_1000;
parameter [REG_ADR_HIBIT : 0] TEX0_BASE_ADR = 6'b10_1100;
parameter [REG_ADR_HIBIT : 0] TEX0_SIZE_ADR = 6'b11_0000;
parameter [REG_ADR_HIBIT : 0] ALPHA_ADR = 6'b11_0100;
parameter [REG_ADR_HIBIT : 0] COLORKEY_ADR = 6'b11_1000;
 
// Declare control register bits
parameter CTRL_TEXTURE_BIT = 2;
parameter CTRL_BLENDING_BIT = 3;
parameter CTRL_COLORKEY_BIT = 4;
parameter CTRL_RECT_BIT = 8;
parameter CTRL_LINE_BIT = 9;
 
// Declare status register bits
parameter STAT_BUSY_BIT = 0;
 
// Declaration of local registers
reg [31:0] control_reg, status_reg, target_base_reg, target_size_reg, tex0_base_reg, tex0_size_reg;
reg [31:0] src_pixel_pos_0_reg, src_pixel_pos_1_reg, color_reg;
reg [31:0] dest_pixel_pos_0_reg, dest_pixel_pos_1_reg;
reg [31:0] clip_pixel_pos_0_reg, clip_pixel_pos_1_reg;
reg [31:0] alpha_reg;
reg [31:0] colorkey_reg;
 
// Wishbone access wires
wire acc, acc32, reg_acc, reg_wacc;
 
reg [31:0] reg_dato; // data output from registers
 
// State machine variables
reg state;
parameter wait_state = 1'b0, busy_state = 1'b1;
 
//
// Module body
//
 
// wishbone access signals
assign acc = cyc_i & stb_i;
assign acc32 = (sel_i == 4'b1111);
assign reg_acc = acc & acc32;
assign reg_wacc = reg_acc & we_i;
 
// Generate wishbone ack
always @(posedge clk_i or posedge rst_i)
if(rst_i)
ack_o <= 1'b0;
else
ack_o <= reg_acc & acc32 & ~ack_o ;
 
// Generate wishbone rty
always @(posedge clk_i or posedge rst_i)
if(rst_i)
rty_o <= 1'b0;
else
rty_o <= 1'b0; //reg_acc & acc32 & ~rty_o ;
 
// Generate wishbone err
always @(posedge clk_i or posedge rst_i)
if(rst_i)
err_o <= 1'b0;
else
err_o <= acc & ~acc32 & ~err_o;
 
// Generate wishbone data out (for reads)
always @(posedge clk_i or posedge rst_i)
if(rst_i)
dat_o <= 32'h0000_0000;
else
dat_o <= reg_dato;
 
// generate interrupt request signal
always @(posedge clk_i or posedge rst_i) // TODO: Add new interrupts (only sint used atm)
if(rst_i)
inta_o <= 1'b0;
else
inta_o <= sint_i; // | other_int | (int_enable & int) | ...
 
// generate registers
always @(posedge clk_i or posedge rst_i)
begin : gen_regs
if (rst_i)
begin
control_reg <= 32'h00000000;
target_base_reg <= 32'h00000000;
target_size_reg <= 32'h00000000;
tex0_base_reg <= 32'h00000000;
tex0_size_reg <= 32'h00000000;
src_pixel_pos_0_reg <= 32'h00000000;
src_pixel_pos_1_reg <= 32'h00000000;
dest_pixel_pos_0_reg <= 32'h00000000;
dest_pixel_pos_1_reg <= 32'h00000000;
clip_pixel_pos_0_reg <= 32'h00000000;
clip_pixel_pos_1_reg <= 32'h00000000;
color_reg <= 32'h00000000;
alpha_reg <= 32'h000000ff;
colorkey_reg <= 32'h00000000;
end
// Read fifo to write to registers
else if (instruction_fifo_rreq)
begin
case (instruction_fifo_q_adr) // synopsis full_case parallel_case
CONTROL_ADR : control_reg <= instruction_fifo_q_data;
TARGET_BASE_ADR : target_base_reg <= instruction_fifo_q_data;
TARGET_SIZE_ADR : target_size_reg <= instruction_fifo_q_data;
TEX0_BASE_ADR : tex0_base_reg <= instruction_fifo_q_data;
TEX0_SIZE_ADR : tex0_size_reg <= instruction_fifo_q_data;
SRC_PIXEL0_ADR : src_pixel_pos_0_reg <= instruction_fifo_q_data;
SRC_PIXEL1_ADR : src_pixel_pos_1_reg <= instruction_fifo_q_data;
DEST_PIXEL0_ADR : dest_pixel_pos_0_reg <= instruction_fifo_q_data;
DEST_PIXEL1_ADR : dest_pixel_pos_1_reg <= instruction_fifo_q_data;
CLIP_PIXEL0_ADR : clip_pixel_pos_0_reg <= instruction_fifo_q_data;
CLIP_PIXEL1_ADR : clip_pixel_pos_1_reg <= instruction_fifo_q_data;
COLOR_ADR : color_reg <= instruction_fifo_q_data;
ALPHA_ADR : alpha_reg <= instruction_fifo_q_data;
COLORKEY_ADR : colorkey_reg <= instruction_fifo_q_data;
endcase
end
else
begin
/* To prevent entering an infinite write cycle, the bits that start pipeline operations are cleared here */
control_reg[CTRL_RECT_BIT] <= 1'b0; // Reset rect write
control_reg[CTRL_LINE_BIT] <= 1'b0; // Reset line write
end
end
 
// generate status register
always @(posedge clk_i or posedge rst_i)
if (rst_i)
status_reg <= 32'h00000000;
else
begin
status_reg[STAT_BUSY_BIT] <= (state == busy_state);
end
 
// Assign target and texture signals
assign target_base_o = target_base_reg[31:2];
assign target_size_x_o = target_size_reg[31:16];
assign target_size_y_o = target_size_reg[15:0];
assign tex0_base_o = tex0_base_reg[31:2];
assign tex0_size_x_o = tex0_size_reg[31:16];
assign tex0_size_y_o = tex0_size_reg[15:0];
 
// Assign source pixel signals
assign src_pixel0_x_o = src_pixel_pos_0_reg[31:16];
assign src_pixel0_y_o = src_pixel_pos_0_reg[15:0];
assign src_pixel1_x_o = src_pixel_pos_1_reg[31:16];
assign src_pixel1_y_o = src_pixel_pos_1_reg[15:0];
// Assign destination pixel signals
assign dest_pixel0_x_o = dest_pixel_pos_0_reg[31:16];
assign dest_pixel0_y_o = dest_pixel_pos_0_reg[15:0];
assign dest_pixel1_x_o = dest_pixel_pos_1_reg[31:16];
assign dest_pixel1_y_o = dest_pixel_pos_1_reg[15:0];
// Assign clipping pixel signals
assign clip_pixel0_x_o = clip_pixel_pos_0_reg[31:16];
assign clip_pixel0_y_o = clip_pixel_pos_0_reg[15:0];
assign clip_pixel1_x_o = clip_pixel_pos_1_reg[31:16];
assign clip_pixel1_y_o = clip_pixel_pos_1_reg[15:0];
// Assign color signals
assign color_o = color_reg;
assign global_alpha_o = alpha_reg[7:0];
assign colorkey_o = colorkey_reg;
 
 
 
// decode control register
assign color_depth_o = control_reg[1:0];
 
assign texture_enable_o = control_reg[CTRL_TEXTURE_BIT];
assign blending_enable_o = control_reg[CTRL_BLENDING_BIT];
assign colorkey_enable_o = control_reg[CTRL_COLORKEY_BIT];
/* 7:5 reserved for future enable bits */
assign rect_write_o = control_reg[CTRL_RECT_BIT];
assign line_write_o = control_reg[CTRL_LINE_BIT];
/* 31:10 reserved for future operation bits */
 
// decode status register TODO
 
// assign output from wishbone reads. Note that this does not account for pending writes in the fifo!
always @(REG_ADR or control_reg or status_reg or target_base_reg or target_size_reg or tex0_base_reg or tex0_size_reg or
src_pixel_pos_0_reg or src_pixel_pos_1_reg or
dest_pixel_pos_0_reg or dest_pixel_pos_1_reg or
clip_pixel_pos_0_reg or clip_pixel_pos_1_reg or color_reg or
alpha_reg or colorkey_reg)
casez (REG_ADR) // synopsis full_case parallel_case
CONTROL_ADR : reg_dato = control_reg;
STATUS_ADR : reg_dato = status_reg;
TARGET_BASE_ADR : reg_dato = target_base_reg;
TARGET_SIZE_ADR : reg_dato = target_size_reg;
TEX0_BASE_ADR : reg_dato = tex0_base_reg;
TEX0_SIZE_ADR : reg_dato = tex0_size_reg;
SRC_PIXEL0_ADR : reg_dato = src_pixel_pos_0_reg;
SRC_PIXEL1_ADR : reg_dato = src_pixel_pos_1_reg;
DEST_PIXEL0_ADR : reg_dato = dest_pixel_pos_0_reg;
DEST_PIXEL1_ADR : reg_dato = dest_pixel_pos_1_reg;
CLIP_PIXEL0_ADR : reg_dato = clip_pixel_pos_0_reg;
CLIP_PIXEL1_ADR : reg_dato = clip_pixel_pos_1_reg;
COLOR_ADR : reg_dato = color_reg;
ALPHA_ADR : reg_dato = alpha_reg;
COLORKEY_ADR : reg_dato = colorkey_reg;
default : reg_dato = 32'h0000_0000;
endcase
 
// State machine
always @(posedge clk_i or posedge rst_i)
if(rst_i)
state <= wait_state;
else
case (state)
wait_state:
// Signals that trigger pipeline operations
if(rect_write_o | line_write_o)
state <= busy_state;
busy_state:
// If a pipeline operation is finished, go back to wait state
if(pipeline_ack_i)
state <= wait_state;
endcase
 
/* Instruction fifo */
wire instruction_fifo_wreq;
wire [31:0] instruction_fifo_q_data;
wire [11:2] instruction_fifo_q_adr;
wire instruction_fifo_rreq;
wire instruction_fifo_valid_out;
reg fifo_read_ack;
reg fifo_write_ack;
 
always @(posedge clk_i or posedge rst_i)
if(rst_i)
fifo_read_ack <= 1'b0;
else
fifo_read_ack <= instruction_fifo_rreq & !fifo_read_ack;
 
assign instruction_fifo_rreq = instruction_fifo_valid_out & ~fifo_read_ack & (state == wait_state) & ~rect_write_o & ~line_write_o;
 
always @(posedge clk_i or posedge rst_i)
if(rst_i)
fifo_write_ack <= 1'b0;
else
fifo_write_ack <= instruction_fifo_wreq ? !fifo_write_ack : reg_wacc;
 
assign instruction_fifo_wreq = reg_wacc & ~fifo_write_ack;
 
// TODO: 64 places large enough?
basic_fifo #(42, 6) instruction_fifo(
.clock ( clk_i ),
.reset ( rst_i ),
 
.data_in ( {adr_i, dat_i} ),
.enq ( instruction_fifo_wreq ),
.full ( ), // TODO: use?
 
.data_out ( {instruction_fifo_q_adr, instruction_fifo_q_data} ),
.valid_out ( instruction_fifo_valid_out ),
.deq ( instruction_fifo_rreq )
);
 
endmodule
 
 
 
/gfx/gfx_color.v
0,0 → 1,73
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
Components for aligning colored pixels to memory and the inverse
 
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/>.
 
*/
 
module color_to_memory(color_depth_i, color_i, x_lsb_i,
mem_o, sel_o);
 
input [1:0] color_depth_i;
input [31:0] color_i;
input [1:0] x_lsb_i;
output [31:0] mem_o;
output [3:0] sel_o;
 
assign sel_o = (color_depth_i == 2'b00) && (x_lsb_i == 2'b00) ? 4'b1000 : // 8-bit
(color_depth_i == 2'b00) && (x_lsb_i == 2'b01) ? 4'b0100 : // 8-bit
(color_depth_i == 2'b00) && (x_lsb_i == 2'b10) ? 4'b0010 : // 8-bit
(color_depth_i == 2'b00) && (x_lsb_i == 2'b11) ? 4'b0001 : // 8-bit
(color_depth_i == 2'b01) && (x_lsb_i[0] == 1'b0) ? 4'b1100 : // 16-bit, high word
(color_depth_i == 2'b01) && (x_lsb_i[0] == 1'b1) ? 4'b0011 : // 16-bit, low word
4'b1111; // 32-bit
 
assign mem_o = (color_depth_i == 2'b00) && (x_lsb_i == 2'b00) ? {color_i[7:0], 24'h000000} : // 8-bit
(color_depth_i == 2'b00) && (x_lsb_i == 2'b01) ? {color_i[7:0], 16'h0000} : // 8-bit
(color_depth_i == 2'b00) && (x_lsb_i == 2'b10) ? {color_i[7:0], 8'h00} : // 8-bit
(color_depth_i == 2'b00) && (x_lsb_i == 2'b11) ? {color_i[7:0]} : // 8-bit
(color_depth_i == 2'b01) && (x_lsb_i[0] == 1'b0) ? {color_i[15:0], 16'h0000} : // 16-bit, high word
(color_depth_i == 2'b01) && (x_lsb_i[0] == 1'b1) ? {color_i[15:0]} : // 16-bit, low word
color_i; // 32-bit
 
endmodule
 
module memory_to_color(color_depth_i, mem_i, mem_lsb_i,
color_o, sel_o);
 
input [1:0] color_depth_i;
input [31:0] mem_i;
input [1:0] mem_lsb_i;
output [31:0] color_o;
output [3:0] sel_o;
 
assign sel_o = color_depth_i == 2'b00 ? 4'b0001 : // 8-bit
color_depth_i == 2'b01 ? 4'b0011 : // 16-bit, low word
4'b1111; // 32-bit
 
assign color_o = (color_depth_i == 2'b00) && (mem_lsb_i == 2'b00) ? {mem_i[31:24]} : // 8-bit
(color_depth_i == 2'b00) && (mem_lsb_i == 2'b01) ? {mem_i[23:16]} : // 8-bit
(color_depth_i == 2'b00) && (mem_lsb_i == 2'b10) ? {mem_i[15:8]} : // 8-bit
(color_depth_i == 2'b00) && (mem_lsb_i == 2'b11) ? {mem_i[7:0]} : // 8-bit
(color_depth_i == 2'b01) && (mem_lsb_i[0] == 1'b0) ? {mem_i[31:16]} : // 16-bit, high word
(color_depth_i == 2'b01) && (mem_lsb_i[0] == 1'b1) ? {mem_i[15:0]} : // 16-bit, low word
mem_i; // 32-bit
 
endmodule
 
/gfx/gfx_wbm_write.v
0,0 → 1,122
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
The Wishbone master component will interface with the video memory, writing outgoing pixels to it.
 
Loosely based on the vga lcds wishbone writer (LGPL) in orpsocv2 by Julius Baxter, julius@opencores.org
 
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/>.
 
*/
 
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
 
module gfx_wbm_write (clk_i, rst_i,
cyc_o, stb_o, cti_o, bte_o, we_o, adr_o, sel_o, ack_i, err_i, dat_o, sint_o,
write_i, ack_o,
render_addr_i, render_sel_i, render_dat_i);
 
// wishbone signals
input clk_i; // master clock input
input rst_i; // Asynchronous active high reset
output reg cyc_o; // cycle output
output stb_o; // strobe ouput
output [ 2:0] cti_o; // cycle type id
output [ 1:0] bte_o; // burst type extension
output we_o; // write enable output
output [31:0] adr_o; // address output
output [ 3:0] sel_o; // byte select outputs
input ack_i; // wishbone cycle acknowledge
input err_i; // wishbone cycle error
output [31:0] dat_o; // wishbone data out /// TEMP reg ///
 
output sint_o; // non recoverable error, interrupt host
 
// Renderer stuff
input write_i;
output reg ack_o;
 
input [31:2] render_addr_i;
input [3:0] render_sel_i;
input [31:0] render_dat_i;
 
//
// module body
//
 
assign adr_o = {render_addr_i, 2'b00};
assign dat_o = render_dat_i;
assign sel_o = render_sel_i;
assign sint_o = err_i;
// We only write, these can be constant
assign we_o = 1'b1;
assign stb_o = 1'b1;
assign cti_o = 3'b000;
assign bte_o = 2'b00;
 
// Acknowledge when a command has completed
always @(posedge clk_i or posedge rst_i)
begin
// reset, init component
if(rst_i)
begin
ack_o <= 1'b0;
cyc_o <= 1'b0;
end
// Else, set outputs for next cycle
else
begin
cyc_o <= ack_i ? 1'b0 : // TODO: connect to pixel fifo rreq instead
write_i ? 1'b1 :
cyc_o;
ack_o <= ack_i; // TODO: always set when fifo isn't full
end
end
 
// Pixel fifo for staging burst writes
/*
// Fifo stuff
wire pixel_fifo_full;
wire pixel_fifo_empty;
wire pixel_fifo_rreq;
wire pixel_fifo_wreq;
wire [31:0] pixel_fifo_d_adr;
wire [31:0] pixel_fifo_d_data;
wire [3:0] pixel_fifo_d_sel;
 
// fifo read & write
assign pixel_fifo_wreq = write_i & !pixel_fifo_full;// & vga_using_mem_i; //TODO: write directly if !vga_using_mem_i and pixel_fifo_empty
assign pixel_fifo_rreq = !pixel_fifo_empty & !vga_using_mem_i; // TODO: connect to ack_i
assign pixel_fifo_d_adr = {render_addr_i, 2'b00};
assign pixel_fifo_d_data = render_dat_i;
assign pixel_fifo_d_sel = render_sel_i;
basic_fifo #(68, 8) pixel_fifo(
.clock ( clk_i ),
.reset ( rst_i ),
 
.data_in ( {pixel_fifo_d_sel, pixel_fifo_d_adr, pixel_fifo_d_data} ),
.enq ( pixel_fifo_wreq ), // write request
.full ( pixel_fifo_full ),
 
// .data_out ( {sel_o, adr_o, dat_o} ), // TODO: multiple drivers
.valid_out ( pixel_fifo_empty ),
.deq ( pixel_fifo_rreq ) // read request
);
*/
endmodule
/gfx/gfx_wbm_read.v
0,0 → 1,107
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
WBM reader
 
Loosely based on the vga lcds wishbone reader (LGPL) in orpsocv2 by Julius Baxter, julius@opencores.org
 
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/>.
 
*/
 
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
 
module gfx_wbm_read (clk_i, rst_i,
cyc_o, stb_o, cti_o, bte_o, we_o, adr_o, sel_o, ack_i, err_i, dat_i, sint_o,
read_request_i,
texture_addr_i, texture_sel_i, texture_dat_o, texture_data_ack);
 
// inputs & outputs
 
// wishbone signals
input clk_i; // master clock input
input rst_i; // asynchronous active high reset
output reg cyc_o; // cycle output
output stb_o; // strobe ouput
output [ 2:0] cti_o; // cycle type id
output [ 1:0] bte_o; // burst type extension
output we_o; // write enable output
output [31:0] adr_o; // address output
output reg [ 3:0] sel_o; // byte select outputs (only 32bits accesses are supported)
input ack_i; // wishbone cycle acknowledge
input err_i; // wishbone cycle error
input [31:0] dat_i; // wishbone data in
 
output sint_o; // non recoverable error, interrupt host
 
// Request stuff
input read_request_i;
 
input [31:2] texture_addr_i;
input [3:0] texture_sel_i;
output [31:0] texture_dat_o;
output reg texture_data_ack;
 
//
// variable declarations
//
reg busy;
 
//
// module body
//
 
assign adr_o = {texture_addr_i, 2'b00};
assign texture_dat_o = dat_i;
// This interface is read only
assign we_o = 1'b0;
assign stb_o = 1'b1;
assign sint_o = err_i;
assign bte_o = 2'b00;
assign cti_o = 3'b000;
 
always @(posedge clk_i or posedge rst_i)
if (rst_i) // Reset
begin
texture_data_ack <= 1'b0;
cyc_o <= 1'b0;
sel_o <= 4'b1111;
busy <= 1'b0;
end
else
begin
sel_o <= texture_sel_i;
if(ack_i) // On ack, stop current read, send ack to fragment (TODO: Blender)
begin
cyc_o <= 1'b0;
texture_data_ack <= 1'b1;
busy <= 1'b0;
end
else if(read_request_i & !texture_data_ack) // Else, is there a pending request? Start a read
begin
cyc_o <= 1'b1;
texture_data_ack <= 1'b0;
busy <= 1'b1;
end
else if(!busy) // Else, are we done? Zero ack
texture_data_ack <= 1'b0;
end
 
endmodule
/gfx/basic_fifo.v
0,0 → 1,113
/*
Basic fifo
Copyright 2005, Timothy Miller
Updated 2012 by Per Lenander & Anton Fosselius (ORSoC)
- basic fifo is no longer of a fixed depth
 
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/>.
 
*/
 
module basic_fifo(
clock,
reset,
data_in,
enq,
full,
data_out,
valid_out,
deq
);
 
parameter fifo_width = 42;
parameter fifo_bit_depth = 6;
 
input clock, reset;
 
input [fifo_width-1:0] data_in;
input enq;
output full;
reg full;
 
output [fifo_width-1:0] data_out;
reg [fifo_width-1:0] data_out;
output valid_out;
reg valid_out;
input deq;
 
 
 
reg [fifo_width-1:0] fifo_data [0:2**(fifo_bit_depth)-1];
reg [fifo_bit_depth:0] fifo_head, fifo_tail;
reg [fifo_bit_depth:0] next_tail;
 
 
// accept input
wire next_full = fifo_head[fifo_bit_depth-1:0] == next_tail[fifo_bit_depth-1:0] &&
fifo_head[fifo_bit_depth] != next_tail[fifo_bit_depth];
wire is_full = fifo_head[fifo_bit_depth-1:0] == fifo_tail[fifo_bit_depth-1:0] &&
fifo_head[fifo_bit_depth] != fifo_tail[fifo_bit_depth];
always @(posedge clock or posedge reset)
if (reset)
begin
fifo_tail <= 1'b0;
next_tail <= 1'b1;
full <= 1'b0;
end
else if (/*!full && */ enq)
begin
// We can only enqueue when not full
fifo_data[fifo_tail[fifo_bit_depth-1:0]] <= data_in;
next_tail <= next_tail + 1'b1;
fifo_tail <= next_tail;
 
// We have to compute if it's full on next cycle
full <= next_full;
end
else
full <= is_full;
 
// provide output
wire is_empty = fifo_head == fifo_tail;
always @(posedge clock or posedge reset)
if (reset) begin
valid_out <= 1'b0;
fifo_head <= 1'b0;
end
else
begin
if (!is_empty)
begin
if (!valid_out || deq)
fifo_head <= fifo_head + 1'b1;
 
valid_out <= 1'b1;
end
else if (deq)
valid_out <= 1'b0;
end
 
always @(posedge clock)
// If no valid out or we're dequeueing, we want to grab
// the next data. If we're empty, we don't get valid_out,
// so we don't care if it's garbage.
if (!valid_out || deq)
data_out <= fifo_data[fifo_head[fifo_bit_depth-1:0]];
 
endmodule
/gfx/gfx_vector_processor.v
0,0 → 1,41
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
VECTOR PROCESSING 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/>.
 
*/
 
/* Stub. TODO */
module gfx_vector_processor(clk_i, rst_i,
vector_i, vector_o
);
 
input clk_i;
input rst_i;
 
input vector_i;
output reg vector_o;
 
always @(posedge clk_i)
begin
vector_o <= #1 vector_i;
end
 
endmodule
 
/gfx/gfx_fragment_processor.v
0,0 → 1,195
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
PER-PIXEL COLORING 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 adds color to the pixel generated by the rasterizer. It can either draw a flat color (using pixel_color_i) or
colors from a texture by using the u and v coordinates generated by the rasterizer.
*/
module gfx_fragment_processor(clk_i, rst_i,
global_alpha_i,
x_counter_i, y_counter_i, u_i, v_i, write_i, ack_o, // from raster
pixel_x_o, pixel_y_o, pixel_color_i, pixel_color_o, pixel_alpha_o, write_o, ack_i, // to render
texture_ack_i, texture_data_i, texture_addr_o, texture_sel_o, texture_request_o, // to/from wishbone master read
texture_enable_i, tex0_base_i, tex0_size_x_i, tex0_size_y_i, color_depth_i, colorkey_enable_i, colorkey_i // from wishbone slave
);
 
input clk_i;
input rst_i;
 
input [7:0] global_alpha_i;
 
// from raster
input [15:0] x_counter_i;
input [15:0] y_counter_i;
input [15:0] u_i; // x-ish
input [15:0] v_i; // y-ish
input [31:0] pixel_color_i;
input write_i;
output reg ack_o;
 
//to render
output reg [15:0] pixel_x_o;
output reg [15:0] pixel_y_o;
output reg [31:0] pixel_color_o;
output reg [7:0] pixel_alpha_o;
output reg write_o;
input ack_i;
 
// to/from wishbone master read
input texture_ack_i;
input [31:0] texture_data_i;
output [31:2] texture_addr_o;
output reg [3:0] texture_sel_o;
output reg texture_request_o;
 
// from wishbone slave
input texture_enable_i;
input [31:2] tex0_base_i;
input [15:0] tex0_size_x_i;
input [15:0] tex0_size_y_i;
input [1:0] color_depth_i;
input colorkey_enable_i;
input [31:0] colorkey_i;
 
wire [31:0] pixel_offset;
 
// Calculate the memory address of the texel to read
assign pixel_offset = (color_depth_i == 2'b00) ? (tex0_size_x_i*v_i + {16'h0, u_i}) : // 8 bit
(color_depth_i == 2'b01) ? (tex0_size_x_i*v_i + {16'h0, u_i}) << 1 : // 16 bit
(tex0_size_x_i*v_i + {16'h0, u_i}) << 2 ; // 32 bit
assign texture_addr_o = tex0_base_i + pixel_offset[31:2];
 
// State machine
reg [1:0] state;
parameter wait_state = 2'b00, texture_read_state = 2'b01, write_pixel_state = 2'b10;
 
wire [31:0] mem_conv_color_o;
 
// Color converter
memory_to_color color_proc(
.color_depth_i (color_depth_i),
.mem_i (texture_data_i),
.mem_lsb_i (u_i[1:0]),
.color_o (mem_conv_color_o),
.sel_o ()
);
 
// Does the fetched texel match the colorkey?
wire transparent_pixel = (color_depth_i == 2'b00) ? (mem_conv_color_o[7:0] == colorkey_i[7:0]) : // 8 bit
(color_depth_i == 2'b01) ? (mem_conv_color_o[15:0] == colorkey_i[15:0]) : // 16 bit
(mem_conv_color_o == colorkey_i); // 32 bit
 
// Acknowledge when a command has completed
always @(posedge clk_i or posedge rst_i)
begin
// reset, init component
if(rst_i)
begin
ack_o <= 1'b0;
write_o <= 1'b0;
pixel_x_o <= 1'b0;
pixel_y_o <= 1'b0;
pixel_color_o <= 1'b0;
pixel_alpha_o <= 1'b0;
texture_request_o <= 1'b0;
texture_sel_o <= 4'b1111;
end
// Else, set outputs for next cycle
else
begin
case (state)
 
wait_state:
begin
ack_o <= 1'b0;
 
if(write_i & texture_enable_i)
texture_request_o <= 1'b1;
else if(write_i)
begin
pixel_x_o <= x_counter_i;
pixel_y_o <= y_counter_i;
pixel_color_o <= pixel_color_i;
pixel_alpha_o <= global_alpha_i; // TODO base on uv?
write_o <= 1'b1; // Note, colorkey only supported for texture reads
end
end
 
 
texture_read_state:
if(texture_ack_i)
begin
pixel_x_o <= x_counter_i;
pixel_y_o <= y_counter_i;
pixel_color_o <= mem_conv_color_o;
pixel_alpha_o <= global_alpha_i; // TODO: base on uv?
texture_request_o <= 1'b0;
if(colorkey_enable_i & transparent_pixel)
ack_o <= 1'b1; // Colorkey enabled: Only write if the pixel doesn't match the colorkey
else
write_o <= 1'b1;
end
 
 
write_pixel_state:
begin
write_o <= 1'b0;
ack_o <= ack_i;
end
 
endcase
end
end
 
// State machine
always @(posedge clk_i or posedge rst_i)
begin
// reset, init component
if(rst_i)
state <= wait_state;
// Move in statemachine
else
case (state)
 
wait_state:
if(write_i & texture_enable_i)
state <= texture_read_state;
else if(write_i)
state <= write_pixel_state;
 
texture_read_state:
// Check for texture ack. If we have colorkeying enabled, only goto the write state if the texture doesn't match the colorkey
if(texture_ack_i & colorkey_enable_i)
state <= transparent_pixel ? wait_state : write_pixel_state;
else if(texture_ack_i)
state <= write_pixel_state;
 
write_pixel_state:
if(ack_i)
state <= wait_state;
 
endcase
end
 
endmodule
 
/gfx/gfx_top.v
0,0 → 1,443
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
TOP 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/>.
 
*/
 
module gfx_top (wb_clk_i, wb_rst_i, wb_inta_o,
// Wishbone master signals (interfaces with video memory, write)
wbm_write_cyc_o, wbm_write_stb_o, wbm_write_cti_o, wbm_write_bte_o, wbm_write_we_o, wbm_write_adr_o, wbm_write_sel_o, wbm_write_ack_i, wbm_write_err_i, wbm_write_dat_o,
// Wishbone master signals (interfaces with video memory, read)
wbm_read_cyc_o, wbm_read_stb_o, wbm_read_cti_o, wbm_read_bte_o, wbm_read_we_o, wbm_read_adr_o, wbm_read_sel_o, wbm_read_ack_i, wbm_read_err_i, wbm_read_dat_i,
// Wishbone slave signals (interfaces with main bus/CPU)
wbs_cyc_i, wbs_stb_i, wbs_cti_i, wbs_bte_i, wbs_we_i, wbs_adr_i, wbs_sel_i, wbs_ack_o, wbs_err_o, wbs_dat_i, wbs_dat_o
);
 
// Common wishbone signals
input wb_clk_i; // master clock input
input wb_rst_i; // Asynchronous active high reset
output wb_inta_o; // interrupt
 
// Wishbone master signals (write)
output wbm_write_cyc_o; // cycle output
output wbm_write_stb_o; // strobe output
output [ 2:0] wbm_write_cti_o; // cycle type id
output [ 1:0] wbm_write_bte_o; // burst type extension
output wbm_write_we_o; // write enable output
output [31:0] wbm_write_adr_o; // address output
output [ 3:0] wbm_write_sel_o; // byte select outputs (only 32bits accesses are supported)
input wbm_write_ack_i; // wishbone cycle acknowledge
input wbm_write_err_i; // wishbone cycle error
output [31:0] wbm_write_dat_o; // wishbone data out
 
// Wishbone master signals (read)
output wbm_read_cyc_o; // cycle output
output wbm_read_stb_o; // strobe output
output [ 2:0] wbm_read_cti_o; // cycle type id
output [ 1:0] wbm_read_bte_o; // burst type extension
output wbm_read_we_o; // write enable output
output [31:0] wbm_read_adr_o; // address output
output [ 3:0] wbm_read_sel_o; // byte select outputs (only 32bits accesses are supported)
input wbm_read_ack_i; // wishbone cycle acknowledge
input wbm_read_err_i; // wishbone cycle error
input [31:0] wbm_read_dat_i; // wishbone data in
 
// Wishbone slave signals
input wbs_cyc_i; // cycle input
input wbs_stb_i; // strobe input
input [ 2:0] wbs_cti_i; // cycle type id
input [ 1:0] wbs_bte_i; // burst type extension
input wbs_we_i; // write enable input
input [31:0] wbs_adr_i; // address input
input [ 3:0] wbs_sel_i; // byte select input (only 32bits accesses are supported)
output wbs_ack_o; // wishbone cycle acknowledge
output wbs_err_o; // wishbone cycle error
input [31:0] wbs_dat_i; // wishbone data in
output [31:0] wbs_dat_o; // wishbone data out
 
// Wires and variables
 
wire wbmwriter_sint; // connect to slave interface
wire wbmreader_sint;
 
wire raster_wbs_pipeline_ack;
 
wire [31:2] target_base_reg;
wire [15:0] wbs_raster_target_size_x;
wire [15:0] wbs_raster_target_size_y;
wire [15:0] target_size_x_reg;
wire [15:0] target_size_y_reg;
 
assign target_size_x_reg = wbs_raster_target_size_x;
assign target_size_y_reg = wbs_raster_target_size_y;
 
wire [31:2] wbs_fragment_tex0_base;
wire [15:0] wbs_fragment_tex0_size_x;
wire [15:0] wbs_fragment_tex0_size_y;
 
wire [31:2] render_wbmwriter_addr;
wire [3:0] render_wbmwriter_sel;
wire [31:0] render_wbmwriter_dat;
 
wire [1:0] color_depth_reg;
 
wire render_wbmwriter_memory_pixel_write;
wire wbs_raster_rect_write;
wire wbs_raster_line_write;
wire wbmwriter_render_ack;
 
// src pixel
wire [15:0] wbs_raster_src_pixel0_x;
wire [15:0] wbs_raster_src_pixel0_y;
wire [15:0] wbs_raster_src_pixel1_x;
wire [15:0] wbs_raster_src_pixel1_y;
 
// dest pixel
wire [15:0] wbs_raster_dest_pixel0_x;
wire [15:0] wbs_raster_dest_pixel0_y;
wire [15:0] wbs_raster_dest_pixel1_x;
wire [15:0] wbs_raster_dest_pixel1_y;
 
// clip pixel
wire [15:0] wbs_raster_clip_pixel0_x;
wire [15:0] wbs_raster_clip_pixel0_y;
wire [15:0] wbs_raster_clip_pixel1_x;
wire [15:0] wbs_raster_clip_pixel1_y;
 
wire [31:0] wbs_fragment_color;
 
wire texture_enable_reg;
 
wire blending_enable_reg;
wire [7:0] global_alpha_reg;
wire colorkey_enable_reg;
wire [31:0] colorkey_reg;
 
// Slave wishbone interface. Reads wishbone bus and fills registers
gfx_wbs wb_databus (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.adr_i (wbs_adr_i[9:0]),
.dat_i (wbs_dat_i),
.dat_o (wbs_dat_o),
.sel_i (wbs_sel_i),
.we_i (wbs_we_i),
.stb_i (wbs_stb_i),
.cyc_i (wbs_cyc_i),
.ack_o (wbs_ack_o),
.rty_o (),
.err_o (wbs_err_o),
.inta_o (wb_inta_o),
 
//source pixel
.src_pixel0_x_o (wbs_raster_src_pixel0_x),
.src_pixel0_y_o (wbs_raster_src_pixel0_y),
.src_pixel1_x_o (wbs_raster_src_pixel1_x),
.src_pixel1_y_o (wbs_raster_src_pixel1_y),
//destination pixel
.dest_pixel0_x_o (wbs_raster_dest_pixel0_x),
.dest_pixel0_y_o (wbs_raster_dest_pixel0_y),
.dest_pixel1_x_o (wbs_raster_dest_pixel1_x),
.dest_pixel1_y_o (wbs_raster_dest_pixel1_y),
//clip pixel
.clip_pixel0_x_o (wbs_raster_clip_pixel0_x),
.clip_pixel0_y_o (wbs_raster_clip_pixel0_y),
.clip_pixel1_x_o (wbs_raster_clip_pixel1_x),
.clip_pixel1_y_o (wbs_raster_clip_pixel1_y),
 
.color_o (wbs_fragment_color),
 
.target_base_o (target_base_reg),
.target_size_x_o (wbs_raster_target_size_x),
.target_size_y_o (wbs_raster_target_size_y),
.tex0_base_o (wbs_fragment_tex0_base),
.tex0_size_x_o (wbs_fragment_tex0_size_x),
.tex0_size_y_o (wbs_fragment_tex0_size_y),
 
.color_depth_o (color_depth_reg),
 
.rect_write_o (wbs_raster_rect_write),
.line_write_o (wbs_raster_line_write),
 
.sint_i (wbmwriter_sint | wbmreader_sint),
 
.pipeline_ack_i (raster_wbs_pipeline_ack),
 
.texture_enable_o (texture_enable_reg),
.blending_enable_o (blending_enable_reg),
.global_alpha_o (global_alpha_reg),
.colorkey_enable_o (colorkey_enable_reg),
.colorkey_o (colorkey_reg)
);
 
/*
// TODO: Remove temp wires
wire vector_in;
wire vector;
 
// Vector processor applies transforms to points
gfx_vector_processor vp0 (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.vector_i (vector_in),
.vector_o (vector)
);
*/
 
wire raster_fragment_write_enable;
wire [15:0] raster_fragment_x_pixel;
wire [15:0] raster_fragment_y_pixel;
wire fragment_raster_ack;
wire [15:0] raster_fragment_u;
wire [15:0] raster_fragment_v;
 
// Rasterizer generates pixels to calculate
gfx_rasterizer rasterizer0 (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
 
.ack_i (fragment_raster_ack),
.ack_o (raster_wbs_pipeline_ack),
.rect_write_i (wbs_raster_rect_write),
.line_write_i (wbs_raster_line_write),
.texture_enable_i (texture_enable_reg),
// source pixel coordinates
.src_pixel0_x_i (wbs_raster_src_pixel0_x),
.src_pixel0_y_i (wbs_raster_src_pixel0_y),
.src_pixel1_x_i (wbs_raster_src_pixel1_x),
.src_pixel1_y_i (wbs_raster_src_pixel1_y),
 
// destination pixel coordinates
.dest_pixel0_x_i (wbs_raster_dest_pixel0_x),
.dest_pixel0_y_i (wbs_raster_dest_pixel0_y),
.dest_pixel1_x_i (wbs_raster_dest_pixel1_x),
.dest_pixel1_y_i (wbs_raster_dest_pixel1_y),
 
// clip pixel coordinates
.clip_pixel0_x_i (wbs_raster_clip_pixel0_x),
.clip_pixel0_y_i (wbs_raster_clip_pixel0_y),
.clip_pixel1_x_i (wbs_raster_clip_pixel1_x),
.clip_pixel1_y_i (wbs_raster_clip_pixel1_y),
 
// Screen size
.target_size_x_i (wbs_raster_target_size_x),
.target_size_y_i (wbs_raster_target_size_y),
 
// Output pixel
.x_counter_o (raster_fragment_x_pixel),
.y_counter_o (raster_fragment_y_pixel),
.u_o (raster_fragment_u),
.v_o (raster_fragment_v),
.write_o (raster_fragment_write_enable)
);
 
wire fragment_blender_write_enable;
wire [15:0] fragment_blender_x_pixel;
wire [15:0] fragment_blender_y_pixel;
wire blender_fragment_ack;
wire [31:0] fragment_blender_color;
wire [7:0] fragment_blender_alpha;
 
wire wbmreader_fragment_texture_ack;
wire [31:0] wbmreader_fragment_texture_data;
wire [31:2] fragment_wbmreader_texture_addr;
wire [3:0] fragment_wbmreader_texture_sel;
wire fragment_wbmreader_texture_request;
 
 
// Fragment processor generates color of pixel (requires RAM read for textures)
gfx_fragment_processor fp0 (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.global_alpha_i (global_alpha_reg),
.x_counter_i (raster_fragment_x_pixel),
.y_counter_i (raster_fragment_y_pixel),
.u_i (raster_fragment_u),
.v_i (raster_fragment_v),
.ack_i (blender_fragment_ack),
.write_i (raster_fragment_write_enable),
.pixel_x_o (fragment_blender_x_pixel),
.pixel_y_o (fragment_blender_y_pixel),
.pixel_color_i (wbs_fragment_color),
.pixel_color_o (fragment_blender_color),
.pixel_alpha_o (fragment_blender_alpha),
.write_o (fragment_blender_write_enable),
.ack_o (fragment_raster_ack),
.texture_ack_i (wbmreader_fragment_texture_ack),
.texture_data_i (wbmreader_fragment_texture_data),
.texture_addr_o (fragment_wbmreader_texture_addr),
.texture_sel_o (fragment_wbmreader_texture_sel),
.texture_request_o (fragment_wbmreader_texture_request),
.texture_enable_i (texture_enable_reg),
.tex0_base_i (wbs_fragment_tex0_base),
.tex0_size_x_i (wbs_fragment_tex0_size_x),
.tex0_size_y_i (wbs_fragment_tex0_size_y),
.color_depth_i (color_depth_reg),
.colorkey_enable_i (colorkey_enable_reg),
.colorkey_i (colorkey_reg)
);
 
wire blender_render_write_enable;
wire [15:0] blender_render_x_pixel;
wire [15:0] blender_render_y_pixel;
wire render_blender_ack;
wire [31:0] blender_render_color;
 
// Connected through arbiter
wire wbmreader_blender_target_ack;
wire [31:2] blender_wbmreader_target_addr;
wire [31:0] wbmreader_blender_target_data;
wire [3:0] blender_wbmreader_target_sel;
wire blender_wbmreader_target_request;
wire wbmreader_blender_busy;
 
// Applies alpha blending if enabled (requires RAM read to get target pixel color)
// Fragment processor generates color of pixel (requires RAM read for textures)
gfx_blender blender0 (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.blending_enable_i (blending_enable_reg),
// Render target information
.target_base_i (target_base_reg),
.target_size_x_i (target_size_x_reg),
.target_size_y_i (target_size_y_reg),
.color_depth_i (color_depth_reg),
.x_counter_i (fragment_blender_x_pixel),
.y_counter_i (fragment_blender_y_pixel),
.alpha_i (fragment_blender_alpha),
.ack_i (render_blender_ack),
.target_ack_i (wbmreader_blender_target_ack),
.target_addr_o (blender_wbmreader_target_addr),
.target_data_i (wbmreader_blender_target_data),
.target_sel_o (blender_wbmreader_target_sel),
.target_request_o (blender_wbmreader_target_request),
.wbm_busy_i (wbmreader_blender_busy),
.write_i (fragment_blender_write_enable),
.pixel_x_o (blender_render_x_pixel),
.pixel_y_o (blender_render_y_pixel),
.pixel_color_i (fragment_blender_color),
.pixel_color_o (blender_render_color),
.write_o (blender_render_write_enable),
.ack_o (blender_fragment_ack)
);
 
// Write pixel to target (check for out of bounds)
gfx_renderer renderer (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
// Render target information
.target_base_i (target_base_reg),
.target_size_x_i (target_size_x_reg),
.target_size_y_i (target_size_y_reg),
.color_depth_i (color_depth_reg),
// Input pixel
.pixel_x_i (blender_render_x_pixel),
.pixel_y_i (blender_render_y_pixel),
.color_i (blender_render_color),
 
.render_addr_o (render_wbmwriter_addr),
.render_sel_o (render_wbmwriter_sel),
.render_dat_o (render_wbmwriter_dat),
.ack_o (render_blender_ack),
.ack_i (wbmwriter_render_ack),
.write_i (blender_render_write_enable),
.write_o (render_wbmwriter_memory_pixel_write)
);
 
// Instansiate wishbone master interface (write only)
gfx_wbm_write wbm_writer (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.cyc_o (wbm_write_cyc_o),
.stb_o (wbm_write_stb_o),
.cti_o (wbm_write_cti_o),
.bte_o (wbm_write_bte_o),
.we_o (wbm_write_we_o),
.adr_o (wbm_write_adr_o),
.sel_o (wbm_write_sel_o),
.ack_i (wbm_write_ack_i),
.err_i (wbm_write_err_i),
.dat_o (wbm_write_dat_o),
.sint_o (wbmwriter_sint),
 
.write_i (render_wbmwriter_memory_pixel_write),
.ack_o (wbmwriter_render_ack),
 
// send ack to renderer when done writing to memory.
.render_addr_i (render_wbmwriter_addr),
.render_sel_i (render_wbmwriter_sel),
.render_dat_i (render_wbmwriter_dat)
);
 
wire wbmreader_arbiter_ack;
wire [31:2] arbiter_wbmreader_addr;
wire [31:0] wbmreader_arbiter_data;
wire [3:0] arbiter_wbmreader_sel;
wire arbiter_wbmreader_request;
 
// Instansiate wbm reader arbiter
gfx_wbm_read_arbiter wbm_arbiter (
.master_busy_o (wbmreader_blender_busy),
// Interface against the wbm read module
.read_request_o (arbiter_wbmreader_request),
.addr_o (arbiter_wbmreader_addr),
.sel_o (arbiter_wbmreader_sel),
.dat_i (wbmreader_arbiter_data),
.ack_i (wbmreader_arbiter_ack),
// Interface against masters (fragment processor)
.m0_read_request_i (fragment_wbmreader_texture_request),
.m0_addr_i (fragment_wbmreader_texture_addr),
.m0_sel_i (fragment_wbmreader_texture_sel),
.m0_dat_o (wbmreader_fragment_texture_data),
.m0_ack_o (wbmreader_fragment_texture_ack),
// Interface against masters (blender)
.m1_read_request_i (blender_wbmreader_target_request),
.m1_addr_i (blender_wbmreader_target_addr),
.m1_sel_i (blender_wbmreader_target_sel),
.m1_dat_o (wbmreader_blender_target_data),
.m1_ack_o (wbmreader_blender_target_ack)
);
 
// Instansiate wishbone master interface (read only for textures)
gfx_wbm_read wbm_reader (
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.cyc_o (wbm_read_cyc_o),
.stb_o (wbm_read_stb_o),
.cti_o (wbm_read_cti_o),
.bte_o (wbm_read_bte_o),
.we_o (wbm_read_we_o),
.adr_o (wbm_read_adr_o),
.sel_o (wbm_read_sel_o),
.ack_i (wbm_read_ack_i),
.err_i (wbm_read_err_i),
.dat_i (wbm_read_dat_i),
.sint_o (wbmreader_sint),
 
// send ack to renderer when done writing to memory.
.read_request_i (arbiter_wbmreader_request),
.texture_addr_i (arbiter_wbmreader_addr),
.texture_sel_i (arbiter_wbmreader_sel),
.texture_dat_o (wbmreader_arbiter_data),
.texture_data_ack (wbmreader_arbiter_ack)
);
 
endmodule
 
/gfx/timescale.v
0,0 → 1,2
`timescale 1ns / 10ps
 
/gfx/gfx_renderer.v
0,0 → 1,150
/*
ORSoC GFX accelerator core
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
 
RENDERING 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/>.
 
*/
 
module gfx_renderer(clk_i, rst_i,
target_base_i, target_size_x_i, target_size_y_i, color_depth_i,
pixel_x_i, pixel_y_i, color_i,
render_addr_o, render_sel_o, render_dat_o,
ack_o, ack_i,
write_i, write_o
);
 
input clk_i;
input rst_i;
 
// Render target information, used for checking out of bounds and stride when writing pixels
input [31:2] target_base_i;
input [15:0] target_size_x_i;
input [15:0] target_size_y_i;
 
input [1:0] color_depth_i;
 
input [15:0] pixel_x_i;
input [15:0] pixel_y_i;
input [31:0] color_i;
 
input write_i;
output reg write_o;
 
// Output registers connected to the wbm
output reg [31:2] render_addr_o;
output reg [3:0] render_sel_o;
output reg [31:0] render_dat_o;
wire [31:2] render_addr;
wire [3:0] render_sel;
wire [31:0] render_dat;
 
output reg ack_o;
input ack_i;
 
// TODO: Fifo for incoming pixel data?
 
 
 
// Define memory address
// Addr[31:2] = Base + (Y*width + X) * ppb
wire [31:0] pixel_offset;
assign pixel_offset = (color_depth_i == 2'b00) ? (target_size_x_i*pixel_y_i + pixel_x_i) : // 8 bit
(color_depth_i == 2'b01) ? (target_size_x_i*pixel_y_i + pixel_x_i) << 1 : // 16 bit
(target_size_x_i*pixel_y_i + pixel_x_i) << 2 ; // 32 bit
 
assign render_addr = target_base_i + pixel_offset[31:2];
 
// Color to memory converter
color_to_memory color_proc(
.color_depth_i (color_depth_i),
.color_i (color_i),
.x_lsb_i (pixel_x_i[1:0]),
.mem_o (render_dat),
.sel_o (render_sel)
);
 
// State machine
reg [0:0] state;
parameter wait_state = 0, write_pixel_state = 1;
 
// Acknowledge when a command has completed
always @(posedge clk_i or posedge rst_i)
begin
// reset, init component
if(rst_i)
begin
write_o <= 1'b0;
ack_o <= 1'b0;
render_addr_o <= 1'b0;
render_sel_o <= 1'b0;
render_dat_o <= 1'b0;
end
// Else, set outputs for next cycle
else
begin
case (state)
 
wait_state:
begin
ack_o <= 1'b0;
if(write_i)
begin
render_addr_o <= render_addr;
render_sel_o <= render_sel;
render_dat_o <= render_dat;
write_o <= 1'b1;
end
end
 
write_pixel_state:
begin
render_addr_o <= render_addr;
render_sel_o <= render_sel;
render_dat_o <= render_dat;
write_o <= 1'b0;
ack_o <= ack_i;
end
 
endcase
end
end
 
// State machine
always @(posedge clk_i or posedge rst_i)
begin
// reset, init component
if(rst_i)
state <= wait_state;
// Move in statemachine
else
case (state)
 
wait_state:
if(write_i)
state <= write_pixel_state;
 
write_pixel_state:
if(ack_i)
state <= wait_state;
 
endcase
end
 
endmodule
 

powered by: WebSVN 2.1.0

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