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_line.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
Bresenham line algarithm
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
// trigger on high
24
 
25
module bresenham_line(clk_i, rst_i,
26
pixel0_x_i, pixel0_y_i, pixel1_x_i, pixel1_y_i,
27
draw_line_i, read_pixel_i,
28
busy_o, x_major_o, major_o, minor_o, valid_o
29
);
30
 
31
parameter point_width = 16;
32
parameter subpixel_width = 16;
33
 
34
input clk_i;
35
input rst_i;
36
 
37
input signed [point_width-1:-subpixel_width] pixel0_x_i;
38
input signed [point_width-1:-subpixel_width] pixel1_x_i;
39
input signed [point_width-1:-subpixel_width] pixel0_y_i;
40
input signed [point_width-1:-subpixel_width] pixel1_y_i;
41
 
42
input draw_line_i;
43
input read_pixel_i;
44
 
45
output reg busy_o;
46
output reg valid_o;
47
 
48
output reg signed [point_width-1:0] major_o;
49
output reg signed [point_width-1:0] minor_o;
50
 
51
//line drawing reg & wires
52
reg [point_width-1:-subpixel_width] xdiff; // dx
53
reg [point_width-1:-subpixel_width] ydiff; // dy
54
output reg x_major_o; // if x is the major axis (for each x, y changes less then x)
55
 
56
reg signed [point_width-1:-subpixel_width] left_pixel_x; // this is the left most pixel of the two input pixels
57
reg signed [point_width-1:-subpixel_width] left_pixel_y;
58
reg signed [point_width-1:-subpixel_width] right_pixel_x; // this is the right most pixel of the two input pixels
59
reg signed [point_width-1:-subpixel_width] right_pixel_y;
60
 
61
reg [point_width-1:-subpixel_width] delta_major; // if x is major this value is xdiff, else ydiff
62
reg [point_width-1:-subpixel_width] delta_minor; // if x is minor this value is xdiff, else ydiff
63
 
64
reg minor_slope_positive; // true if slope is in first quadrant 
65
 
66
reg  signed          [point_width-1:0] major_goal;
67
reg  signed [2*point_width-1:-subpixel_width] eps;
68
wire signed [2*point_width-1:-subpixel_width] eps_delta_minor;
69
wire done;
70
 
71
// State machine
72
reg [2:0] state;
73
parameter wait_state = 0, line_prep_state = 1, line_state = 2, raster_state = 3;
74
 
75
assign eps_delta_minor = eps+delta_minor;
76
 
77
always@(posedge clk_i or posedge rst_i)
78
if(rst_i)
79
  state <= wait_state;
80
else
81
  case (state)
82
 
83
    wait_state:
84
      if(draw_line_i)
85
        state <= line_prep_state; // if request for drawing a line, go to line drawing state
86
 
87
    line_prep_state:
88
      state <= line_state;
89
 
90
    line_state:
91
      state <= raster_state;
92
 
93
    raster_state:
94
      if(!busy_o)
95
        state <= wait_state;
96
 
97
  endcase
98
 
99
wire is_inside_screen = (minor_o >= 0) & (major_o >= -1);
100
reg previously_outside_screen;
101
 
102
always@(posedge clk_i or posedge rst_i)
103
begin
104
  if(rst_i)
105
  begin
106
    minor_slope_positive <= 1'b0;
107
    eps                  <= 1'b0;
108
    major_o              <= 1'b0;
109
    minor_o              <= 1'b0;
110
    busy_o               <= 1'b0;
111
    major_goal           <= 1'b0;
112
    x_major_o            <= 1'b0;
113
    delta_minor          <= 1'b0;
114
    delta_major          <= 1'b0;
115
    valid_o              <= 1'b0;
116
    left_pixel_x         <= 1'b0;
117
    left_pixel_y         <= 1'b0;
118
    right_pixel_x        <= 1'b0;
119
    right_pixel_y        <= 1'b0;
120
    xdiff                <= 1'b0;
121
    ydiff                <= 1'b0;
122
    previously_outside_screen <= 1'b0;
123
  end
124
  else
125
  begin
126
 
127
// ## new magic
128
    // Start a raster line operation 
129
   case (state)
130
 
131
      wait_state:
132
        if(draw_line_i)
133
        begin
134
          // set busy!
135
          previously_outside_screen <= 1'b0;
136
          busy_o  <= 1'b1;
137
          valid_o <= 1'b0;
138
          // check diff in x and y
139
          if(pixel0_x_i > pixel1_x_i)
140
          begin
141
            xdiff         <= pixel0_x_i - pixel1_x_i;
142
 
143
            // pixel0 is greater then pixel1, pixel1 is left of pixel0.
144
            left_pixel_x  <= pixel1_x_i;
145
            left_pixel_y  <= pixel1_y_i;
146
            right_pixel_x <= pixel0_x_i;
147
            right_pixel_y <= pixel0_y_i;
148
 
149
            // check diff for y axis (swapped)
150
            if(pixel1_y_i > pixel0_y_i)
151
            begin
152
              ydiff                <= pixel1_y_i - pixel0_y_i;
153
              minor_slope_positive <= 1'b0;
154
            end
155
            else
156
            begin
157
              ydiff                <= pixel0_y_i - pixel1_y_i;
158
              minor_slope_positive <= 1'b1;
159
            end
160
 
161
          end
162
          else
163
          begin
164
            xdiff         <= pixel1_x_i - pixel0_x_i;
165
 
166
            // pixel1 is greater then pixel0, pixel0 is left of pixel1.
167
            left_pixel_x  <= pixel0_x_i;
168
            left_pixel_y  <= pixel0_y_i;
169
            right_pixel_x <= pixel1_x_i;
170
            right_pixel_y <= pixel1_y_i;
171
 
172
            // check diff for y axis
173
            if(pixel0_y_i > pixel1_y_i)
174
            begin
175
              ydiff                <= pixel0_y_i - pixel1_y_i;
176
              minor_slope_positive <= 1'b0; // the slope is "\" negative
177
            end
178
            else
179
            begin
180
              ydiff                <= pixel1_y_i - pixel0_y_i;
181
              minor_slope_positive <= 1'b1; // the slope is "/" positive
182
            end
183
          end
184
        end
185
 
186
    // Prepare linedrawing
187
      line_prep_state:
188
      begin
189
        if(xdiff > ydiff)
190
        begin // x major axis
191
          x_major_o    <= 1'b1;
192
          delta_major  <= xdiff;
193
          delta_minor  <= ydiff;
194
        end
195
        else
196
        begin // y major axis 
197
          x_major_o    <= 1'b0;
198
          delta_major  <= ydiff;
199
          delta_minor  <= xdiff;
200
        end
201
      end
202
 
203
 
204
      // Rasterize a line between dest_pixel0 and dest_pixel1 (rasterize = generate the pixels)
205
      line_state:
206
      begin
207
          if(x_major_o)
208
          begin
209
            major_o    <= $signed(left_pixel_x[point_width-1:0]);
210
            minor_o    <= $signed(left_pixel_y[point_width-1:0]);
211
            major_goal <= $signed(right_pixel_x[point_width-1:0]);
212
          end
213
          else
214
          begin
215
            major_o    <= $signed(left_pixel_y[point_width-1:0]);
216
            minor_o    <= $signed(left_pixel_x[point_width-1:0]);
217
            major_goal <= $signed(right_pixel_y[point_width-1:0]);
218
          end
219
          eps          <= 1'b0;
220
          busy_o       <= 1'b1;
221
          valid_o      <= (left_pixel_x >= 0 && left_pixel_y >= 0);
222
 
223
          previously_outside_screen <= ~(left_pixel_x >= 0 && left_pixel_y >= 0);
224
      end
225
 
226
    raster_state:
227
    begin
228
      // pixels is now valid!           
229
      valid_o <= (previously_outside_screen | read_pixel_i) & is_inside_screen;
230
 
231
      previously_outside_screen <= ~is_inside_screen;
232
 
233
      //bresenham magic
234
      if((read_pixel_i & is_inside_screen) | previously_outside_screen)
235
      begin
236
        if((major_o < major_goal) & minor_slope_positive & x_major_o & busy_o) // if we are between endpoints and want to draw a line, continue
237
        begin
238
          major_o   <=  major_o + 1'b1; // major axis increeses
239
 
240
          if((eps_delta_minor*2) >= $signed(delta_major))
241
          begin
242
            eps     <=  eps_delta_minor - delta_major;
243
            minor_o <=  minor_o + 1'b1; // minor axis increeses
244
          end
245
          else
246
            eps     <=  eps_delta_minor;
247
        end
248
        else if((major_o < major_goal) & minor_slope_positive & !x_major_o & busy_o)
249
        begin
250
          major_o   <=  major_o + 1'b1; // major axis increeses
251
 
252
          if((eps_delta_minor*2) >= $signed(delta_major))
253
          begin
254
            eps     <=  eps_delta_minor - delta_major;
255
            minor_o <=  minor_o + 1'b1; // minor axis increeses
256
          end
257
          else
258
            eps     <=  eps_delta_minor;
259
        end
260
        else if((major_o > major_goal) & !minor_slope_positive & !x_major_o & busy_o)// the slope is negative
261
        begin
262
          major_o   <=  major_o - 1'b1; // major axis decreeses
263
 
264
          if((eps_delta_minor*2) >= $signed(delta_major))
265
          begin
266
            eps     <=  eps_delta_minor - delta_major;
267
            minor_o <=  minor_o + 1'b1; // minor axis increeses
268
          end
269
          else
270
            eps     <=  eps_delta_minor;
271
        end
272
        else if((major_o < major_goal) & !minor_slope_positive & x_major_o & busy_o)// special to fix ocant 4 & 8.
273
        begin
274
          major_o   <=  major_o + 1'b1; // major axis increeses
275
 
276
          if((eps_delta_minor*2) >= $signed(delta_major))
277
          begin
278
            eps     <=  eps_delta_minor - delta_major;
279
            minor_o <=  minor_o - 1'b1; // minor axis decreeses
280
          end
281
          else
282
            eps     <=  eps_delta_minor;
283
        end
284
        // if we have reached tho goal and are busy, stop being busy.
285
        else if(busy_o)
286
        begin
287
          busy_o <=  1'b0;
288
          valid_o <= 1'b0;
289
        end
290
      end
291
    end
292
    endcase
293
  end
294
end
295
 
296
endmodule
297
 

powered by: WebSVN 2.1.0

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