history/display: backspace logic
[hwmod.git] / src / display.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4 use work.gen_pkg.all;
5 use work.textmode_vga_component_pkg.all;
6 use work.textmode_vga_pkg.all;
7 use work.textmode_vga_platform_dependent_pkg.all;
8
9 entity display is
10         port (
11                 sys_clk : in std_logic;
12                 sys_res_n : in std_logic;
13                 -- History
14                 d_new_eingabe : in std_logic;
15                 d_new_result : in std_logic;
16                 d_new_bs : in std_logic;
17                 d_zeile : out hzeile;
18                 d_spalte : out hspalte;
19                 d_get : out std_logic;
20                 d_done : in std_logic;
21                 d_char : in hbyte;
22                 -- VGA
23                 command : out std_logic_vector(7 downto 0);
24                 command_data : out std_logic_vector(31 downto 0);
25                 free : in std_logic
26         );
27 end entity display;
28
29 architecture beh of display is
30         type DISPLAY_STATE is (SIDLE, S_NEW_BS, S_BACK, S_BLANK, S_NEW_RESULT,
31                 S_NEW_INPUT, S_COUNTUP, S_GETCH, S_CR1, S_NL1, S_PUTCH1, S_PUTCH2,
32                 S_WAIT, S_NOP1);
33         signal state_int, state_next : DISPLAY_STATE;
34         signal d_zeile_int, d_zeile_next : hzeile;
35         signal d_spalte_int, d_spalte_next : hspalte;
36         signal d_get_int, d_get_next : std_logic;
37         signal command_int, command_next : std_logic_vector(7 downto 0);
38         signal command_data_int, command_data_next : std_logic_vector(31 downto 0);
39         signal istate_next, istate_int : signed(2 downto 0);
40 begin
41         d_zeile <= d_zeile_int;
42         d_spalte <= d_spalte_int;
43         d_get <= d_get_int;
44         command <= command_int;
45         command_data <= command_data_int;
46
47         process(sys_clk, sys_res_n)
48         begin
49                 if sys_res_n = '0' then
50                         -- internal
51                         state_int <= SIDLE;
52                         istate_int <= (others => '0');
53                         -- out
54                         d_zeile_int <= (others => '0');
55                         d_spalte_int <= (others => '0');
56                         d_get_int <= '0';
57                         command_int <= COMMAND_NOP;
58                         command_data_int <= (others => '0');
59                 elsif rising_edge(sys_clk) then
60                         -- internal
61                         state_int <= state_next;
62                         istate_int <= istate_next;
63                         -- out
64                         d_zeile_int <= d_zeile_next;
65                         d_spalte_int <= d_spalte_next;
66                         d_get_int <= d_get_next;
67                         command_int <= command_next;
68                         command_data_int <= command_data_next;
69                 end if;
70         end process;
71
72         -- next state
73         process(state_int, d_new_result, d_new_eingabe, d_new_bs, d_done, free,
74                 d_spalte_int, d_char, istate_int)
75         begin
76                 state_next <= state_int;
77                 istate_next <= istate_int;
78
79                 case state_int is
80                         when SIDLE =>
81                                 istate_next <= b"111"; -- default: immer wieder ins SIDLE;
82                                 if d_new_bs = '1' then
83                                         state_next <= S_NEW_BS;
84                                 elsif d_new_eingabe = '1' then
85                                         state_next <= S_NEW_INPUT;
86                                 end if;
87                                 if d_new_result = '1' then
88                                         state_next <= S_NEW_RESULT;
89                                 end if;
90
91                         when S_NEW_RESULT =>
92                                 state_next <= S_CR1;
93                         when S_NEW_INPUT =>
94                                 state_next <= S_COUNTUP;
95
96                         when S_NEW_BS =>
97                                 state_next <= S_BACK;
98                         when S_BACK =>
99                                 if free = '0' then
100                                         state_next <= S_WAIT;
101                                         case istate_int is
102                                                 when b"111" => istate_next <= b"001"; -- => danach S_BLANK und wieder hierher
103                                                 when others => istate_next <= b"111"; -- => danach SIDLE
104                                         end case;
105                                 end if;
106                         when S_BLANK =>
107                                 if free = '0' then
108                                         state_next <= S_WAIT;
109                                         istate_next <= b"010"; -- => danach S_BACK
110                                 end if;
111
112                         when S_CR1 =>
113                                 if free = '0' then
114                                         state_next <= S_WAIT;
115                                         istate_next <= b"000"; -- => danach S_NL1
116                                 end if;
117                         when S_NL1 =>
118                                 if free = '0' then
119                                         state_next <= S_WAIT;
120                                         istate_next <= b"111"; -- => wieder nach SIDLE
121                                 end if;
122
123                         when S_COUNTUP =>
124                                 state_next <= S_GETCH;
125                         when S_GETCH =>
126                                 if free = '1' and d_done = '1' and d_new_result = '0' and d_new_eingabe = '0' then
127                                         state_next <= S_PUTCH1;
128                                 end if;
129                         when S_PUTCH1 =>
130                                 state_next <= S_PUTCH2;
131                         when S_PUTCH2 =>
132                                 if free = '0' or (free = '1' and d_char = x"00") then
133                                         state_next <= S_WAIT;
134                                 end if;
135                         when S_WAIT =>
136                                 if free = '1' and d_done = '0' then
137                                         state_next <= S_NOP1;
138                                 end if;
139                         when S_NOP1 =>
140                                 if free = '1' then
141                                         case istate_int is
142                                                 when b"000" => state_next <= S_NL1;
143                                                 when b"001" => state_next <= S_BLANK;
144                                                 when b"010" => state_next <= S_BACK;
145                                                 when others => state_next <= SIDLE;
146                                         end case;
147                                 end if;
148                 end case;
149         end process;
150
151         -- out
152         process(state_int, d_zeile_int, d_spalte_int, d_get_int, command_int,
153                 command_data_int, d_char)
154         begin
155                 d_zeile_next <= d_zeile_int;
156                 d_spalte_next <= d_spalte_int;
157                 d_get_next <= '0';
158                 command_next <= command_int;
159                 command_data_next <= command_data_int;
160
161                 case state_int is
162                         when SIDLE =>
163                                 null;
164                         when S_NEW_RESULT =>
165                                 d_spalte_next <= (others => '0');
166                                 case d_zeile_int is
167                                         when "11111" => d_zeile_next <= "00000";
168                                         when others => d_zeile_next <= std_logic_vector(unsigned(d_zeile_int) + 1);
169                                 end case;
170                         when S_NEW_INPUT =>
171                                 null;
172
173                         when S_NEW_BS =>
174                                 -- underflow check schon im history modul
175                                 d_spalte_next <= std_logic_vector(unsigned(d_spalte_int) - 1);
176                         when S_BACK =>
177                                 -- einen schritt zurueck
178                                 command_next <= COMMAND_SET_CURSOR_COLUMN;
179                                 command_data_next <= x"ffffff" & '0' & std_logic_vector(unsigned(d_spalte_int));
180                         when S_BLANK =>
181                                 command_next <= COMMAND_SET_CHAR;
182                                 command_data_next <= x"ffffff" & x"20"; -- white space
183
184                         when S_CR1 =>
185                                 command_next <= COMMAND_SET_CHAR;
186                                 command_data_next <= x"ffffff" & x"0d"; -- carrige return
187                         when S_NL1 =>
188                                 command_next <= COMMAND_SET_CHAR;
189                                 command_data_next <= x"ffffff" & x"0a"; -- newline
190
191                         when S_COUNTUP =>
192                                 d_get_next <= '1';
193                                 d_spalte_next <= std_logic_vector(unsigned(d_spalte_int) + 1);
194                         when S_GETCH =>
195                                 d_get_next <= '1';
196                         when S_PUTCH1 =>
197                                 if d_char /= x"00" then
198                                         command_next <= COMMAND_SET_CHAR;
199                                         command_data_next <= x"ffffff" & std_logic_vector(d_char);
200                                 end if;
201                         when S_PUTCH2 => null;
202                         when S_WAIT | S_NOP1 =>
203                                 command_next <= COMMAND_NOP;
204                                 command_data_next <= x"00000000";
205                 end case;
206         end process;
207 end architecture beh;