Skip to content

Commit cf11dcd

Browse files
committed
99.792MHz/1A82: Added control lines for raw mode
Control registers and lines for a raw mode, in which the programmer can write to video memory directly, have been added. The idea is that they will be able to use this mode for drawing on a low resolution display.
1 parent 52068f4 commit cf11dcd

File tree

3 files changed

+112
-16
lines changed

3 files changed

+112
-16
lines changed

top.vhd

+43-3
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ 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
@@ -150,6 +150,13 @@ architecture behav of top is
150150
signal mem_data_i_we: std_ulogic := '0';
151151
signal mem_data_o: std_ulogic_vector(15 downto 0) := (others => '0');
152152
signal mem_control_we: std_ulogic := '0';
153+
154+
-- signal sine_we: std_ulogic := '0';
155+
-- signal sine: std_ulogic_vector(15 downto 0) := (others => '0');
156+
157+
signal vt100_raw_addr_we: std_ulogic := '0';
158+
signal vt100_raw_data_we: std_ulogic := '0';
159+
signal vt100_raw_do: std_ulogic_vector(15 downto 0) := (others => '0');
153160
begin
154161
-------------------------------------------------------------------------------
155162
-- The Main components
@@ -245,6 +252,11 @@ 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_we <= '1' when is_write and selector = x"C" else '0';
257+
258+
vt100_raw_addr_we <= '1' when is_write and selector = x"C" else '0';
259+
vt100_raw_data_we <= '1' when is_write and selector = x"D" else '0';
248260
end block;
249261

250262
io_read: process(
@@ -262,6 +274,8 @@ begin
262274
timer_counter_o,
263275

264276
vga_data_busy,
277+
vt100_raw_do,
278+
-- sine,
265279

266280
mem_data_o)
267281
begin
@@ -289,10 +303,31 @@ begin
289303
io_din <= "000" & btnu_d & btnd_d & btnl_d & btnr_d & btnc_d & sw_d;
290304
when "100" =>
291305
io_din <= mem_data_o;
306+
when "101" =>
307+
io_din <= vt100_raw_do;
308+
-- io_din <= sine;
292309
when others => io_din <= (others => '0');
293310
end case;
294311
end process;
295312

313+
--- Sine ----------------------------------------------------------
314+
-- sine_block: block
315+
-- signal x, s: std_ulogic_vector(15 downto 0);
316+
-- begin
317+
-- reg_sin: work.util.reg
318+
-- generic map(g => g, N => x'length)
319+
-- port map(clk => clk, rst => rst, we => sine_we, di => io_dout, do => x);
320+
--
321+
-- sine_fifo_0: work.util.sine generic map(g => g) port map(x => x, s => s);
322+
--
323+
-- reg_sout: work.util.reg
324+
-- generic map(g => g, N => x'length)
325+
-- port map(clk => clk, rst => rst, we => '1', di => s, do => sine);
326+
--
327+
-- end block;
328+
--- Sine ----------------------------------------------------------
329+
330+
296331
--- UART ----------------------------------------------------------
297332
uart_fifo_0: work.uart_pkg.uart_top
298333
generic map (g => g, baud => uart_baud, use_fifo => false)
@@ -355,7 +390,12 @@ begin
355390
we => vga_data_we,
356391
char => vga_data,
357392
busy => vga_data_busy,
358-
o_vga => o_vga);
393+
o_vga => o_vga,
394+
395+
raw_addr_we => vt100_raw_addr_we,
396+
raw_data_we => vt100_raw_data_we,
397+
raw_di => io_dout,
398+
raw_do => vt100_raw_do);
359399
end generate;
360400

361401
-- Test code

util.vhd

+5
Original file line numberDiff line numberDiff line change
@@ -3963,6 +3963,9 @@ end architecture;
39633963
-- Angles are input as signed Furmans (1 Furman = (1/pow(2, 16) of a circle))
39643964
-- 1 Degree is ~182 Furmans. 1 rad is ~10430 Furmans.
39653965
-- Result is signed scaled 16-bit integer; -1 = -32767, +1 = 32767
3966+
--
3967+
-- TODO: Optionally insert registers at various locations throughout the module, specified
3968+
-- with a generic.
39663969
library ieee, work;
39673970
use ieee.std_logic_1164.all;
39683971
use ieee.numeric_std.all;
@@ -4065,3 +4068,5 @@ begin
40654068
wait;
40664069
end process;
40674070
end architecture;
4071+
------------------------- Sine / Cosine ------------------------------------------------------
4072+

vga.vhd

+64-13
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ package vga_pkg is
5050
type vga_control_registers_interface is record
5151
crx: std_ulogic_vector(6 downto 0); -- Cursor position X
5252
cry: std_ulogic_vector(5 downto 0); -- Cursor position Y
53-
ctl: std_ulogic_vector(4 downto 0); -- Control register
53+
ctl: std_ulogic_vector(5 downto 0); -- Control register
5454
end record;
5555

5656
constant vga_control_registers_initialize: vga_control_registers_interface := (
@@ -75,6 +75,7 @@ package vga_pkg is
7575
vga_din: in std_ulogic_vector(15 downto 0);
7676
vga_addr: in std_ulogic_vector(12 downto 0);
7777
base: in std_ulogic_vector(12 downto 0);
78+
raw_do: out std_ulogic_vector(15 downto 0);
7879

7980
-- VGA control registers
8081
i_font_sel: in std_ulogic_vector(0 downto 0);
@@ -97,7 +98,7 @@ package vga_pkg is
9798
--
9899
ocrx: in std_ulogic_vector(6 downto 0);
99100
ocry: in std_ulogic_vector(5 downto 0);
100-
octl: in std_ulogic_vector(4 downto 0);
101+
octl: in std_ulogic_vector(5 downto 0);
101102
--
102103
o_vga: out vga_physical_interface);
103104
end component;
@@ -134,7 +135,12 @@ package vga_pkg is
134135
char: in std_ulogic_vector(7 downto 0);
135136

136137
busy: out std_ulogic;
137-
o_vga: out vga_physical_interface);
138+
o_vga: out vga_physical_interface;
139+
140+
raw_addr_we: in std_ulogic;
141+
raw_data_we: in std_ulogic;
142+
raw_di: in std_ulogic_vector(15 downto 0);
143+
raw_do: out std_ulogic_vector(15 downto 0));
138144
end component;
139145

140146
-- VGA test bench, not-synthesizeable
@@ -217,7 +223,12 @@ begin
217223
we => we,
218224
char => char,
219225
busy => busy,
220-
o_vga => physical);
226+
o_vga => physical,
227+
228+
raw_addr_we => '0',
229+
raw_data_we => '0',
230+
raw_di => x"0000",
231+
raw_do => open);
221232

222233
stimulus_process: process
223234
begin
@@ -395,7 +406,12 @@ entity vt100 is
395406
char: in std_ulogic_vector(7 downto 0);
396407

397408
busy: out std_ulogic;
398-
o_vga: out vga_physical_interface);
409+
o_vga: out vga_physical_interface;
410+
411+
raw_addr_we: in std_ulogic;
412+
raw_data_we: in std_ulogic;
413+
raw_di: in std_ulogic_vector(15 downto 0);
414+
raw_do: out std_ulogic_vector(15 downto 0));
399415
end entity;
400416

401417
-- A better way of structuring this would be to process numbers in parallel
@@ -424,7 +440,7 @@ architecture rtl of vt100 is
424440
constant lsqb: unsigned(char'range) := x"5b"; -- '['
425441
constant ascii_c: unsigned(char'range) := x"63"; -- 'c'
426442
constant attr_default: unsigned(7 downto 0) := "00111000";
427-
constant ctl_default: unsigned(4 downto 0) := "01111";
443+
constant ctl_default: unsigned(5 downto 0) := "001111";
428444

429445
signal addr: std_ulogic_vector(12 downto 0) := (others => '0');
430446
signal data_we: std_ulogic := '0';
@@ -479,7 +495,23 @@ architecture rtl of vt100 is
479495

480496
signal saved_base_n, saved_base_c: unsigned(base_c'range) := (others => '0');
481497
signal is_base_saved_n, is_base_saved_c: boolean := false;
498+
499+
signal raw_addr: std_ulogic_vector(addr'range) := (others => '0');
500+
signal raw_data: std_ulogic_vector(raw_di'range) := (others => '0');
501+
signal raw_data_we_delayed: std_ulogic := '0';
482502
begin
503+
raw_data_reg: work.util.reg
504+
generic map(g => g, N => raw_di'length)
505+
port map(clk => clk, rst => rst, di => raw_di, we => raw_data_we, do => raw_data);
506+
raw_addr_reg_we: work.util.reg
507+
generic map(g => g, N => 1)
508+
port map(clk => clk, rst => rst, di(0) => raw_addr_we, we => '1', do(0) => raw_data_we_delayed);
509+
510+
-- NB. Auto increment feature on addr might be useful
511+
raw_addr_reg: work.util.reg
512+
generic map(g => g, N => raw_addr'length)
513+
port map(clk => clk, rst => rst, di => raw_di(raw_addr'range), we => raw_addr_we, do => raw_addr);
514+
483515
accumulator_0: work.vga_pkg.atoi
484516
generic map(g => g, N => number)
485517
port map(
@@ -496,11 +528,13 @@ begin
496528
address: block
497529
signal mul: unsigned(15 downto 0) := (others => '0');
498530
signal addr_int: unsigned(addr'range) := (others => '0');
531+
signal addr_cooked: std_ulogic_vector(addr'range) := (others => '0');
499532
begin
500533
mul <= to_unsigned(to_integer(y_c) * width, mul'length);
501534
addr_int <= mul(addr_int'range) + ("000000" & x_c);
502535
addr_sel <= addr_int when state_c /= ERASING else count_c;
503-
addr <= std_ulogic_vector(addr_sel + (base_c & "0000"));
536+
addr_cooked <= std_ulogic_vector(addr_sel + (base_c & "0000"));
537+
addr <= addr_cooked when ctl_c(5) = '0' else raw_addr;
504538
end block;
505539

506540
x_minus_one <= x_c - 1;
@@ -531,28 +565,31 @@ begin
531565
signal vga_ctr: vga_control_registers_interface := vga_control_registers_initialize;
532566
signal attr: unsigned(attr_c'range) := attr_default;
533567
signal ch: std_ulogic_vector(c_c'range) := (others => '0');
568+
signal top_we: std_ulogic := '0';
534569
begin
535570
ch <= std_ulogic_vector(asterisk) when conceal_c else std_ulogic_vector(c_c);
536571
attr <= attr_c when state_c /= ERASING else attr_default;
537-
vga_din <= std_ulogic_vector(attr) & ch;
572+
vga_din <= std_ulogic_vector(attr) & ch when ctl_c(5) = '0' else raw_data;
538573
vga_ctr.crx <= std_ulogic_vector(x_plus_one); -- not limited, goes off screen edge
539574
vga_ctr.cry <= std_ulogic_vector(y_c);
540575
vga_ctr.ctl <= std_ulogic_vector(ctl_c);
541576
vga_ctr_we.crx <= cursor_we;
542577
vga_ctr_we.cry <= cursor_we;
543578
vga_ctr_we.ctl <= cursor_we;
579+
top_we <= data_we when ctl_c(5) = '0' else raw_data_we_delayed;
544580

545581
vga_0: work.vga_pkg.vga_top
546582
generic map(g => g)
547583
port map(
548584
clk => clk,
549585
clk25MHz => clk25MHz,
550586
rst => rst,
551-
vga_we_ram => data_we,
587+
vga_we_ram => top_we,
552588
vga_din => vga_din,
553589
vga_addr => addr,
554590
base(base_c'range)=> std_ulogic_vector(base_c),
555591
base(3 downto 0) => "0000",
592+
raw_do => raw_do,
556593
i_font_sel => font_sel_c,
557594
i_vga_control_we => vga_ctr_we,
558595
i_vga_control => vga_ctr,
@@ -762,6 +799,15 @@ begin
762799
when x"6d" => -- CSI n 'm' : SGR
763800
state_n <= ATTRIB;
764801

802+
when x"68" =>
803+
if n1_c = X"02" then -- 80x40 (in MS-DOS it is 80x25)
804+
ctl_n(5) <= '0';
805+
elsif n1_c = X"05" then -- 320x200 monochrome
806+
ctl_n(5) <= '1';
807+
else
808+
-- unsupported mode
809+
end if;
810+
state_n <= ACCEPT;
765811
-- NB. Number parameter does nothing.
766812
when x"53" => -- CSI n 'S' : scroll up
767813
saved_base_n <= base_c;
@@ -903,6 +949,7 @@ begin
903949
when x"2D" => reverse_video("101", false);
904950
when x"2E" => reverse_video("110", false);
905951
when x"2F" => reverse_video("111", false);
952+
906953
when others =>
907954
end case;
908955
state_n <= ACCEPT;
@@ -938,6 +985,7 @@ entity vga_top is
938985
vga_din: in std_ulogic_vector(15 downto 0);
939986
vga_addr: in std_ulogic_vector(12 downto 0);
940987
base: in std_ulogic_vector(12 downto 0);
988+
raw_do: out std_ulogic_vector(15 downto 0);
941989

942990
-- VGA control registers
943991
i_font_sel: in std_ulogic_vector(0 downto 0);
@@ -1039,7 +1087,7 @@ begin
10391087
a_dre => '1',
10401088
a_addr => vga_addr,
10411089
a_din => vga_din,
1042-
a_dout => open,
1090+
a_dout => raw_do,
10431091
-- Internal interface
10441092
b_clk => clk25MHz,
10451093
b_dwe => '0',
@@ -1087,7 +1135,7 @@ entity vga_core is
10871135
--
10881136
ocrx: in std_ulogic_vector(6 downto 0);
10891137
ocry: in std_ulogic_vector(5 downto 0);
1090-
octl: in std_ulogic_vector(4 downto 0);
1138+
octl: in std_ulogic_vector(5 downto 0);
10911139
--
10921140
o_vga: out vga_physical_interface);
10931141
end entity;
@@ -1126,12 +1174,15 @@ architecture rtl of vga_core is
11261174

11271175
signal bell_c, bell_n: std_ulogic := '0';
11281176
signal bell_on_c, bell_on_n: std_ulogic := '0';
1177+
1178+
signal raw_mode: std_ulogic := '0';
11291179
begin
11301180
-- Control register. Individual control signal
11311181
bell_n <= octl(4);
11321182
bell <= bell_c xor bell_n;
11331183
vga_en <= octl(3);
1134-
cur_en <= octl(2);
1184+
raw_mode <= octl(5);
1185+
cur_en <= octl(2) and not raw_mode;
11351186
cur_blink <= octl(1);
11361187
cur_mode <= octl(0);
11371188

@@ -1205,7 +1256,7 @@ begin
12051256
-- Proboscide99 31/08/08
12061257
blank <= '0' when (hctr < 8) or (hctr > 647) or (vctr > 479) else '1';
12071258

1208-
-- flip-flips for sync of R, G y B signal, initialized with '0'
1259+
-- flip-flops for sync of R, G y B signal, initialized with '0'
12091260
process (rst, clk25MHz)
12101261
begin
12111262
if rst = '1' and g.asynchronous_reset then

0 commit comments

Comments
 (0)