blob: 807e64c54ca4891d1ee27170214519229103944b [file] [log] [blame]
/*
* Copyright (c) 2021, Marcos Medeiros
* Licensed under BSD 3-clause.
*/
`include "fixedpt.vh"
module HuedeonGPU(
input i_clk,
input i_reset,
input i_enable,
input i_chip_select,
input [31:0] i_wr_address,
input [31:0] i_wr_data,
input i_wr_enable,
output [31:0] o_status,
output wire o_wr_enable,
output wire [17:0] o_wr_address,
output wire [7:0] o_r,
output wire [7:0] o_g,
output wire [7:0] o_b,
output [17:0] o_display_offset,
output reg ack_o
);
// GPU Registers
parameter REG_RESET = 0;
parameter REG_CONTROL = 1;
parameter REG_DRAW = 2;
parameter REG_V1_X = 3;
parameter REG_V1_Y = 4;
parameter REG_V1_Z = 5;
parameter REG_V1_COLOR = 6;
parameter REG_V1_UV = 7;
parameter REG_V2_X = 8;
parameter REG_V2_Y = 9;
parameter REG_V2_Z = 10;
parameter REG_V2_COLOR = 11;
parameter REG_V2_UV = 12;
parameter REG_V3_X = 13;
parameter REG_V3_Y = 14;
parameter REG_V3_Z = 15;
parameter REG_V3_COLOR = 16;
parameter REG_V3_UV = 17;
parameter REG_DRAW_OFFSET = 18;
parameter REG_DISP_OFFSET = 19;
// Vertex (X,Y,Z,U,V,R,G,B,A)
reg `FIXPT v1_x, v1_y, v1_z;
reg [15:0] v1_u, v1_v;
reg [7:0] v1_r, v1_g, v1_b, v1_a;
reg `FIXPT v2_x, v2_y, v2_z;
reg [15:0] v2_u, v2_v;
reg [7:0] v2_r, v2_g, v2_b, v2_a;
reg `FIXPT v3_x, v3_y, v3_z;
reg [15:0] v3_u, v3_v;
reg [7:0] v3_r, v3_g, v3_b, v3_a;
reg draw;
reg [17:0] draw_offset = 0;
reg [17:0] display_offset = 0;
reg control;
wire reset = i_reset || (i_wr_address == REG_RESET && i_wr_data[0]);
assign o_display_offset = display_offset;
always @(posedge i_clk)
begin
if (i_enable && i_wr_enable && i_chip_select)
begin
ack_o <= 1'b1;
case (i_wr_address)
REG_CONTROL : control <= i_wr_data;
REG_DRAW : draw <= i_wr_data[0];
REG_V1_X : v1_x <= i_wr_data;
REG_V1_Y : v1_y <= i_wr_data;
REG_V1_Z : v1_z <= i_wr_data;
REG_V1_UV : { v1_u, v1_v } <= i_wr_data;
REG_V1_COLOR : { v1_a, v1_r, v1_g, v1_b } <= i_wr_data;
REG_V2_X : v2_x <= i_wr_data;
REG_V2_Y : v2_y <= i_wr_data;
REG_V2_Z : v2_z <= i_wr_data;
REG_V2_UV : { v2_u, v2_v } <= i_wr_data;
REG_V2_COLOR : { v2_a, v2_r, v2_g, v2_b } <= i_wr_data;
REG_V3_X : v3_x <= i_wr_data;
REG_V3_Y : v3_y <= i_wr_data;
REG_V3_Z : v3_z <= i_wr_data;
REG_V3_UV : { v3_u, v3_v } <= i_wr_data;
REG_V3_COLOR : { v3_a, v3_r, v3_g, v3_b } <= i_wr_data;
REG_DRAW_OFFSET : draw_offset <= i_wr_data;
REG_DISP_OFFSET : display_offset <= i_wr_data;
endcase
end
else if(i_enable && i_chip_select) begin
ack_o <= 1'b1;
draw <= 0;
end
else begin
// Reset state write.
ack_o <= 1'b0;
draw <= 0;
end
end
wire enable_vertex_color = control;
wire tre_busy;
wire tre_done;
wire signed [15:0] wr_x_addr;
wire signed [15:0] wr_y_addr;
assign o_wr_address = draw_offset + (wr_y_addr * 320) + wr_x_addr;
assign o_status = { 29'b0, tre_done, tre_busy };
TriRasterEngine tre(
.i_clk (i_clk),
.i_reset (reset),
.i_draw (draw),
.i_v1_x (v1_x),
.i_v1_y (v1_y),
.i_v1_z (v1_z),
.i_v1_r (enable_vertex_color ? v1_r : 0),
.i_v1_g (enable_vertex_color ? v1_g : 0),
.i_v1_b (enable_vertex_color ? v1_b : 0),
.i_v1_u (v1_u),
.i_v1_v (v1_v),
.i_v2_x (v2_x),
.i_v2_y (v2_y),
.i_v2_z (v2_z),
.i_v2_r (enable_vertex_color ? v2_r : 0),
.i_v2_g (enable_vertex_color ? v2_g : 0),
.i_v2_b (enable_vertex_color ? v2_b : 0),
.i_v2_u (v2_u),
.i_v2_v (v2_v),
.i_v3_x (v3_x),
.i_v3_y (v3_y),
.i_v3_z (v3_z),
.i_v3_r (enable_vertex_color ? v3_r : 0),
.i_v3_g (enable_vertex_color ? v3_g : 0),
.i_v3_b (enable_vertex_color ? v3_b : 0),
.i_v3_u (v3_u),
.i_v3_v (v3_v),
.o_color_r (o_r),
.o_color_g (o_g),
.o_color_b (o_b),
.o_x (wr_x_addr),
.o_y (wr_y_addr),
.o_write_pixel (o_wr_enable),
.o_busy (tre_busy),
.o_done (tre_done)
);
endmodule