-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGPUModule.sv
More file actions
322 lines (286 loc) · 7.31 KB
/
Copy pathGPUModule.sv
File metadata and controls
322 lines (286 loc) · 7.31 KB
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
module GPU(
// Synchronization
input logic Clock,
input logic Reset,
// VGA In-Out
output logic hsync,
output logic vsync,
output logic[7:0] red,
output logic[7:0] green,
output logic[7:0] blue,
output logic PxClock,
output logic Blank,
output logic Sync,
// Video RAM Access
output logic[19:0] RAMAddress,
inout wire [15:0] RAMData,
output logic RAMHB,
output logic RAMLB,
output logic RAMOE,
output logic RAMWE,
output logic RAMCE,
// Bus Interface
input logic [32:0] BusAddress,
inout logic [32:0] BusData,
input logic DataRead,
input logic DataWrite
);
// Local Register Addresses:
localparam LowerWordInstructionAddress = 1024;
localparam MidWordInstructionAddress = 1025;
localparam UpperWordInstructionAddress = 1026;
// VGA timings https://timetoexplore.net/blog/video-timings-vga-720p-1080p
localparam HS_STA = 16; // horizontal sync start
localparam HS_END = 16 + 96; // horizontal sync end
localparam HA_STA = 16 + 96 + 48; // horizontal active pixel start
localparam VS_STA = 480 + 10; // vertical sync start
localparam VS_END = 480 + 10 + 2; // vertical sync end
localparam VA_END = 480; // vertical active pixel end
localparam LINE = 800; // complete line (pixels)
localparam SCREEN = 525; // complete screen (lines)
reg [9:0] h_count; // line position
reg [9:0] v_count; // screen position
logic [31:0] LowerWordInstruction,
MidWordInstruction,
UpperWordInstruction;
logic Ready,Valid,ReadInstruction;
assign Ready = ~(PixelListLength==64);
logic [95:0] Instructions[0:15];
logic [3:0] InstructionCount;
//Current State signals
logic Active, //Active when Output active pixels
ReadTime, //Active when fetching data from RAM
WriteTime, //Active when can write data to RAM
PixelClock, //VGA Controller Pixel Clock
WriteDataAvailable; //Active when there are data to be written to RAM
// Pixel x and y
logic [9:0] x;
logic [8:0] y;
logic old_DataWrite;
always_ff @ (posedge Clock)
begin
old_DataWrite<=DataWrite;
end
logic [42:0] PixelInstructions[0:63];
logic [42:0] NewPixelInstruction;
logic [5:0] PixelListLength;
logic WritePixel,RGBWriteSeq;
logic [7:0] RedOut, //Current Red Output
GreenOut, //Current Green Output
BlueOut, //Current Blue Output
RedNext,
GreenNext;
logic [19:0] ReadAddress,
WriteAddress;
logic [15:0] WriteData;
assign PxClock=PixelClock;
// ReadAddress from RAM for pixel x,y (leading 0 for Red and Green, 1 for Blue)
assign ReadAddress[19] = ~PixelClock;
assign ReadAddress[18:10] = y;
assign ReadAddress[9:0] = x;
// Write function not implemented yet
assign WriteDataAvailable = ~(PixelListLength==0) ;
assign WriteAddress = {RGBWriteSeq,PixelInstructions[0][42:34],PixelInstructions[0][33:24]};
assign WriteData = RGBWriteSeq ? PixelInstructions[0][23:8] : {PixelInstructions[0][7:0],8'b00000000};
// Output RGA color to VGA controller
assign red=RedOut;
assign green=GreenOut;
assign blue=BlueOut;
// generate sync signals (active low for 640x480)
assign hsync = ~((h_count >= HS_STA) & (h_count < HS_END));
assign vsync = ~((v_count >= VS_STA) & (v_count < VS_END));
assign Sync=1;
// keep x and y bound within the active pixels
assign x = (h_count < HA_STA) ? 0 : (h_count - HA_STA);
assign y = (v_count >= VA_END) ? (VA_END - 1) : (v_count);
// blanking: high within the blanking period
assign Blank = ~((h_count < HA_STA) | (v_count > VA_END - 1));
// active: high during active pixel drawing
assign Active = ~((h_count < HA_STA) | (v_count > VA_END - 1));
assign ReadTime = (h_count > HA_STA - 1) & (v_count < VA_END -1);
assign WriteTime = ~ReadTime & WriteDataAvailable;
assign RAMData = ReadTime ? {16{1'bz}} :
WriteTime ? WriteData :
{16{1'bz}} ;
GPU_Core Core0(
.Clock(Clock),
.Reset(Reset),
.Instruction(Instructions[0]),
.ReadInstruction(ReadInstruction),
.InstructionValid(Valid),
.PixelInstruction(NewPixelInstruction),
.WriteInstruction(WritePixel),
.Ready(Ready)
);
always_ff @(posedge Clock)
begin
if(Reset)
begin
InstructionCount<=0;
end
else
if(BusAddress==LowerWordInstructionAddress && DataWrite && ~old_DataWrite)
begin
LowerWordInstruction<=BusData;
end
else
if(BusAddress==MidWordInstructionAddress && DataWrite && ~old_DataWrite)
begin
MidWordInstruction<=BusData;
end
else
if(BusAddress==UpperWordInstructionAddress && DataWrite && ~old_DataWrite)
begin
UpperWordInstruction<=BusData;
if(~(InstructionCount==16))
begin
if(~(ReadInstruction && ~(InstructionCount==0)))
begin
Instructions[InstructionCount]<={LowerWordInstruction,MidWordInstruction,UpperWordInstruction};
InstructionCount<=InstructionCount+1;
end
else
begin
Instructions[0:14]<=Instructions[1:15];
Instructions[InstructionCount-1]<={LowerWordInstruction,MidWordInstruction,UpperWordInstruction};
end
end
end
else
if(ReadInstruction && ~(InstructionCount==0))
begin
Instructions[0:14]<=Instructions[1:15];
InstructionCount<=InstructionCount-1;
end
end
always_ff @ (posedge Clock)
begin
if(Reset)
begin
PixelListLength<=0;
end
if(WriteTime && RGBWriteSeq)
begin
if(WritePixel)
begin
PixelInstructions[0:62]<=PixelInstructions[1:63];
PixelInstructions[PixelListLength-1]<=NewPixelInstruction;
end
else
begin
PixelListLength<=PixelListLength-1;
PixelInstructions[0:62]<=PixelInstructions[1:63];
end
end
else
begin
if(WritePixel && ~(PixelListLength==64))
begin
PixelInstructions[0:62]<=PixelInstructions[1:63];
PixelInstructions[PixelListLength]<=NewPixelInstruction;
PixelListLength<=PixelListLength+1;
end
end
end
always_ff @ (posedge Clock)
begin
if(Reset)
begin
RGBWriteSeq<=0;
end
else
begin
if(WriteTime)
begin
RGBWriteSeq<=~RGBWriteSeq;
end
end
end
always_comb
begin
//RAM signals
RAMCE = 0;
RAMLB = 0;
RAMHB = 0;
if(ReadTime)
begin
RAMOE = 0;
RAMAddress = ReadAddress;
RAMWE = 1;
end
else
if(WriteTime)
begin
RAMOE = 1;
RAMAddress = WriteAddress;
RAMWE = Clock; //Prepare Data when clock is high write data on transition 1 -> 0 move on on transition 0 -> 1
end
else
begin
RAMOE = 1;
RAMAddress = 0;
RAMWE = 1;
end
end
always_ff @ (negedge Clock)
begin
if(Reset)
begin
RedOut<=0;
GreenOut<=0;
BlueOut<=0;
RedNext<=0;
GreenNext<=0;
end
if(ReadTime) //If it's reading phase
begin
if(PixelClock) //Reading Red, Green and Blue
begin
RedNext<=RAMData[15:8];
GreenNext<=RAMData[7:0];
end
else
begin
RedOut<=RedNext;
GreenOut<=GreenNext;
BlueOut<=RAMData[15:8];
end
end
end
always_ff @ (posedge Clock)
begin
if(Reset)
begin
PixelClock<=0;
end
else
begin
PixelClock<=~PixelClock;
end
end
always_ff @ (posedge Clock)
begin
if (Reset) // reset to start of frame
begin
h_count <= 0;
v_count <= 0;
end
else
begin
if (~PixelClock) // once per pixel
begin
if (h_count == LINE) // end of line
begin
h_count <= 0;
v_count <= v_count + 1;
end
else
begin
h_count <= h_count + 1;
if (v_count == SCREEN) // end of screen
v_count <= 0;
end
end
end
end
endmodule