1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
`define VGA_W 160
`define VGA_H 120
module circle(clk, rst_n, colour, centre_x, centre_y, radius, start, done,
vga_x, vga_y, vga_colour, vga_plot);
input logic clk, rst_n, start;
input logic [2:0] colour;
input logic [6:0] centre_y;
input logic [7:0] centre_x, radius;
output logic done, vga_plot;
output logic [2:0] vga_colour;
output logic [6:0] vga_y;
output logic [7:0] vga_x;
logic clear;
logic [2:0] octant;
logic [7:0] offset_x, offset_y, offset_x_next, offset_y_next;
/* One bit larger since these are signed. */
logic signed [7:0] vga_y_next;
logic signed [8:0] vga_x_next, crit, crit_next;
assign vga_colour = colour;
always_comb case (octant)
3'd0: begin
vga_x_next = centre_x + offset_x;
vga_y_next = centre_y + offset_y;
end
3'd1: begin
vga_x_next = centre_x + offset_y;
vga_y_next = centre_y + offset_x;
end
3'd2: begin
vga_x_next = centre_x - offset_y;
vga_y_next = centre_y + offset_x;
end
3'd3: begin
vga_x_next = centre_x - offset_x;
vga_y_next = centre_y + offset_y;
end
3'd4: begin
vga_x_next = centre_x - offset_x;
vga_y_next = centre_y - offset_y;
end
3'd5: begin
vga_x_next = centre_x - offset_y;
vga_y_next = centre_y - offset_x;
end
3'd6: begin
vga_x_next = centre_x + offset_y;
vga_y_next = centre_y - offset_x;
end
3'd7: begin
vga_x_next = centre_x + offset_x;
vga_y_next = centre_y - offset_y;
end
endcase
always_comb begin
offset_x_next = offset_x;
offset_y_next = offset_y + 1;
if (crit <= 0)
crit_next = crit + 2 * offset_y_next + 1;
else begin
offset_x_next = offset_x - 1;
crit_next = crit
+ 2 * (offset_y_next - offset_x_next) + 1;
end
end
always_ff @(posedge clk) begin
if (rst_n !== 1) begin
done <= 1'b0;
/* Initialise the registers for the circle algorithm. */
vga_x <= 8'b0;
vga_y <= 7'b0;
vga_plot <= 1'b0;
octant <= 3'b0;
offset_y <= 8'b0;
offset_x <= radius;
crit <= 1 - radius;
end
/* Draw the circle using the Bresenham circle algorithm. */
if (start && ~done) begin
if (offset_y <= offset_x) begin
if ((vga_x_next >= 0) && (vga_x_next <= `VGA_W))
vga_x <= vga_x_next;
if ((vga_y_next >= 0) && (vga_y_next <= `VGA_H))
vga_y <= vga_y_next;
/* Plot only within the monitor's geometry. */
vga_plot <= ((vga_x_next >= 0)
&& (vga_x_next <= `VGA_W)
&& (vga_y_next >= 0)
&& (vga_y_next <= `VGA_H));
octant <= octant + 1;
/* The last octant. */
if (octant == 7) begin
offset_x <= offset_x_next;
offset_y <= offset_y_next;
crit <= crit_next;
end
/* Finished. */
end else begin
done <= 1'b1;
vga_plot <= 1'b0;
end
/* Wait for start to be deasserted. */
end else if (~start && done)
done <= 1'b0;
end
endmodule
|