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

Subversion Repositories orsoc_graphics_accelerator

[/] [orsoc_graphics_accelerator/] [trunk/] [rtl/] [verilog/] [gfx/] [gfx_triangle.v] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 Orka
/*
2
ORSoC GFX accelerator core
3
Copyright 2012, ORSoC, Per Lenander, Anton Fosselius.
4
 
5
TRIANGLE MODULE
6
 
7
 This file is part of orgfx.
8
 
9
 orgfx is free software: you can redistribute it and/or modify
10
 it under the terms of the GNU Lesser General Public License as published by
11
 the Free Software Foundation, either version 3 of the License, or
12
 (at your option) any later version.
13
 
14
 orgfx is distributed in the hope that it will be useful,
15
 but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 GNU Lesser General Public License for more details.
18
 
19
 You should have received a copy of the GNU Lesser General Public License
20
 along with orgfx.  If not, see <http://www.gnu.org/licenses/>.
21
 
22
*/
23
 
24
/*
25
This module rasterizes a triangle
26
*/
27
module gfx_triangle(clk_i, rst_i,
28
  ack_i, ack_o,
29
  triangle_write_i, texture_enable_i,
30
  //destination point 0, 1, 2
31
  dest_pixel0_x_i, dest_pixel0_y_i,
32
  dest_pixel1_x_i, dest_pixel1_y_i,
33
  dest_pixel2_x_i, dest_pixel2_y_i,
34
 
35
  x_counter_o, y_counter_o,
36
  write_o,
37
  triangle_edge0_o, triangle_edge1_o, triangle_area_o
38
  );
39
 
40
parameter point_width = 16;
41
parameter subpixel_width = 16;
42
 
43
input clk_i;
44
input rst_i;
45
 
46
input ack_i;
47
output reg ack_o;
48
 
49
input triangle_write_i;
50
input texture_enable_i;
51
 
52
//dest pixels
53
input signed [point_width-1:-subpixel_width] dest_pixel0_x_i;
54
input signed [point_width-1:-subpixel_width] dest_pixel0_y_i;
55
input signed [point_width-1:-subpixel_width] dest_pixel1_x_i;
56
input signed [point_width-1:-subpixel_width] dest_pixel1_y_i;
57
input signed [point_width-1:-subpixel_width] dest_pixel2_x_i;
58
input signed [point_width-1:-subpixel_width] dest_pixel2_y_i;
59
 
60
wire signed [point_width-1:0] p0_x = $signed(dest_pixel0_x_i[point_width-1:0]);
61
wire signed [point_width-1:0] p0_y = $signed(dest_pixel0_y_i[point_width-1:0]);
62
wire signed [point_width-1:0] p1_x = $signed(dest_pixel1_x_i[point_width-1:0]);
63
wire signed [point_width-1:0] p1_y = $signed(dest_pixel1_y_i[point_width-1:0]);
64
wire signed [point_width-1:0] p2_x = $signed(dest_pixel2_x_i[point_width-1:0]);
65
wire signed [point_width-1:0] p2_y = $signed(dest_pixel2_y_i[point_width-1:0]);
66
 
67
// Generated pixel coordinates
68
output reg [point_width-1:0] x_counter_o;
69
output reg [point_width-1:0] y_counter_o;
70
// Write pixel output signal
71
output reg write_o;
72
 
73
output     [2*point_width-1:0] triangle_edge0_o;
74
output     [2*point_width-1:0] triangle_edge1_o;
75
output reg [2*point_width-1:0] triangle_area_o;
76
 
77
// triangle raster reg & wires
78
reg triangle_ignore_pixel;
79
reg signed [point_width-1:0] triangle_bound_min_x;
80
reg signed [point_width-1:0] triangle_bound_min_y;
81
reg signed [point_width-1:0] triangle_bound_max_x;
82
reg signed [point_width-1:0] triangle_bound_max_y;
83
 
84
reg signed [2*point_width-1:0] triangle_area0;
85
reg signed [2*point_width-1:0] triangle_area1;
86
 
87
// edge0
88
reg signed [point_width-1:0] triangle_edge0_y2y1;
89
reg signed [point_width-1:0] triangle_edge0_xx1;
90
reg signed [point_width-1:0] triangle_edge0_x2x1;
91
reg signed [point_width-1:0] triangle_edge0_yy1;
92
 
93
// edge1
94
reg signed [point_width-1:0] triangle_edge1_y0y2;
95
reg signed [point_width-1:0] triangle_edge1_xx2;
96
reg signed [point_width-1:0] triangle_edge1_x0x2;
97
reg signed [point_width-1:0] triangle_edge1_yy2;
98
 
99
//edge2
100
reg signed [point_width-1:0] triangle_edge2_y1y0;
101
reg signed [point_width-1:0] triangle_edge2_xx0;
102
reg signed [point_width-1:0] triangle_edge2_x1x0;
103
reg signed [point_width-1:0] triangle_edge2_yy0;
104
reg        [point_width-1:0] triangle_x_counter;
105
reg        [point_width-1:0] triangle_y_counter;
106
reg                          triangle_line_active;
107
 
108
reg signed [point_width-1:-subpixel_width] diff_x1x0;
109
reg signed [point_width-1:-subpixel_width] diff_y2y0;
110
reg signed [point_width-1:-subpixel_width] diff_x2x0;
111
reg signed [point_width-1:-subpixel_width] diff_y1y0;
112
 
113
wire signed [point_width-1:0] diff_x1x0_int = diff_x1x0[point_width-1:0];
114
wire signed [point_width-1:0] diff_y2y0_int = diff_y2y0[point_width-1:0];
115
wire signed [point_width-1:0] diff_x2x0_int = diff_x2x0[point_width-1:0];
116
wire signed [point_width-1:0] diff_y1y0_int = diff_y1y0[point_width-1:0];
117
 
118
wire signed [2*point_width-1:0] triangle_edge0_val1 = triangle_edge0_y2y1 * triangle_edge0_xx1;
119
wire signed [2*point_width-1:0] triangle_edge0_val2 = triangle_edge0_x2x1 * triangle_edge0_yy1;
120
wire signed [2*point_width-1:0] triangle_edge1_val1 = triangle_edge1_y0y2 * triangle_edge1_xx2;
121
wire signed [2*point_width-1:0] triangle_edge1_val2 = triangle_edge1_x0x2 * triangle_edge1_yy2;
122
wire signed [2*point_width-1:0] triangle_edge2_val1 = triangle_edge2_y1y0 * triangle_edge2_xx0;
123
wire signed [2*point_width-1:0] triangle_edge2_val2 = triangle_edge2_x1x0 * triangle_edge2_yy0;
124
 
125
 
126
// e0(x,y) = -(p2y-p1y)(x-p1x)+(p2x-p1x)(y+p1y)
127
wire signed [2*point_width-1:0] triangle_edge0 = triangle_edge0_val2 - triangle_edge0_val1;
128
// e1(x,y) = -(p0y-p2y)(x-p2x)+(p0x-p2x)(y+p2y)
129
wire signed [2*point_width-1:0] triangle_edge1 = triangle_edge1_val2 - triangle_edge1_val1;
130
// e2(x,y) = -(p1y-p0y)(x-p0x)+(p1x-p0x)(y+p2y)
131
wire signed [2*point_width-1:0] triangle_edge2 = triangle_edge2_val2 - triangle_edge2_val1;
132
 
133
// Assign output (used in division in the interp module)
134
assign triangle_edge0_o = triangle_edge0;
135
assign triangle_edge1_o = triangle_edge1;
136
 
137
// Triangle iteration variables
138
wire triangle_done        = (triangle_y_counter >= triangle_bound_max_y ) & (triangle_line_done);
139
wire triangle_line_done   = (triangle_x_counter > triangle_bound_max_x) | (!triangle_valid_pixel & triangle_line_active);
140
wire triangle_valid_pixel = (triangle_edge0 >= 0 && triangle_edge1 >= 0 && triangle_edge2 >= 0)
141
                            && (triangle_x_counter >= 1'b0 && triangle_y_counter >= 1'b0);
142
 
143
// State machine
144
reg [1:0] state;
145
parameter wait_state           = 2'b00,
146
          triangle_prep_state  = 2'b01,
147
          triangle_calc_state  = 2'b10,
148
          triangle_write_state = 2'b11;
149
 
150
// Manage states
151
always @(posedge clk_i or posedge rst_i)
152
if(rst_i)
153
  state <= wait_state;
154
else
155
  case (state)
156
 
157
    wait_state:
158
      if(triangle_write_i)
159
        state <= triangle_prep_state;
160
 
161
    // Preparation stage
162
    triangle_prep_state:
163
      state <= triangle_calc_state;
164
 
165
    // Per pixel preparation stage
166
    triangle_calc_state:
167
      // Backface culling
168
      if(triangle_area0 - triangle_area1 > 0)
169
      begin
170
        if(ack_i | triangle_ignore_pixel)
171
          state <= triangle_write_state;
172
      end
173
      else
174
        state <= wait_state;
175
 
176
    // Pixel write stage
177
    triangle_write_state:
178
      if(triangle_done)
179
        state <= wait_state;
180
      else
181
        state <= triangle_calc_state;
182
 
183
  endcase
184
 
185
// Manage outputs (mealy machine)
186
always @(posedge clk_i or posedge rst_i)
187
begin
188
  // Reset
189
  if(rst_i)
190
  begin
191
    ack_o       <= 1'b0;
192
    x_counter_o <= 1'b0;
193
    y_counter_o <= 1'b0;
194
    write_o     <= 1'b0;
195
 
196
    diff_x1x0   <= 1'b0;
197
    diff_y2y0   <= 1'b0;
198
    diff_x2x0   <= 1'b0;
199
    diff_y1y0   <= 1'b0;
200
 
201
    //reset triangle regs
202
    triangle_bound_min_x  <= 1'b0;
203
    triangle_bound_min_y  <= 1'b0;
204
    triangle_bound_max_x  <= 1'b0;
205
    triangle_bound_max_y  <= 1'b0;
206
    triangle_ignore_pixel <= 1'b0;
207
    triangle_line_active  <= 1'b0;
208
    triangle_area0        <= 1'b0;
209
    triangle_area1        <= 1'b0;
210
 
211
    triangle_edge0_y2y1   <= 1'b0;
212
    triangle_edge0_xx1    <= 1'b0;
213
    triangle_edge0_x2x1   <= 1'b0;
214
    triangle_edge0_yy1    <= 1'b0;
215
 
216
    triangle_edge1_y0y2   <= 1'b0;
217
    triangle_edge1_xx2    <= 1'b0;
218
    triangle_edge1_x0x2   <= 1'b0;
219
    triangle_edge1_yy2    <= 1'b0;
220
 
221
    triangle_edge2_y1y0   <= 1'b0;
222
    triangle_edge2_xx0    <= 1'b0;
223
    triangle_edge2_x1x0   <= 1'b0;
224
    triangle_edge2_yy0    <= 1'b0;
225
 
226
    triangle_x_counter    <= 1'b0;
227
    triangle_y_counter    <= 1'b0;
228
 
229
    triangle_area_o       <= 1'b0;
230
  end
231
  else
232
  begin
233
    case (state)
234
 
235
      // Wait for incoming instructions
236
      wait_state:
237
      begin
238
        ack_o       <= 1'b0;
239
        if(triangle_write_i)
240
        begin
241
          // Initialize bounds
242
          triangle_bound_min_x <= (dest_pixel0_x_i <= dest_pixel1_x_i && dest_pixel0_x_i <= dest_pixel2_x_i) ? p0_x :
243
                                  (dest_pixel1_x_i <= dest_pixel2_x_i) ? p1_x :
244
                                  p2_x;
245
          triangle_bound_max_x <= (dest_pixel0_x_i >= dest_pixel1_x_i && dest_pixel0_x_i >= dest_pixel2_x_i) ? p0_x :
246
                                  (dest_pixel1_x_i >= dest_pixel2_x_i) ? p1_x :
247
                                  p2_x;
248
          triangle_bound_min_y <= (dest_pixel0_y_i <= dest_pixel1_y_i && dest_pixel0_y_i <= dest_pixel2_y_i) ? p0_y :
249
                                  (dest_pixel1_y_i <= dest_pixel2_y_i) ? p1_y :
250
                                  p2_y;
251
          triangle_bound_max_y <= (dest_pixel0_y_i >= dest_pixel1_y_i && dest_pixel0_y_i >= dest_pixel2_y_i) ? p0_y :
252
                                  (dest_pixel1_y_i >= dest_pixel2_y_i) ? p1_y :
253
                                  p2_y;
254
 
255
          diff_x1x0 <= dest_pixel1_x_i - dest_pixel0_x_i;
256
          diff_y2y0 <= dest_pixel2_y_i - dest_pixel0_y_i;
257
          diff_x2x0 <= dest_pixel2_x_i - dest_pixel0_x_i;
258
          diff_y1y0 <= dest_pixel1_y_i - dest_pixel0_y_i;
259
        end
260
      end
261
 
262
      // Triangle preparation
263
      triangle_prep_state:
264
      begin
265
        triangle_x_counter    <= (triangle_bound_min_x > 0) ? triangle_bound_min_x : 1'b0;
266
        triangle_y_counter    <= (triangle_bound_min_y > 0) ? triangle_bound_min_y : 1'b0;
267
        triangle_ignore_pixel <= 1'b1;
268
 
269
        triangle_area0        <= diff_x1x0_int * diff_y2y0_int;
270
        triangle_area1        <= diff_x2x0_int * diff_y1y0_int;
271
      end
272
 
273
      // Rasterize triangle
274
      triangle_calc_state:
275
      begin
276
        // Backface culling
277
        ack_o           <= (triangle_area0 - triangle_area1 <= 0);
278
        triangle_area_o <= triangle_area0 - triangle_area1;
279
 
280
        write_o <= 1'b0;
281
 
282
        if(ack_i | triangle_ignore_pixel)
283
        begin
284
          triangle_edge0_y2y1 <= p2_y                        - p1_y;
285
          triangle_edge0_xx1  <= $signed(triangle_x_counter) - p1_x;
286
          triangle_edge0_x2x1 <= p2_x                        - p1_x;
287
          triangle_edge0_yy1  <= $signed(triangle_y_counter) - p1_y;
288
 
289
          triangle_edge1_y0y2 <= p0_y                        - p2_y;
290
          triangle_edge1_xx2  <= $signed(triangle_x_counter) - p2_x;
291
          triangle_edge1_x0x2 <= p0_x                        - p2_x;
292
          triangle_edge1_yy2  <= $signed(triangle_y_counter) - p2_y;
293
 
294
          triangle_edge2_y1y0 <= p1_y                        - p0_y;
295
          triangle_edge2_xx0  <= $signed(triangle_x_counter) - p0_x;
296
          triangle_edge2_x1x0 <= p1_x                        - p0_x;
297
          triangle_edge2_yy0  <= $signed(triangle_y_counter) - p0_y;
298
        end
299
      end
300
 
301
      triangle_write_state:
302
      if(triangle_done)
303
      begin
304
        ack_o   <= 1'b1;
305
        write_o <= 1'b0;
306
      end
307
      else
308
      begin
309
        x_counter_o            <= triangle_x_counter;
310
        y_counter_o            <= triangle_y_counter;
311
        write_o                <= triangle_valid_pixel;
312
        triangle_ignore_pixel  <= !triangle_valid_pixel;
313
        if(triangle_line_done) // iterate through width of rect
314
        begin
315
          triangle_x_counter   <= (triangle_bound_min_x > 0) ? triangle_bound_min_x : 1'b0;
316
          triangle_y_counter   <= triangle_y_counter + 1'b1;
317
          triangle_line_active <= 1'b0;
318
        end
319
        else
320
        begin
321
          triangle_x_counter   <= triangle_x_counter + 1'b1;
322
          triangle_line_active <= triangle_valid_pixel;
323
        end
324
      end
325
    endcase
326
  end
327
end
328
 
329
endmodule
330
 

powered by: WebSVN 2.1.0

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