2 * Copyright 2018 Jacob Lifshay
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 `timescale 1ns / 100ps
25 module vga_text_buffer(
27 input [15:0] screen_x,
28 input [15:0] screen_y,
30 output reg [7:0] screen_char,
37 parameter font_x_size = 8;
38 parameter font_y_size = 8;
39 parameter screen_x_size = 800;
40 parameter screen_y_size = 600;
41 parameter text_x_size = screen_x_size / font_x_size;
42 parameter text_y_size = screen_y_size / font_y_size;
43 parameter ram_x_size = 128;
44 parameter ram_y_size = 128;
46 // ram_style = "block"
47 reg [7:0] text_ram[ram_x_size * ram_y_size - 1 : 0];
49 initial $readmemh("text_initial.hex", text_ram);
53 initial screen_char = 0;
55 reg [11:0] scroll_amount;
57 initial scroll_amount = 0;
59 always @(posedge pixel_clock) begin
60 screen_char <= screen_valid ? text_ram[ram_x_size * ((screen_y / font_y_size) + scroll_amount) + (screen_x / font_x_size)] : 0;
73 wire [11:0] cursor_x_after_tab_unwrapped = ((cursor_x >> 3) + 1) << 3;
74 wire [11:0] cursor_x_after_tab = (cursor_x_after_tab_unwrapped == text_x_size ? 0 : cursor_x_after_tab_unwrapped);
76 reg [15:0] text_ram_write_address;
77 reg text_ram_write_enable;
78 reg [7:0] text_ram_write_data;
80 always @(posedge clk) begin
81 if(text_ram_write_enable)
82 text_ram[text_ram_write_address] <= text_ram_write_data;
85 parameter space_char = 'h20;
86 parameter escape_char = 'h1B;
87 parameter left_bracket_char = 'h5B;
88 parameter capital_H_char = 'h48;
90 always @(posedge clk) begin
91 text_ram_write_enable = 0;
101 if(cursor_x != ram_x_size - 1) begin
103 text_ram_write_enable = 1;
104 text_ram_write_address = ram_x_size * (cursor_y + scroll_amount) + cursor_x;
105 text_ram_write_data = space_char;
106 cursor_x <= cursor_x + 1;
108 else if(cursor_y != ram_y_size - 1) begin
110 text_ram_write_enable = 1;
111 text_ram_write_address = ram_x_size * (cursor_y + scroll_amount) + cursor_x;
112 text_ram_write_data = space_char;
114 cursor_y <= cursor_y + 1;
117 text_ram_write_enable = 1;
118 text_ram_write_address = ram_x_size * (cursor_y + scroll_amount) + cursor_x;
119 text_ram_write_data = space_char;
130 if(cursor_y != text_y_size - 1) begin
132 cursor_y <= cursor_y + 1;
139 scroll_amount <= scroll_amount + 1;
151 cursor_x <= cursor_x_after_tab;
155 text_ram_write_enable = 1;
156 text_ram_write_address = ram_x_size * (cursor_y + scroll_amount) + cursor_x;
157 text_ram_write_data = tty_data;
158 if(cursor_x != text_x_size - 1) begin
159 cursor_x <= cursor_x + 1;
162 else if(cursor_y != text_y_size - 1) begin
164 cursor_y <= cursor_y + 1;
169 cursor_y <= text_y_size - 1;
172 scroll_amount <= scroll_amount + 1;
182 if(cursor_x != ram_x_size - 1) begin
184 text_ram_write_enable = 1;
185 text_ram_write_address = ram_x_size * (cursor_y + scroll_amount) + cursor_x;
186 text_ram_write_data = space_char;
187 cursor_x <= cursor_x + 1;
190 text_ram_write_enable = 1;
191 text_ram_write_address = ram_x_size * (cursor_y + scroll_amount) + cursor_x;
192 text_ram_write_data = space_char;
201 'h52: begin // "R": reset
205 left_bracket_char: begin
210 text_ram_write_enable = 1;
211 text_ram_write_address = ram_x_size * (cursor_y + scroll_amount) + cursor_x;
212 text_ram_write_data = tty_data;
213 if(cursor_x != text_x_size - 1) begin
214 cursor_x <= cursor_x + 1;
218 else if(cursor_y != text_y_size - 1) begin
220 cursor_y <= cursor_y + 1;
226 cursor_y <= text_y_size - 1;
229 scroll_amount <= scroll_amount + 1;
241 capital_H_char: begin // move to top left
248 text_ram_write_enable = 1;
249 text_ram_write_address = ram_x_size * (cursor_y + scroll_amount) + cursor_x;
250 text_ram_write_data = tty_data;
251 if(cursor_x != text_x_size - 1) begin
252 cursor_x <= cursor_x + 1;
256 else if(cursor_y != text_y_size - 1) begin
258 cursor_y <= cursor_y + 1;
264 cursor_y <= text_y_size - 1;
267 scroll_amount <= scroll_amount + 1;