-
Notifications
You must be signed in to change notification settings - Fork 10
/
mist_video.v
219 lines (192 loc) · 5.75 KB
/
mist_video.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
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
// A video pipeline for MiST. Just insert between the core video output and the VGA pins
// Provides an optional scandoubler, a rotateable OSD and (optional) RGb->YPbPr conversion
module mist_video
(
// master clock
// it should be 4x (or 2x) pixel clock for the scandoubler
input clk_sys,
// OSD SPI interface
input SPI_SCK,
input SPI_SS3,
input SPI_DI,
// scanlines (00-none 01-25% 10-50% 11-75%)
input [1:0] scanlines,
// non-scandoubled pixel clock divider:
// 0 - clk_sys/4, 1 - clk_sys/2, 2 - clk_sys/3, 3 - clk_sys/4, etc
input [2:0] ce_divider,
// 0 = HVSync 31KHz, 1 = CSync 15KHz
input scandoubler_disable,
// disable csync without scandoubler
input no_csync,
// YPbPr always uses composite sync
input ypbpr,
// Rotate OSD [0] - rotate [1] - left or right
input [1:0] rotate,
// composite-like blending
input blend,
// video in
input [COLOR_DEPTH-1:0] R,
input [COLOR_DEPTH-1:0] G,
input [COLOR_DEPTH-1:0] B,
input HBlank,
input VBlank,
input HSync,
input VSync,
// MiST video output signals
output reg [OUT_COLOR_DEPTH-1:0] VGA_R,
output reg [OUT_COLOR_DEPTH-1:0] VGA_G,
output reg [OUT_COLOR_DEPTH-1:0] VGA_B,
output reg VGA_VS,
output reg VGA_HS,
output reg VGA_HB,
output reg VGA_VB,
output reg VGA_DE
);
parameter OSD_COLOR = 3'd4;
parameter OSD_X_OFFSET = 10'd0;
parameter OSD_Y_OFFSET = 10'd0;
parameter SD_HCNT_WIDTH = 9;
parameter COLOR_DEPTH = 6; // 1-8
parameter OSD_AUTO_CE = 1'b1;
parameter SYNC_AND = 1'b0; // 0 - XOR, 1 - AND
parameter USE_BLANKS = 1'b0; // Honor H/VBlank signals?
parameter SD_HSCNT_WIDTH = 12;
parameter OUT_COLOR_DEPTH = 6; // 1-8
parameter BIG_OSD = 1'b0; // 16 line OSD
parameter VIDEO_CLEANER = 1'b0; // Align VSync/VBlank to HSync/HBlank edges. HDMI usually needs it.
wire [OUT_COLOR_DEPTH-1:0] SD_R_O;
wire [OUT_COLOR_DEPTH-1:0] SD_G_O;
wire [OUT_COLOR_DEPTH-1:0] SD_B_O;
wire SD_HS_O;
wire SD_VS_O;
wire SD_HB_O;
wire SD_VB_O;
wire pixel_ena;
scandoubler #(SD_HCNT_WIDTH, COLOR_DEPTH, SD_HSCNT_WIDTH, OUT_COLOR_DEPTH) scandoubler
(
.clk_sys ( clk_sys ),
.bypass ( scandoubler_disable ),
.ce_divider ( {1'b0, ce_divider} ),
.scanlines ( scanlines ),
.pixel_ena ( pixel_ena ),
.hb_in ( HBlank ),
.vb_in ( VBlank ),
.hs_in ( HSync ),
.vs_in ( VSync ),
.r_in ( R ),
.g_in ( G ),
.b_in ( B ),
.hb_out ( SD_HB_O ),
.vb_out ( SD_VB_O ),
.hs_out ( SD_HS_O ),
.vs_out ( SD_VS_O ),
.r_out ( SD_R_O ),
.g_out ( SD_G_O ),
.b_out ( SD_B_O )
);
wire [OUT_COLOR_DEPTH-1:0] osd_r_o;
wire [OUT_COLOR_DEPTH-1:0] osd_g_o;
wire [OUT_COLOR_DEPTH-1:0] osd_b_o;
osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR, OSD_AUTO_CE, USE_BLANKS, OUT_COLOR_DEPTH, BIG_OSD) osd
(
.clk_sys ( clk_sys ),
.rotate ( rotate ),
.ce ( pixel_ena ),
.SPI_DI ( SPI_DI ),
.SPI_SCK ( SPI_SCK ),
.SPI_SS3 ( SPI_SS3 ),
.R_in ( SD_R_O ),
.G_in ( SD_G_O ),
.B_in ( SD_B_O ),
.HBlank ( SD_HB_O ),
.VBlank ( SD_VB_O ),
.HSync ( SD_HS_O ),
.VSync ( SD_VS_O ),
.R_out ( osd_r_o ),
.G_out ( osd_g_o ),
.B_out ( osd_b_o )
);
wire [OUT_COLOR_DEPTH-1:0] cofi_r, cofi_g, cofi_b;
wire cofi_hs, cofi_vs;
wire cofi_hb, cofi_vb;
wire cofi_pixel_ena;
cofi #(OUT_COLOR_DEPTH) cofi (
.clk ( clk_sys ),
.pix_ce ( pixel_ena ),
.enable ( blend ),
.hblank ( USE_BLANKS ? SD_HB_O : ~SD_HS_O ),
.vblank ( SD_VB_O ),
.hs ( SD_HS_O ),
.vs ( SD_VS_O ),
.red ( osd_r_o ),
.green ( osd_g_o ),
.blue ( osd_b_o ),
.hs_out ( cofi_hs ),
.vs_out ( cofi_vs ),
.hblank_out( cofi_hb ),
.vblank_out( cofi_vb ),
.red_out ( cofi_r ),
.green_out( cofi_g ),
.blue_out( cofi_b ),
.pix_ce_out(cofi_pixel_ena)
);
wire [OUT_COLOR_DEPTH-1:0] cleaner_r_o;
wire [OUT_COLOR_DEPTH-1:0] cleaner_g_o;
wire [OUT_COLOR_DEPTH-1:0] cleaner_b_o;
wire cleaner_hs_o, cleaner_vs_o, cleaner_hb_o, cleaner_vb_o;
video_cleaner #(OUT_COLOR_DEPTH) video_cleaner(
.clk_vid ( clk_sys ),
.ce_pix ( scandoubler_disable ? 1'b1 : cofi_pixel_ena ),
.enable ( VIDEO_CLEANER ),
.R ( cofi_r ),
.G ( cofi_g ),
.B ( cofi_b ),
.HSync ( cofi_hs ),
.VSync ( cofi_vs ),
.HBlank ( cofi_hb ),
.VBlank ( cofi_vb ),
.VGA_R ( cleaner_r_o ),
.VGA_G ( cleaner_g_o ),
.VGA_B ( cleaner_b_o ),
.VGA_VS ( cleaner_vs_o),
.VGA_HS ( cleaner_hs_o),
.HBlank_out ( cleaner_hb_o),
.VBlank_out ( cleaner_vb_o)
);
wire hs, vs, cs;
wire hb, vb;
wire [OUT_COLOR_DEPTH-1:0] r,g,b;
RGBtoYPbPr #(OUT_COLOR_DEPTH) rgb2ypbpr
(
.clk ( clk_sys ),
.ena ( ypbpr ),
.red_in ( cleaner_r_o ),
.green_in ( cleaner_g_o ),
.blue_in ( cleaner_b_o ),
.hs_in ( cleaner_hs_o ),
.vs_in ( cleaner_vs_o ),
.cs_in ( SYNC_AND ? (cleaner_hs_o & cleaner_vs_o) : ~(cleaner_hs_o ^ cleaner_vs_o) ),
.hb_in ( cleaner_hb_o ),
.vb_in ( cleaner_vb_o ),
.red_out ( r ),
.green_out ( g ),
.blue_out ( b ),
.hs_out ( hs ),
.vs_out ( vs ),
.cs_out ( cs ),
.hb_out ( hb ),
.vb_out ( vb )
);
always @(posedge clk_sys) begin
VGA_R <= r;
VGA_G <= g;
VGA_B <= b;
// a minimig vga->scart cable expects a composite sync signal on the VGA_HS output.
// and VCC on VGA_VS (to switch into rgb mode)
VGA_HS <= ((~no_csync & scandoubler_disable) || ypbpr)? cs : hs;
VGA_VS <= ((~no_csync & scandoubler_disable) || ypbpr)? 1'b1 : vs;
VGA_HB <= hb;
VGA_VB <= vb;
VGA_DE <= ~(hb | vb);
end
endmodule