Add Wishbone datasheets
[AGH_computer_science_engineering_thesis.git] / design / vga.v
blob5e42866972feb9fa06181cf6bb117631a5adcf9e
1 /*
2 * | *WISHBONE DATASHEET* |
3 * |---------------------------------------------------------------------------|
4 * | *Description* | *Specification* |
5 * |---------------------------------+-----------------------------------------|
6 * | General description | VGA signal generator (640x480@60Hz) |
7 * |---------------------------------+-----------------------------------------|
8 * | Supported cycles | SLAVE, pipelined READ/WRITE |
9 * |---------------------------------+-----------------------------------------|
10 * | Data port, size | 16-bit |
11 * | Data port, granularity | 16-bit |
12 * | Data port, maximum operand size | 16-bit |
13 * | Data transfer ordering | Big endian and/or little endian |
14 * | Data transfer ordering | Undefined |
15 * | Address port, size | 11-bit |
16 * |---------------------------------+-----------------------------------------|
17 * | Clock frequency constraints | NONE (determined by memory primitive, |
18 * | | about 100 MHz in case of iCE40HX8K) |
19 * |---------------------------------+-----------------------------------------|
20 * | | *Signal name* | *WISHBONE Equiv.* |
21 * | |------------------+----------------------|
22 * | | ACK_O | ACK_O |
23 * | | ADR_I | ADR_I() |
24 * | Supported signal list and cross | CLK_I | CLK_I |
25 * | reference to equivalent | DAT_I | DAT_I() |
26 * | WISHBONE signals | DAT_O | DAT_O() |
27 * | | STB_I | STB_I |
28 * | | WE_I | WE_I |
29 * | | RST_I | RST_I |
30 * | | STALL_O | STALL_O |
31 * |---------------------------------+-----------------------------------------|
32 * | | Circuit assumes the use of synchronous |
33 * | Special requirements | RAM with asynchronour read |
34 * | | inreffable by synthesis software. |
35 * |---------------------------------+-----------------------------------------|
36 * | | Module provides a simple text mode, |
37 * | | that can be used to display 30 lines of |
38 * | | 80 characters each. Module can be used |
39 * | | as follows: |
40 * | Additional information | * ASCII values of characters to |
41 * | | display should be written to text |
42 * | | mode memory. |
43 * | | * A non-zero value should be |
44 * | | written to the "power-on" |
45 * | | register to start generating VGA |
46 * | | signal. |
47 * | | * Zero should be written to the |
48 * | | "power-on" register to stop |
49 * | | generating VGA output. |
50 * | | Also see the memory map below. |
51 * | | The "power-on" register can be |
52 * | | read at any time to check if VGA |
53 * | | output is being generated. It reads |
54 * | | a non-zero value if module is |
55 * | | operating and zero otherwise. |
56 * | | Each byte of the text mode memory |
57 * | | corresponds to one character on |
58 * | | video display. They are arranged by |
59 * | | rows, from up to down. I.e. writing |
60 * | | value 65 to the first 2 bytes of |
61 * | | text video memory shall result in |
62 * | | character "A" being printed in 2 |
63 * | | leftmost fields of the topmost line |
64 * | | of the display. Writing a byte |
65 * | | value outside ASCII range shall |
66 * | | result in a replacement character |
67 * | | being written. Text mode memory is |
68 * | | 2560 bytes big. The last 160 bytes |
69 * | | are not used by video display and |
70 * | | don't serve any special purpose. |
71 * | | The font used for ASCII characters |
72 * | | is defined in an external file and |
73 * | | can be substituted. |
77 * The memory map is as follows:
78 * h000 - h4FF - VGA text memory
79 * h500 - VGA power-on reg
81 * Accessing higher addresses than specified results in UNDEFINED behavior.
84 `default_nettype none
86 module vga
88 parameter FONT_FILE = "font.mem"
91 output wire ACK_O,
92 input wire CLK_I,
93 input wire [10:0] ADR_I,
94 input wire [15:0] DAT_I,
95 output wire [15:0] DAT_O,
96 input wire RST_I,
97 input wire STB_I,
98 input wire WE_I,
99 output wire STALL_O,
101 /* Non-wishbone */
102 input wire clock_25mhz,
103 output wire h_sync,
104 output wire v_sync,
105 output wire [2:0] red,
106 output wire [2:0] green,
107 output wire [2:0] blue
110 reg powered_on;
112 parameter LINES = V_ACTIVE_VIDEO / 16; /* 30 */
113 parameter LINE_LENGTH = H_ACTIVE_VIDEO / 8; /* 80 */
114 parameter CHARACTERS_ON_SCREEN = LINE_LENGTH * LINES; /* 2400 */
117 * We want to store 2400 characters in memory. 2 chars go into one 16-bit
118 * word, so wee need a 1200x16 array. One embedded RAM block in iCE40 FPGAs
119 * is able to store 256x16 bits. This means, instead of choosing 1200 as
120 * array size, we can choose 1280, which is a multiple of 256.
122 reg [15:0] text_memory [1279 : 0];
124 /* Enable writes and reads of text_memory using wishbone interface. */
126 reg [15:0] data_at_adr;
127 reg outputting_data;
128 reg ack;
130 assign DAT_O = outputting_data ? data_at_adr : {16{powered_on}};
131 assign ACK_O = ack;
132 assign STALL_O = 1'b0;
134 always @ (posedge CLK_I) begin
135 ack <= STB_I && !RST_I;
137 if (STB_I && WE_I) begin
138 if (ADR_I < 1280)
139 text_memory[ADR_I] <= DAT_I;
140 else
141 powered_on <= DAT_I != 16'b0;
144 outputting_data <= ADR_I < 1280;
146 data_at_adr <= text_memory[ADR_I];
149 /* Non-wishbone part - generate 640x480 60Hz VGA output */
151 reg powered_on_latched;
153 always @ (posedge clock_25mhz)
154 powered_on_latched <= powered_on;
156 parameter H_POLARITY = 1'b0;
157 parameter H_FRONT_PORCH = 8;
158 parameter H_SYNC = 96;
159 parameter H_BACK_PORCH = 40;
160 parameter H_LEFT_BORDER = 8;
161 parameter H_ACTIVE_VIDEO = 640;
162 parameter H_RIGHT_BORDER = 8;
164 reg [9:0] h_counter;
166 parameter H_STAGE_RB_OR_FP = 0; /* right border of front porch */
167 parameter H_STAGE_SYNC = 1;
168 parameter H_STAGE_BP_OR_LB = 2; /* back porch or left border */
169 parameter H_STAGE_ACTIVE_VIDEO = 3;
171 reg [1:0] h_stage;
173 always @ (posedge clock_25mhz) begin
174 if (powered_on_latched) begin
175 if ((h_stage == H_STAGE_RB_OR_FP &&
176 h_counter + 1 == H_RIGHT_BORDER + H_FRONT_PORCH) ||
177 (h_stage == H_STAGE_SYNC &&
178 h_counter + 1 == H_SYNC) ||
179 (h_stage == H_STAGE_BP_OR_LB &&
180 h_counter + 1 == H_BACK_PORCH + H_LEFT_BORDER) ||
181 (h_stage == H_STAGE_ACTIVE_VIDEO &&
182 h_counter + 1 == H_ACTIVE_VIDEO)) begin
183 h_stage <= h_stage + 1;
184 h_counter <= 0;
185 end else begin // if ((h_stage == H_STAGE_RB_OR_FP &&...
186 h_counter <= h_counter + 1;
188 end else begin // if (powered_on_latched)
189 h_stage <= H_STAGE_RB_OR_FP;
190 h_counter <= H_RIGHT_BORDER - 1;
191 end // else: !if(powered_on_latched)
192 end // always @ (posedge clock_25mhz)
194 wire end_of_line;
195 assign end_of_line = h_stage == H_STAGE_RB_OR_FP &&
196 h_counter + 1 == H_RIGHT_BORDER;
198 parameter V_POLARITY = 1'b1;
199 parameter V_FRONT_PORCH = 2;
200 parameter V_SYNC = 2;
201 parameter V_BACK_PORCH = 25;
202 parameter V_TOP_BORDER = 8;
203 parameter V_ACTIVE_VIDEO = 480;
204 parameter V_BOTTOM_BORDER = 8;
206 reg [8:0] v_counter;
208 parameter V_STAGE_BB_OR_FP = 0; /* bottom border of front porch */
209 parameter V_STAGE_SYNC = 1;
210 parameter V_STAGE_BP_OR_TB = 2; /* back porch or top border */
211 parameter V_STAGE_ACTIVE_VIDEO = 3;
213 reg [1:0] v_stage;
215 always @ (posedge clock_25mhz) begin
216 if (powered_on_latched) begin
217 if (end_of_line) begin
218 if ((v_stage == V_STAGE_BB_OR_FP &&
219 v_counter + 1 == V_BOTTOM_BORDER + V_FRONT_PORCH) ||
220 (v_stage == V_STAGE_SYNC &&
221 v_counter + 1 == V_SYNC) ||
222 (v_stage == V_STAGE_BP_OR_TB &&
223 v_counter + 1 == V_BACK_PORCH + V_TOP_BORDER) ||
224 (v_stage == V_STAGE_ACTIVE_VIDEO &&
225 v_counter + 1 == V_ACTIVE_VIDEO)) begin
226 v_stage <= v_stage + 1;
227 v_counter <= 0;
228 end else begin // if ((v_stage == V_STAGE_BB_OR_FP &&...
229 v_counter <= v_counter + 1;
231 end // if (end_of_line)
232 end else begin // if (powered_on_latched)
233 v_stage <= V_STAGE_BB_OR_FP;
234 v_counter <= V_BOTTOM_BORDER;
235 end // else: !if(powered_on_latched)
236 end // always @ (posedge clock_25mhz)
238 reg [0:7] font [128 * 16 - 1 : 0];
240 /* Should result in initialization of embedded RAM */
241 initial begin
242 $readmemb(FONT_FILE, font, 0, 128 * 16 - 1);
245 parameter FG_COLOR = {3'b010, 3'b111, 3'b101};
246 parameter BG_COLOR = {3'b000, 3'b000, 3'b111};
248 /* display this for non-ascii characters */
249 wire [0:7] replacement_char [0:16];
250 assign replacement_char[0] = 8'b00000000;
251 assign replacement_char[1] = 8'b00011000;
252 assign replacement_char[2] = 8'b00111100;
253 assign replacement_char[3] = 8'b01100110;
254 assign replacement_char[4] = 8'b01011010;
255 assign replacement_char[5] = 8'b01111010;
256 assign replacement_char[6] = 8'b01111010;
257 assign replacement_char[7] = 8'b01111010;
258 assign replacement_char[8] = 8'b01110110;
259 assign replacement_char[9] = 8'b01101110;
260 assign replacement_char[10] = 8'b01101110;
261 assign replacement_char[11] = 8'b01111110;
262 assign replacement_char[12] = 8'b01101110;
263 assign replacement_char[13] = 8'b00111100;
264 assign replacement_char[14] = 8'b00011000;
265 assign replacement_char[15] = 8'b00000000;
267 wire [6:0] char_x;
268 wire [4:0] char_y;
269 wire [12:0] char_flat_idx;
270 assign char_x = h_counter / 8;
271 assign char_y = v_counter / 16;
272 assign char_flat_idx = char_x + char_y * LINE_LENGTH;
275 * hs[0], vs[0], fetched_memory_field, is_high_byte, char, char_pixel_x[0],
276 * char_pixel_y and display_on[0] get loaded first, then, one tick later,
277 * hs[1], vs[1], char_pixel_x[1], display_on[1], char_pixel_row,
278 * replacement_pixel_row and is_ascii_char get loaded and finally, another
279 * tick later, color gets loaded
281 reg [2:0] hs;
282 reg [2:0] vs;
283 reg [15:0] fetched_memory_field;
284 reg is_high_byte;
285 reg [2:0] char_pixel_x [1:0];
286 reg [3:0] char_pixel_y;
287 reg [1:0] display_on;
288 reg [0:7] char_pixel_row;
289 reg [0:7] replacement_pixel_row;
290 reg is_ascii_char;
291 reg [8:0] color;
293 wire [7:0] char;
294 wire [0:7] pixel_row_to_use;
295 wire pixel_on;
296 assign char = is_high_byte ? fetched_memory_field[15:8] :
297 fetched_memory_field[7:0];
298 assign pixel_row_to_use = is_ascii_char ? char_pixel_row :
299 replacement_pixel_row;
300 assign pixel_on = pixel_row_to_use[char_pixel_x[1]];
302 /* Assign module's outputs */
303 assign h_sync = hs[2];
304 assign v_sync = vs[2];
305 assign {red, green, blue} = color;
307 always @ (posedge clock_25mhz) begin
308 /* Stuff, that gets loaded first */
309 if (h_stage == H_STAGE_SYNC)
310 hs[0] <= H_POLARITY;
311 else
312 hs[0] <= ~H_POLARITY;
314 if (v_stage == V_STAGE_SYNC)
315 vs[0] <= V_POLARITY;
316 else
317 vs[0] <= ~V_POLARITY;
319 fetched_memory_field <= text_memory[char_flat_idx[12:1]];
320 is_high_byte <= char_flat_idx[0];
322 char_pixel_x[0] <= h_counter % 8;
323 char_pixel_y <= v_counter % 16;
325 display_on[0] <= h_stage == H_STAGE_ACTIVE_VIDEO &&
326 v_stage == V_STAGE_ACTIVE_VIDEO;
328 /* Stuff, that gets loaded one tick later */
329 hs[1] <= hs[0];
330 vs[1] <= vs[0];
332 char_pixel_x[1] <= char_pixel_x[0];
334 display_on[1] <= display_on[0];
336 char_pixel_row <= font[char[6:0] * 16 + char_pixel_y];
337 replacement_pixel_row <= replacement_char[char_pixel_y];
339 is_ascii_char <= ~char[7];
341 /* Stuff, that gets loaded another tick later */
342 hs[2] <= hs[1];
343 vs[2] <= vs[1];
345 if (!display_on)
346 color <= 9'b0;
347 else if (pixel_on)
348 color <= FG_COLOR;
349 else
350 color <= BG_COLOR;
351 end // always @ (posedge clock_25mhz)
353 `ifdef SIMULATION
354 /* avoid undefined values */
355 initial begin
356 powered_on <= 0;
357 powered_on_latched <= 0;
358 ack <= 0;
360 hs <= {3{~H_POLARITY}};
361 vs <= {3{~V_POLARITY}};
362 fetched_memory_field <= 16'b0;
363 is_high_byte <= 0;
364 char_pixel_x[0] <= 0;
365 char_pixel_x[1] <= 0;
366 char_pixel_y <= 0;
367 display_on <= 2'b0;
368 char_pixel_row <= 8'b0;
369 replacement_pixel_row <= 8'b0;
370 is_ascii_char <= 0;
371 color <= 9'b0;
373 h_counter <= 0;
374 h_stage <= H_STAGE_RB_OR_FP;
376 v_counter <= 0;
377 v_stage <= V_STAGE_BB_OR_FP;
379 `endif
380 endmodule // vga