Skip to content

Commit 701558b

Browse files
committed
Merge branch 'vt100'
2 parents 52068f4 + df9c919 commit 701558b

File tree

11 files changed

+1903
-1797
lines changed

11 files changed

+1903
-1797
lines changed

embed.fth

+73-54
Large diffs are not rendered by default.

font.bin

+835-835
Large diffs are not rendered by default.

fonts/terminus.bin

+831-831
Large diffs are not rendered by default.

makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ EFORTH=h2.hex
9595
h2${EXE}: h2.c h2.h
9696
${CC} ${CFLAGS} -std=c99 $< -o $@
9797

98-
embed${EXE}: embed.o
98+
embed${EXE}: embed.c
99+
${CC} ${CFLAGS} -std=c99 $< -o $@
99100

100101
${EFORTH}: embed${EXE} embed.blk embed.fth
101102
${DF}embed${EXE} embed.blk $@ embed.fth

readme.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,10 @@ interface with devices on the [Nexys3][] board:
258258
* [VGA][] output device, text mode only, 80 by 40 characters from
259259
<http://www.javiervalcarce.eu/html/vhdl-vga80x40-en.html>. This has
260260
been heavily modified from the original, which now implements most of a
261-
[VT100][] terminal emulator.
261+
[VT100][] terminal emulator. This has two fonts available to it:
262+
- [Terminus][]/[KOI8-R][] (Default)
263+
- Latin [ISO-8859-15][] (Secondary Font) from
264+
<https://git.kernel.org/pub/scm/linux/kernel/git/legion/kbd.git>
262265
* [Timer][] in [timer.vhd][].
263266
* [UART][] (Rx/Tx) in [uart.vhd][].
264267
* [PS/2][] Keyboard
@@ -1213,6 +1216,9 @@ a text buffer to it would help in developing code for the platform.
12131216
[embed]: https://github.com/howerj/embed
12141217
[SDL]: https://www.libsdl.org/
12151218
[Apache 2.0]: https://www.apache.org/licenses/LICENSE-2.0.html
1219+
[KOI8-R]: https://en.wikipedia.org/wiki/KOI8-R
1220+
[Terminus]: http://terminus-font.sourceforge.net/
1221+
[ISO-8859-15]: https://en.wikipedia.org/wiki/ISO/IEC_8859-15
12161222

12171223
<!--
12181224

t/ansi.fth

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ WORDLIST CONSTANT COOL-TEXT ( <_< - way cool )
1111
COOL-TEXT >ORDER DEFINITIONS
1212
VARIABLE COOL-CHARACTER CHAR * COOL-CHARACTER !
1313
: BYE BYE ;
14-
: CR CR ;
14+
: CR $D EMIT $A EMIT ;
1515
: {{ CR COOL-TEXT >ORDER DUP ;
1616
: >_> CHAR COOL-CHARACTER ! ;
1717
: <_< [CHAR] * COOL-CHARACTER ! ;

tb.vhd

+9-11
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,16 @@ architecture testing of tb is
3939
);
4040

4141
constant number_of_interrupts: positive := 8;
42-
constant uart_baud: 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";
4646
constant reset_period_us: natural := 1;
4747
constant jitter_on: boolean := false;
48-
4948
constant clock_period: time := 1000 ms / g.clock_frequency;
49+
constant tb_vga_on: boolean := false;
50+
constant tb_uart_on: boolean := false;
51+
constant tb_util_on: boolean := false;
5052

5153
-- Test bench configurable options --
5254

@@ -169,15 +171,11 @@ begin
169171
mem_addr => mem_addr,
170172
mem_data => mem_data);
171173

172-
uut_util: work.util.util_tb generic map(g => g);
173-
uut_vga: work.vga_pkg.vt100_tb generic map(g => g);
174-
175-
-- The "io_pins_tb" works correctly, however in GHDL 0.29, compiled under
176-
-- Windows, fails to simulate this component correctly, resulting
177-
-- in a crash. This does not affect the Linux build of GHDL. It has
178-
-- something to do with 'Z' values for std_logic types.
179-
180-
uut_io_pins: work.util.io_pins_tb generic map(g => g);
174+
-- NB. It would be nice to configure these as off/on, as well as
175+
-- controlling how long they run for from here.
176+
util_g: if tb_util_on generate uut_util: work.util.util_tb generic map(g => g); end generate;
177+
vga_g: if tb_vga_on generate uut_vga: work.vga_pkg.vt100_tb generic map(g => g); end generate;
178+
uart_g: if tb_uart_on generate uut_uart: work.uart_pkg.uart_tb generic map(g => g); end generate;
181179

182180
uart_0_blk: block
183181
signal uart_clock_rx_we, uart_clock_tx_we, uart_control_we: std_ulogic := '0';

top.vhd

+26-2
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,16 @@ entity top is
6666
mem_wait: out std_ulogic := '0'; -- positive logic!
6767
flash_cs: out std_ulogic := '0';
6868
flash_rp: out std_ulogic := '1';
69-
mem_addr: out std_ulogic_vector(26 downto 1) := (others => '0');
70-
mem_data: inout std_logic_vector(15 downto 0) := (others => 'Z'));
69+
mem_addr: out std_ulogic_vector(26 downto 1) := (others => '0');
70+
mem_data: inout std_logic_vector(15 downto 0) := (others => 'Z'));
7171
end;
7272

7373
architecture behav of top is
7474
constant timer_length: positive := 16;
7575
constant number_of_interrupts: positive := 8;
7676
constant number_of_led_displays: positive := 4;
7777
constant timer_period_us: positive := 20000;
78+
constant use_sine: boolean := false;
7879

7980
-- Signals
8081
signal rst: std_ulogic := '0';
@@ -150,6 +151,10 @@ architecture behav of top is
150151
signal mem_data_i_we: std_ulogic := '0';
151152
signal mem_data_o: std_ulogic_vector(15 downto 0) := (others => '0');
152153
signal mem_control_we: std_ulogic := '0';
154+
155+
signal sine_we: std_ulogic := '0';
156+
signal sine: std_ulogic_vector(15 downto 0) := (others => '0');
157+
153158
begin
154159
-------------------------------------------------------------------------------
155160
-- The Main components
@@ -163,6 +168,8 @@ begin
163168
clk => clk,
164169
rst => rst);
165170

171+
-- TODO: Add interrupts on video blanking periods, which should
172+
-- make writing graphics code easier.
166173
cpu_irc(0) <= btnu_d; -- configurable CPU reset (can mask this)
167174
cpu_irc(1) <= not rx_fifo_empty;
168175
cpu_irc(2) <= rx_fifo_full;
@@ -245,6 +252,10 @@ begin
245252
uart_clock_tx_we <= '1' when is_write and selector = x"9" else '0';
246253
uart_clock_rx_we <= '1' when is_write and selector = x"A" else '0';
247254
uart_control_we <= '1' when is_write and selector = x"B" else '0';
255+
256+
sine_o: if use_sine generate
257+
sine_we <= '1' when is_write and selector = x"C" else '0';
258+
end generate;
248259
end block;
249260

250261
io_read: process(
@@ -262,6 +273,7 @@ begin
262273
timer_counter_o,
263274

264275
vga_data_busy,
276+
sine,
265277

266278
mem_data_o)
267279
begin
@@ -289,10 +301,22 @@ begin
289301
io_din <= "000" & btnu_d & btnd_d & btnl_d & btnr_d & btnc_d & sw_d;
290302
when "100" =>
291303
io_din <= mem_data_o;
304+
when "101" =>
305+
if use_sine then
306+
io_din <= sine;
307+
end if;
292308
when others => io_din <= (others => '0');
293309
end case;
294310
end process;
295311

312+
--- Sine ----------------------------------------------------------
313+
sine_gen_0: if use_sine generate
314+
sine_0: work.util.sine
315+
generic map(g => g)
316+
port map(clk => clk, rst => rst, xwe => sine_we, x => io_dout, s => sine);
317+
end generate;
318+
--- Sine ----------------------------------------------------------
319+
296320
--- UART ----------------------------------------------------------
297321
uart_fifo_0: work.uart_pkg.uart_top
298322
generic map (g => g, baud => uart_baud, use_fifo => false)

uart.vhd

+52-24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
--
1+
-- FILE: uart.vhd
22
-- BRIEF: UART TX/RX module
33
-- LICENSE: MIT
44
-- COPYRIGHT: Richard James Howe (2019)
@@ -323,38 +323,44 @@ architecture structural of uart_core is
323323
signal rx_fail: std_ulogic_vector(1 downto 0);
324324
signal rx_ok_buf: std_ulogic;
325325
signal do, do_c, do_n: std_ulogic_vector(rx_do'range);
326+
signal fail_c, fail_n: std_ulogic_vector(1 downto 0);
326327
signal nd_c, nd_n: std_ulogic; -- new data
327328
begin
328-
rx_ok_buf <= not (rx_fail(0) or rx_fail(1)) after g.delay;
329-
rx_ok <= rx_ok_buf after g.delay;
329+
rx_ok_buf <= not (fail_c(0) or fail_c(1)) after g.delay;
330+
rx_ok <= rx_ok_buf;
330331
rx_do <= do after g.delay;
331332
rx_nd <= nd_c and rx_ok_buf after g.delay; -- no new data if there are errors
332333

333334
process (clk, rst)
334335
begin
335336
if rst = '1' and g.asynchronous_reset then
336-
do_c <= (others => '0') after g.delay;
337-
nd_c <= '0' after g.delay;
337+
do_c <= (others => '0') after g.delay;
338+
fail_c <= (others => '0') after g.delay;
339+
nd_c <= '0' after g.delay;
338340
elsif rising_edge(clk) then
339341
if rst = '1' and not g.asynchronous_reset then
340-
do_c <= (others => '0') after g.delay;
341-
nd_c <= '0' after g.delay;
342+
do_c <= (others => '0') after g.delay;
343+
fail_c <= (others => '0') after g.delay;
344+
nd_c <= '0' after g.delay;
342345
else
343-
do_c <= do_n after g.delay;
344-
nd_c <= nd_n after g.delay;
346+
do_c <= do_n after g.delay;
347+
nd_c <= nd_n after g.delay;
348+
fail_c <= fail_n after g.delay;
345349
end if;
346350
end if;
347351
end process;
348352

349-
process (do_c, do, nd_c, rx_we, rx_re)
353+
process (do_c, do, nd_c, rx_we, rx_re, fail_c, rx_fail)
350354
begin
351-
do_n <= do_c after g.delay;
352-
nd_n <= nd_c after g.delay;
355+
do_n <= do_c after g.delay;
356+
nd_n <= nd_c after g.delay;
357+
fail_n <= fail_c after g.delay;
353358
if rx_we = '1' then
354-
do_n <= do after g.delay;
355-
nd_n <= '1' after g.delay;
359+
nd_n <= '1' after g.delay;
360+
do_n <= do after g.delay;
361+
fail_n <= rx_fail after g.delay;
356362
elsif rx_re = '1' then
357-
nd_n <= '0' after g.delay;
363+
nd_n <= '0' after g.delay;
358364
end if;
359365
end process;
360366

@@ -608,7 +614,7 @@ begin
608614
state_n <= idle after g.delay;
609615
when idle =>
610616
count_n <= 0 after g.delay;
611-
if rx_sync = '0' and majority = '1' then
617+
if rx_sync = '0' then -- and majority = '1' then
612618
state_n <= start after g.delay;
613619
cr <= '1' after g.delay;
614620
sr_n <= (others => '0') after g.delay;
@@ -653,7 +659,6 @@ begin
653659
state_n <= done after g.delay; -- frame error
654660
fail_n(0) <= '1' after g.delay;
655661
elsif count_c = ctr_stop_bits(ctr_c) then
656-
count_n <= 0 after g.delay;
657662
state_n <= done after g.delay;
658663
else
659664
count_n <= count_c + 1 after g.delay;
@@ -662,6 +667,9 @@ begin
662667
when done => -- The consuming module needs to store rx_c/fail_c immediately
663668
we <= '1' after g.delay;
664669
state_n <= idle after g.delay;
670+
--rx_n <= (others => '0') after g.delay;
671+
--sr_n <= (others => '0') after g.delay;
672+
--fail_n <= (others => '0') after g.delay;
665673
end case;
666674

667675
if ctr_we = '1' then
@@ -817,11 +825,17 @@ architecture testing of uart_tb is
817825
constant clock_period: time := 1000 ms / g.clock_frequency;
818826
signal rst, clk: std_ulogic := '1';
819827
signal stop: boolean := false;
828+
signal loopback: boolean := true;
820829
signal tx, rx: std_ulogic;
821830
signal tx_ok, rx_ok: std_ulogic;
822831
signal tx_we, rx_re: std_ulogic := '0';
823832
signal rx_nd: std_ulogic;
824833
signal di, do: std_ulogic_vector(7 downto 0);
834+
835+
signal reg: std_ulogic_vector(15 downto 0);
836+
signal clock_reg_tx_we: std_ulogic;
837+
signal clock_reg_rx_we: std_ulogic;
838+
signal control_reg_we: std_ulogic;
825839
begin
826840
-- duration: process begin wait for 20000 us; stop <= true; wait; end process;
827841
clk_process: process
@@ -843,7 +857,7 @@ begin
843857
stimulus: process
844858
procedure write(data: std_ulogic_vector(di'range)) is
845859
begin
846-
wait for clock_period;
860+
wait for clock_period * 1;
847861
while tx_ok = '0' loop
848862
wait for clock_period;
849863
end loop;
@@ -856,6 +870,19 @@ begin
856870
di <= x"00";
857871
wait until rst = '0';
858872
wait for clock_period;
873+
reg <= x"8080";
874+
control_reg_we <= '1';
875+
wait for clock_period;
876+
control_reg_we <= '0';
877+
reg <= x"0036";
878+
clock_reg_tx_we <= '1';
879+
wait for clock_period;
880+
clock_reg_tx_we <= '0';
881+
clock_reg_rx_we <= '1';
882+
reg <= x"0035";
883+
wait for clock_period;
884+
clock_reg_rx_we <= '0';
885+
wait for clock_period;
859886

860887
write(x"AA");
861888
write(x"BB");
@@ -866,7 +893,8 @@ begin
866893
while tx_ok = '0' loop
867894
wait for clock_period;
868895
end loop;
869-
896+
loopback <= false;
897+
wait for clock_period * 50000;
870898
stop <= true;
871899
wait;
872900
end process;
@@ -884,7 +912,7 @@ begin
884912
wait;
885913
end process;
886914

887-
rx <= tx; -- loop back test
915+
rx <= tx when loopback else '0'; -- loop back test
888916

889917
uut: work.uart_pkg.uart_core
890918
generic map(g => g)
@@ -900,10 +928,10 @@ begin
900928
rx_nd => rx_nd,
901929
rx_re => rx_re,
902930
rx_do => do,
903-
reg => (others => '0'),
904-
clock_reg_tx_we => '0',
905-
clock_reg_rx_we => '0',
906-
control_reg_we => '0'
931+
reg => reg,
932+
clock_reg_tx_we => clock_reg_tx_we,
933+
clock_reg_rx_we => clock_reg_rx_we,
934+
control_reg_we => control_reg_we
907935
);
908936
end architecture;
909937

0 commit comments

Comments
 (0)