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 |
|