Skip to content

Commit 742dc4d

Browse files
committed
103.556MHz/1B00: Moved font, ++ VT100, test code
The VT100 terminal emulator has been much improved, and a new attribute can be applied to the text (whilst not losing any current attributes). Text can be blinked on and off (using a clock derived from the cursor blink clock, divided by four), the cursor save and restore command has been added, along with a few other miscellaneous commands, and a bug in the relative cursor positioning routines has been fixed (a relative move of 0 should be treated the same as 1 for those functions, it was not being treated that way). * UART baud initial value can be set by a generic, which is nice to have, but not needed as it can be set from a control register. The other options cannot be set at the moment and default to 8 bits, 1 stop bit, no parity. * Special cases for majority logic gates of 1, 2 and 3 have been added to the 'majority' module. * The font directory has moved. * 'vga.vhd' converted to a UTF-8 file, fixed some invalid characters. * Formatting changed 'port(' -> 'port (' * Added extra VT100 terminal codes to simulator. * Instead of commenting out code, generate functions are used. * This applies to the new VGA code. * And to adding a FIFO to the UART (which almost works). * Some extra comments have been added. The next major problems with the project will be: * Making the UART more reliable, currently we get nonsense if we are not processing received characters quick enough and we spend a lot of time waiting around for transmission. There is a rate that we will not be able to keep up with when it comes to processing text, however we should never be receiving invalid data, which we are, if we cannot keep up. * The UART RX module does not work with certain values for the baud generator (specifically at 115200, the value that needs to go into the clock register is '54', however it does not work when given that value, 50-53 and 55 have been tried and work, 54 does not). For TX, '54' works. * Scrolling should be handled by the VT100 terminal, currently it just erases everything on the screen. This is not optimal.
1 parent 0777103 commit 742dc4d

15 files changed

+651
-356
lines changed

fonts/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.pbm

lat0.bin renamed to fonts/lat0.bin

File renamed without changes.

fonts/makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
SOURCES:=$(wildcard *.bin)
2+
OBJFILES=$(SOURCES:%.bin=%.pbm)
3+
4+
.PHONY: all clean
5+
6+
all: ${OBJFILES}
7+
8+
%.pbm: %.bin
9+
echo "P1\n8" `wc $< | awk '{print $$1}'` > $@
10+
cat $< >> $@
11+
12+
clean:
13+
rm -fv ${OBJFILES}
14+

fonts/readme.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Font Directory
2+
3+
This directory contains fonts which can used with the VGA terminal emulator
4+
component.
5+
6+
All characters are 8 pixels wide, and 12 high. To ease editing and viewing of
7+
the font, they are stored in a text file as a pixel map, with a '1' character
8+
representing a switched on pixel. No prizes for guessing which character
9+
represents an off pixel.
10+
11+
The format has two other advantages; it is easy for it to be read in by the HDL
12+
tool-chain, and it can be converted to a viewable [PBM][] file quite easily. The
13+
conversion just requires prepending a header.
14+
15+
The [Terminus][] font used could do with some cleaning up - apart from the
16+
normal printable ASCII characters, the characters outside of that range were
17+
picked at random.
18+
19+
## Copyright
20+
21+
The fonts are under copyright. I believe the [Terminus][] font to be licensed under
22+
the 'SIL OPEN FONT LICENSE Version 1.1', the iso-8859-15 Latin-0 font I am
23+
unsure of, it came with the original project and was generated from an open
24+
source font package.
25+
26+
[PBM]: https://en.wikipedia.org/wiki/Netpbm_format
27+
[Terminus]: http://terminus-font.sourceforge.net/
File renamed without changes.

h2.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -935,7 +935,7 @@ static void terminal_at_xy(vt100_t * const t, unsigned x, unsigned y, const bool
935935
if (limit_not_wrap) {
936936
x = MAX(x, 0);
937937
y = MAX(y, 0);
938-
x = MIN(x, t->width - 1);
938+
x = MIN(x, t->width - 1);
939939
y = MIN(y, t->height - 1);
940940
} else {
941941
x %= t->width;
@@ -998,11 +998,15 @@ static int terminal_escape_sequences(vt100_t * const t, const uint8_t c) {
998998
assert(t);
999999
assert(t->state != TERMINAL_NORMAL_MODE);
10001000
switch (t->state) {
1001-
case TERMINAL_CSI:
1002-
if (c == '[')
1003-
t->state = TERMINAL_COMMAND;
1004-
else
1005-
goto fail;
1001+
case TERMINAL_CSI: /* process CSI and some non-CSI Escape Only commands */
1002+
switch (c) {
1003+
case '[': t->state = TERMINAL_COMMAND; break;
1004+
case 'c': goto eraser; /*reset display*/ break;
1005+
case '7': t->cursor_saved = t->cursor; t->attribute_saved = t->attribute; break;
1006+
case '8': t->cursor = t->cursor_saved; t->attribute = t->attribute_saved; break;
1007+
default: goto fail;
1008+
}
1009+
10061010
break;
10071011
case TERMINAL_COMMAND:
10081012
switch (c) {
@@ -1064,7 +1068,11 @@ static int terminal_escape_sequences(vt100_t * const t, const uint8_t c) {
10641068
if (t->n1 == 6)
10651069
goto success;
10661070
goto fail;
1071+
eraser: /* HAHA: This is clearly the best way of doing things. */
1072+
t->command_index = 1;
1073+
t->n1 = 3; /* fall-through */
10671074
case 'J': /* reset */
1075+
10681076
switch (t->n1) {
10691077
case 3: /* fall-through */
10701078
case 2: t->cursor = 0; /* with cursor */ /* fall-through */

h2.fth

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ location search-previous 0
615615

616616

617617
: 5u.r 5 u.r space ; hidden
618-
: dm+ 2/ for aft dup @ 5u.r cell+ then next ; ( a u -- a )
618+
: dm+ 2/ for aft dup @ 5u.r cell+ then next ; hidden ( a u -- a )
619619
: colon 58 emit ; hidden ( -- )
620620

621621
\ It would be nice to colorize the dump output.
@@ -662,13 +662,14 @@ location search-previous 0
662662
: vt100 ' ps2? <key> ! ' vga! <emit> ! hand ;
663663
: interactive ' input <key> ! ' output <emit> ! hand ;
664664
: io!
665-
$36 oUartTxBaud ! ( set TX baud rate )
666-
$32 oUartRxBaud ! ( set TX baud rate )
665+
( 115200 9600 )
666+
$36 ( $28B ) oUartTxBaud ! ( set TX baud rate )
667+
$35 ( $28A ) oUartRxBaud ! ( set TX baud rate )
667668
$8484 oUartControl ! ( set UART control register; 8 bits, 1 stop, no parity )
668669
0 timer! 0 led! 0 segments!
669670
0 ien! 0 oIrcMask ! interactive ; ( -- : initialize I/O )
670-
: ver $666 ;
671-
: hi io! ( save ) hex cr hi-string print ver <# # # 46 hold # #> type cr here . .free cr [ ;
671+
\ : ver $666 ;
672+
: hi io! ( save ) hex cr hi-string print cpu-id <# # # 46 hold # #> type cr here . .free cr [ ;
672673
: cold io! branch entry ;
673674
: bye cold ;
674675

h2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ typedef struct {
200200
terminal_state_t state;
201201
bool blinks;
202202
bool cursor_on;
203-
vt100_attribute_t attribute;
203+
vt100_attribute_t attribute, attribute_saved;
204204
vt100_attribute_t attributes[VT100_MAX_SIZE];
205205
uint8_t m[VT100_MAX_SIZE];
206206
uint8_t command_index;

makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,11 @@ viewer: simulation
176176
endif
177177

178178
USB?=/dev/ttyUSB0
179+
BAUD?=115200
180+
#BAUD?=9600
179181

180182
talk:
181-
picocom --omap delbs -e b -b 115200 ${USB}
183+
picocom --omap delbs -e b -b ${BAUD} ${USB}
182184

183185
bitfile: design.bit
184186

readme.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ The following peripherals have been implemented in the [VHDL][] SoC to
252252
interface with devices on the [Nexys3][] board:
253253

254254
* [VGA][] output device, text mode only, 80 by 40 characters from
255-
<http://www.javiervalcarce.eu/html/vhdl-vga80x40-en.html>
255+
<http://www.javiervalcarce.eu/html/vhdl-vga80x40-en.html>. This has
256+
been heavily modified from the original, which now implements most of a VT100
257+
terminal emulator.
256258
* Timer
257259
* [UART][] (Rx/Tx) in [uart.vhd][].
258260
* [PS/2][] Keyboard

tb.vhd

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ architecture testing of tb is
3939
);
4040

4141
constant number_of_interrupts: positive := 8;
42-
constant uart_baud_rate: positive := 115200;
42+
constant uart_baud: positive := 115200;
4343
constant configuration_file_name: string := "tb.cfg";
4444
constant uart_tx_time: time := (10*1000 ms) / 115200;
4545
constant uart_default_input: std_ulogic_vector(7 downto 0) := x"AA";
@@ -138,7 +138,7 @@ begin
138138
generic map(
139139
g => g,
140140
reset_period_us => reset_period_us,
141-
uart_baud_rate => uart_baud_rate)
141+
uart_baud => uart_baud)
142142
port map(
143143
debug => dbgi,
144144
clk => clk,
@@ -183,8 +183,8 @@ begin
183183
signal uart_clock_rx_we, uart_clock_tx_we, uart_control_we: std_ulogic := '0';
184184
signal uart_reg: std_ulogic_vector(15 downto 0);
185185
begin
186-
uart_0: work.uart_pkg.uart_top
187-
generic map (g => g)
186+
uart_0: work.uart_pkg.uart_core
187+
generic map (g => g, baud => uart_baud)
188188
port map (
189189
clk => clk,
190190
rst => rst,
@@ -206,7 +206,7 @@ begin
206206
end block;
207207

208208
-- uut_uart: work.uart_pkg.uart_core
209-
-- generic map(g => g, baud_rate => uart_baud_rate)
209+
-- generic map(g => g, baud_rate => uart_baud)
210210
-- port map(
211211
-- clk => clk,
212212
-- rst => rst,

top.vhd

Lines changed: 104 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ entity top is
2424
generic(
2525
g: common_generics := default_settings;
2626
reset_period_us: natural := 1;
27-
uart_baud_rate: positive := 115200;
27+
uart_baud: positive := 115200;
2828
uart_fifo_depth: positive := 8);
2929
port
3030
(
@@ -113,7 +113,6 @@ architecture behav of top is
113113
signal rx_fifo_full: std_ulogic := '0';
114114
signal rx_data_re: std_ulogic := '0';
115115

116-
signal tx_data: std_ulogic_vector(7 downto 0) := (others => '0');
117116
signal tx_fifo_full: std_ulogic := '0';
118117
signal tx_fifo_empty: std_ulogic := '0';
119118
signal tx_data_we: std_ulogic := '0';
@@ -216,7 +215,6 @@ begin
216215
assert not(io_wr = '1' and io_re = '1') report "IO Read/Write issued at same time" severity error;
217216

218217
vga_data <= io_dout(vga_data'range);
219-
tx_data <= io_dout(tx_data'range);
220218

221219
-- TODO: Raise trap (interrupt with bus error) on invalid memory access.
222220
io_write: block
@@ -298,33 +296,66 @@ begin
298296
--- UART ----------------------------------------------------------
299297
uart_0_blk: block
300298
signal tx_ok, rx_nd: std_ulogic;
299+
signal tx_data: std_ulogic_vector(7 downto 0) := (others => '0');
300+
constant use_fifo_uart: boolean := false;
301301
begin
302-
tx_fifo_full <= not tx_ok;
303-
tx_fifo_empty <= tx_ok;
304-
305-
rx_fifo_full <= rx_nd;
306-
rx_fifo_empty <= not rx_nd;
307-
uart_0: work.uart_pkg.uart_top
308-
generic map (g => g)
309-
port map (
310-
clk => clk,
311-
rst => rst,
312-
tx_di => tx_data,
313-
tx_we => tx_data_we,
314-
tx_ok => tx_ok,
315-
tx => tx,
316-
317-
rx => rx,
318-
rx_ok => open,
319-
rx_nd => rx_nd,
320-
rx_do => rx_data,
321-
rx_re => rx_data_re,
322-
323-
reg => io_dout,
324-
clock_reg_tx_we => uart_clock_tx_we,
325-
clock_reg_rx_we => uart_clock_rx_we,
326-
control_reg_we => uart_control_we
327-
);
302+
tx_data <= io_dout(tx_data'range);
303+
304+
ugen0: if not use_fifo_uart generate
305+
tx_fifo_full <= not tx_ok;
306+
tx_fifo_empty <= tx_ok;
307+
308+
rx_fifo_full <= rx_nd;
309+
rx_fifo_empty <= not rx_nd;
310+
311+
uart_0: work.uart_pkg.uart_core
312+
generic map (g => g, baud => uart_baud)
313+
port map (
314+
clk => clk,
315+
rst => rst,
316+
tx_di => tx_data,
317+
tx_we => tx_data_we,
318+
tx_ok => tx_ok,
319+
tx => tx,
320+
321+
rx => rx,
322+
rx_ok => open,
323+
rx_nd => rx_nd,
324+
rx_do => rx_data,
325+
rx_re => rx_data_re,
326+
327+
reg => io_dout,
328+
clock_reg_tx_we => uart_clock_tx_we,
329+
clock_reg_rx_we => uart_clock_rx_we,
330+
control_reg_we => uart_control_we);
331+
end generate;
332+
333+
-- TEST CODE, TX is not quite working. This generate should
334+
-- be moved into the core module.
335+
ugen1: if use_fifo_uart generate
336+
uart_fifo_0: work.uart_pkg.uart_top
337+
generic map (g => g, baud => uart_baud)
338+
port map (
339+
clk => clk,
340+
rst => rst,
341+
342+
tx => tx,
343+
tx_fifo_full => tx_fifo_full,
344+
tx_fifo_empty => tx_fifo_empty,
345+
tx_fifo_we => tx_data_we,
346+
tx_fifo_data => tx_data,
347+
348+
rx => rx,
349+
rx_fifo_re => rx_data_re,
350+
rx_fifo_data => rx_data,
351+
rx_fifo_full => rx_fifo_full,
352+
rx_fifo_empty => rx_fifo_empty,
353+
354+
reg => io_dout,
355+
clock_reg_tx_we => uart_clock_tx_we,
356+
clock_reg_rx_we => uart_clock_rx_we,
357+
control_reg_we => uart_control_we);
358+
end generate;
328359
end block;
329360
--- UART ----------------------------------------------------------
330361

@@ -352,44 +383,51 @@ begin
352383
--- Timer ---------------------------------------------------------
353384

354385
--- VGA -----------------------------------------------------------
355-
vt100_0: work.vga_pkg.vt100
356-
generic map (g => g)
357-
port map (
358-
clk => clk,
359-
clk25MHz => clk25MHz,
360-
rst => rst,
361-
we => vga_data_we,
362-
char => vga_data,
363-
busy => vga_data_busy,
364-
o_vga => o_vga
365-
);
386+
vga_selector: block
387+
constant use_vt100: boolean := true;
388+
begin
389+
gen_vt100_0: if use_vt100 generate
390+
vt100_0: work.vga_pkg.vt100
391+
generic map (g => g)
392+
port map (
393+
clk => clk,
394+
clk25MHz => clk25MHz,
395+
rst => rst,
396+
we => vga_data_we,
397+
char => vga_data,
398+
busy => vga_data_busy,
399+
o_vga => o_vga);
400+
end generate;
366401

367-
-- Test code
368-
-- NOTE: Timing is not the best, VGA monitor loses synchronization
369-
-- every so often with this module.
370-
-- vga_c1: block
371-
-- signal row, column: integer := 0;
372-
-- signal h_blank, v_blank, draw: std_ulogic := '0';
373-
-- begin
374-
-- draw <= not h_blank and not v_blank;
375-
-- vga_c: work.util.vga_controller
376-
-- generic map (
377-
-- g => g,
378-
-- pixel_clock_frequency => 25_000_000,
379-
-- cfg => work.util.vga_640x480)
380-
-- port map (
381-
-- clk => clk25MHz,
382-
-- rst => rst,
383-
-- row => row,
384-
-- column => column,
385-
-- h_blank => h_blank,
386-
-- v_blank => v_blank,
387-
-- h_sync => o_vga.hsync,
388-
-- v_sync => o_vga.vsync);
389-
-- o_vga.red <= "111" when draw = '1' else "000";
390-
-- o_vga.green <= "111" when (draw = '1' and row < 100 and column < 100) else "000";
391-
-- o_vga.blue <= "11";
392-
-- end block;
402+
-- Test code
403+
-- NOTE: Timing is not the best, VGA monitor loses synchronization
404+
-- every so often with this module.
405+
vga_gen_c1: if not use_vt100 generate
406+
vga_c1: block
407+
signal row, column: integer := 0;
408+
signal h_blank, v_blank, draw: std_ulogic := '0';
409+
begin
410+
draw <= not h_blank and not v_blank;
411+
vga_c: work.util.vga_controller
412+
generic map (
413+
g => g,
414+
pixel_clock_frequency => 25_000_000,
415+
cfg => work.util.vga_640x480)
416+
port map (
417+
clk => clk25MHz,
418+
rst => rst,
419+
row => row,
420+
column => column,
421+
h_blank => h_blank,
422+
v_blank => v_blank,
423+
h_sync => o_vga.hsync,
424+
v_sync => o_vga.vsync);
425+
o_vga.red <= "111" when draw = '1' else "000";
426+
o_vga.green <= "111" when (draw = '1' and row < 100 and column < 100) else "000";
427+
o_vga.blue <= "11";
428+
end block;
429+
end generate;
430+
end block;
393431
--- VGA -----------------------------------------------------------
394432

395433
--- Keyboard ------------------------------------------------------

0 commit comments

Comments
 (0)