-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdisplay_output.sv
180 lines (154 loc) · 3.84 KB
/
display_output.sv
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
// VGA Hardware Driver
// Does timing for a VGA monitor at 25Mhz for 640x480 resolution
//
// Outputs current x and y values that are being drawn so that other
// logic can determine what color should happen at that time
module display_output (clk, reset, VGA_HS, VGA_VS, x, y, draw, VGA_BLANK_N, VGA_SYNC_N, VGA_CLK);
output VGA_BLANK_N, VGA_SYNC_N, VGA_CLK;
//VGA digital to analog coverter here http://www.eecg.toronto.edu/~tm4/ADV7123_a.pdf
assign VGA_BLANK_N = 1'b1;
assign VGA_SYNC_N = 1'b0;
assign VGA_CLK = clk;
input clk, reset;
output reg VGA_HS, VGA_VS;
output reg draw;
output [9:0] x, y;
wire [9:0] HS_counter, VS_counter;
assign x = HS_counter;
assign y = VS_counter;
reg HS_increment, VS_increment;
reg HS_reset;
reg VS_reset;
reg [2:0] ps_h, ns_h;
reg [2:0] ps_v, ns_v;
counter HS (.clk, .reset(HS_reset | reset), .add(HS_increment), .out(HS_counter));
counter VS (.clk, .reset(VS_reset | reset), .add(VS_increment), .out(VS_counter));
//Vertical Sync Timings for 25Mhz, could be changed slightly and still work R_cycle is important
parameter [9:0] R_cycle = 480, S_cycle = R_cycle + 10, P_cycle = S_cycle + 2, Q_cycle = P_cycle + 33;
//Horizontal Sync Timings for 25Mhz, could be changed slightly and still work R_cycle is important
parameter [9:0] D_cycle = 640, E_cycle = D_cycle + 15, B_cycle = E_cycle + 95, C_cycle = B_cycle + 48;
parameter [3:0] P = 0, Q = 1, R = 2, S = 3;
parameter [3:0] B = 0, C = 1, D = 2, E = 3;
//Two state machines, when VS is in the R state and HS is in the D state "draw" is true
//We output the HS and VS state as when HS < 640 and VS <480 HS and VS represent the current pixel to be drawn.
//Logic outside this module decide what color that pixel should be
always @(*) begin
HS_increment = 1'b1;
if(HS_counter == C_cycle) begin
VS_increment = 1'b1;
HS_reset = 1'b1;
if(VS_counter == Q_cycle - 1) begin
VS_reset = 1'b1;
end
else begin
VS_reset = 1'b0;
end
end
else begin
VS_increment = 1'b0;
HS_reset = 1'b0;
VS_reset = 1'b0;
end
case(ps_v)
P: begin
VGA_VS = 1'b0;
if(VS_counter == P_cycle - 1)
ns_v = Q;
else
ns_v = P;
end
Q: begin
VGA_VS = 1'b1;
if(VS_counter == Q_cycle - 1)
ns_v = R;
else
ns_v = Q;
end
R: begin
VGA_VS = 1'b1;
if(VS_counter == R_cycle - 1)
ns_v = S;
else
ns_v = R;
end
S: begin
VGA_VS = 1'b1;
if(VS_counter == S_cycle - 1)
ns_v = P;
else
ns_v = S;
end
endcase
case(ps_h)
B: begin
VGA_HS = 1'b0;
draw = 1'b0;
if(HS_counter == B_cycle - 1)
ns_h = C;
else
ns_h = B;
end
C: begin
VGA_HS = 1'b1;
draw = 1'b0;
if(HS_counter == C_cycle - 1)
ns_h = D;
else
ns_h = C;
end
D: begin
if(ps_v == R) begin
draw = 1'b1;
end
else begin
draw = 1'b0;
end
VGA_HS = 1'b1;
if(HS_counter == D_cycle - 1)
ns_h = E;
else
ns_h = D;
end
E: begin
draw = 1'b0;
VGA_HS = 1'b1;
if(HS_counter == E_cycle - 1)
ns_h = B;
else
ns_h = E;
end
endcase
end
always @(posedge clk) begin
if (reset) begin
ps_h <= D;
ps_v <= R;
end
else begin
ps_h <= ns_h;
if(HS_counter == C_cycle - 1)
ps_v <= ns_v;
end
end
endmodule
module display_output_testbench();
reg clk, reset;
reg [7:0] VGA_R, VGA_G, VGA_B;
wire VGA_HS ,VGA_VS;
display_output duct (.clk,. reset, .VGA_HS, .VGA_VS);
parameter CLOCK_PERIOD=40;
initial clk=1;
always begin
#(CLOCK_PERIOD/2);
clk = ~clk;
end
initial begin
reset <= 0;
@(posedge clk);
reset <= 1;
@(posedge clk);
reset <= 0;
#(CLOCK_PERIOD*1000000);
$stop;
end
endmodule