-
Notifications
You must be signed in to change notification settings - Fork 0
/
address-gen.v
143 lines (125 loc) · 3.36 KB
/
address-gen.v
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
Designer: Lazaros Athanasiadis
Designed in: Fall Semester 2019-20
Designed for: Digital Systems Lab, 3rd lab assignment (VGA driver)
Description: This module calculates the correct VRAM adress for the current pixel,
as long as the image-source module has outputted source = 1.
*/
module address_generator(clk, reset, frame, hpixel, vpixel, address, select);
input clk, reset;
input [5:0] frame;
input [6:0] hpixel, vpixel;
output [13:0] address;
output select;
reg select;
reg [5:0] old_frame;
//My animation consists of 8 sprites, therefore I need a 3 bit reg to cycle through them
reg [2:0] current_sprite;
/*
My animation's speed will be 10FPS.
My VGA driver works at 60FPS, so, in order to achive 10FPS,
the same frame must be displayed 6 times.
*/
reg [2:0] frame_counter;
reg [6:0] H; //horizontal offset
reg [6:0] V; //vertical offset
//7 most/least significant bits of address
wire [6:0] address_high, address_low;
parameter [2:0] MAX_FRAME = 3'd6; //resulting FPS will be 60/MAX_FRAME
always @(posedge clk or posedge reset) begin
if (reset == 1'b1) begin
frame_counter = 3'b000;
current_sprite = 3'b000;
end
else begin
old_frame <= frame;
if (old_frame != frame) begin
//frame changed
frame_counter = frame_counter + 3'b1;
end
if (frame_counter == MAX_FRAME) begin
//time to change the displayed sprite
frame_counter = 3'd0;
current_sprite = current_sprite + 3'b1;
end
/*
First set of block RAMs has the first 6 sprites, while the second
set has the last 2.
The sprites are stored left-to-right, top-to-bottom.
All offsets are in regard of the first pixel (leftmost of first row)
of the first sprite.
So each for each sprite that was displayed in the same row, the horizontal
offset must be incremented by 42, while the bottom sprites have a
vertical offset of 48.
*/
case (current_sprite)
3'd0:
begin
H = 7'd0; //no offsets
V = 6'd0;
//first 6 sprites are stored in the first set of block RAMs
select = 1'b0;
end
3'd1:
begin
H = 7'd42; //
V = 6'd0;
end
3'd2:
begin
H = 7'd84;
V = 6'd0;
end
3'd3:
begin
H = 7'd0;
V = 6'd48;
end
3'd4:
begin
H = 7'd42;
V = 6'd48;
end
3'd5:
begin
H = 7'd84;
V = 6'd48;
end
//same as case 0, since this is the same position at the second atlas
3'd6:
begin
H = 7'd0;
V = 6'd0;
//last 2 sprites are stored in the second set of block RAMs
select = 1'b1;
end
//same as case 1, since this is the same position at the second atlas
3'd7:
begin
H = 7'd42;
V = 6'd0;
end
endcase
end
end
/*
I subtract 23 from vpixel and 42 from hpixel to align the displayed sprite with
point A, which is the start of the box in which the sprites are displayed
<---------128-------->
43 42 43
<---><----------><--->
^ +--------------------+ ^
|24 | | |
v | A(42,23) | |
^ | +----------+ | |
|48 | | | | | 96
| | | | | |
v | +----------+ | |
^ | | |
|24 | | |
v +--------------------+ v
*/
assign address_low = hpixel - 6'd42 + H;
assign address_high = vpixel - 6'd23 + V;
assign address = {address_high,address_low};
endmodule