-- a simple CPU for driving a vdu component -- copyright: Frank Buss, 2006 -- -- available opcodes: -- -- NOP -- description: no operation -- registers: - -- flags: - -- -- CLEAR -- description: clear screen -- registers: - -- flags: - -- -- WRITE null-terminated string -- description: write null-terminated string -- registers: - -- flags: - -- -- WRITEA -- description: write accu -- registers: - -- flags: - -- -- LDA number -- description: load number in accu -- registers: accu <= number -- flags: - -- -- LDS signal -- description: load signal in accu -- registers: accu <= signal -- flags: - -- -- STS signal -- description: store accu in signal -- registers: signal <= accu -- flags: - -- -- ROR count -- description: rotate accu right by count -- registers: accu <= accu ror count -- flags: - -- -- ROL count -- description: rotate accu left by count -- registers: accu <= accu rol count -- flags: - -- -- TEST bit -- description: test bit in accu -- registers: - -- flags: z <= 1, if bit is set, 0 otherwise -- -- LDX number -- description: load number in x register -- registers: x <= number -- flags: - -- -- LDY number -- description: load number in y register -- registers: y <= number -- flags: - -- -- INCX -- description: increment x by 1 -- registers: x <= x + 1 -- flags: - -- -- INCY -- description: increment y by 1 -- registers: y <= y + 1 -- flags: - -- -- INCA -- description: increment accu by 1 -- registers: accu <= accu + 1 -- flags: - -- -- INCS -- description: increment signal by 1 -- registers: signal <= signal + 1 -- flags: - -- -- CMPX number -- description: compare x with number -- registers: - -- flags: z <= 1, if equal, 0 otherwise -- -- CMPY number -- description: compare y with number -- registers: - -- flags: z <= 1, if equal, 0 otherwise -- -- CMPA number -- description: compare accu with number -- registers: - -- flags: z <= 1, if equal, 0 otherwise -- -- BEQ address -- description: jump to address, if z flag is set -- registers: pc <= address, if z=1 -- flags: - -- -- BNE address -- description: jump to address, if z flag is not set -- registers: pc <= address, if z=0 -- flags: - -- -- JUMP address -- description: jump to address -- registers: pc <= address, if z=0 -- flags: - -- -- WAIT address -- description: wait for 'number' tenths seconds -- registers: - -- flags: - -- -- TXY -- description: swap x and y -- registers: x <= y, y <= x -- flags: - -- -- TAX -- description: swap accu and x -- registers: accu <= x, x <= accu -- flags: - -- -- TAY -- description: swap accu and y -- registers: accu <= y, y <= accu -- flags: - library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- use IEEE.STD_LOGIC_ARITH.ALL; -- use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.NUMERIC_STD.ALL; entity displaytest is port( -- control register interface vdu_clk_in : in std_logic; -- 50MHz System clock -- vga port connections vga_red_o : out std_logic; vga_green_o : out std_logic; vga_blue_o : out std_logic; vga_hsync_o : out std_logic; vga_vsync_o : out std_logic; -- LEDs led : out unsigned(7 downto 0); -- switches switch : in unsigned(7 downto 0); -- buttons button : in unsigned(3 downto 0); -- 7-segement display digit : out unsigned(3 downto 0); segment : out unsigned(7 downto 0) ); end displaytest; architecture arch of displaytest is -- mapped vdu signals signal clk : std_logic; -- 12.5 MHz CPU Clock signal vdu_rst : std_logic; signal vdu_cs : std_logic; signal vdu_rw : std_logic; signal vdu_addr : unsigned(2 downto 0); signal vdu_data_in : unsigned(7 downto 0); signal vdu_data_out : unsigned(7 downto 0); -- local signals -- some counters for testing signal counter_1000hz : unsigned(31 downto 0) := (others => '0'); signal clk_1000hz : std_logic; -- 7 segment position signal digit_position : unsigned(3 downto 0) := (others => '0'); subtype byte is natural range 0 to 255; subtype dword is unsigned(31 downto 0); -- vdu control signals signal vdu_delay_counter : unsigned(31 downto 0) := (others => '0'); signal vdu_delay_clk : std_logic := '0'; signal cmd_count : unsigned(7 downto 0) := (others => '0'); signal bit_pos : unsigned(7 downto 0) := (others => '0'); signal line_bit_pos : unsigned(7 downto 0) := (others => '0'); signal bit_pos4 : unsigned(3 downto 0) := (others => '0'); signal shift_register : unsigned(255 downto 0) := (others => '0'); constant NOP_CODE : natural := 0; constant CLEAR_CODE : natural := 1; constant WRITE_CODE : natural := 2; constant WRITEA_CODE : natural := 3; constant LDA_CODE : natural := 4; constant LDS_CODE : natural := 5; constant STS_CODE : natural := 6; constant ROR_CODE : natural := 7; constant ROL_CODE : natural := 8; constant TEST_CODE : natural := 9; constant LDX_CODE : natural := 10; constant LDY_CODE : natural := 11; constant INCX_CODE : natural := 12; constant INCY_CODE : natural := 13; constant INCA_CODE : natural := 14; constant INCS_CODE : natural := 15; constant CMPX_CODE : natural := 16; constant CMPY_CODE : natural := 17; constant CMPA_CODE : natural := 18; constant BEQ_CODE : natural := 19; constant BNE_CODE : natural := 20; constant JUMP_CODE : natural := 21; constant WAIT_CODE : natural := 22; constant TXY_CODE : natural := 23; constant TAX_CODE : natural := 24; constant TAY_CODE : natural := 25; constant SECONDS_SIGNAL : integer := 255; constant TIMER_SIGNAL : integer := 254; constant LED_SIGNAL : integer := 253; constant CURSOR_X_SIGNAL : integer := 252; constant CURSOR_Y_SIGNAL : integer := 251; constant COLOR_SIGNAL : integer := 250; constant BLACK_COLOR : integer := 0; constant CYAN_COLOR : integer := 6; constant CYAN_INVERSE_COLOR : integer := 96; type cpu_state_type is (load_data, execute_command, write_data); type execute_state_type is ( decode_command, clear_screen, clear_screen_step, write_string, write_string_step, write_accu, write_accu_step, lda_command, lds_command, sts_command, ror_command, rol_command, test_command, ldx_command, ldy_command, incs_command, cmpx_command, cmpy_command, cmpa_command, beq_command, bne_command, jump_command, wait_command, wait_step ); -- cpu signal counter_1hz : dword := (others => '0'); signal seconds : dword := (others => '0'); signal free_counter : dword := (others => '0'); signal wait_counter : dword := (others => '0'); signal wait01_counter : dword := (others => '0'); signal z_flag : std_logic := '0'; signal accu, accu_shift : dword := (others => '0'); signal x_register, y_register : dword := (others => '0'); signal led_cache : byte := 0; signal mem0, mem1, mem2, mem3, mem4 : dword := (others => '0'); signal cpu_state : cpu_state_type := load_data; signal cpu_return_state : cpu_state_type := load_data; signal execute_state : execute_state_type := decode_command; signal write_state : byte := 0; signal pc : byte := 0; signal data : byte := 0; signal x_pos : byte := 0; signal y_pos : byte := 0; signal char : byte := 0; -- color: bit 7: calculated block character, 6-4: background, 3: blink, 2-0 foreground signal color : byte := 0; component vdu port( -- control register interface vdu_clk_in : in std_logic; -- 50MHz System clock cpu_clk_out : out std_logic; -- 12.5 MHz CPU Clock vdu_rst : in std_logic; vdu_cs : in std_logic; vdu_rw : in std_logic; vdu_addr : in unsigned(2 downto 0); vdu_data_in : in unsigned(7 downto 0); vdu_data_out : out unsigned(7 downto 0); -- vga port connections vga_red_o : out std_logic; vga_green_o : out std_logic; vga_blue_o : out std_logic; vga_hsync_o : out std_logic; vga_vsync_o : out std_logic ); end component; begin vdu_instance: vdu port map( vdu_clk_in => vdu_clk_in, cpu_clk_out => clk, vdu_rst => vdu_rst, vdu_cs => vdu_cs, vdu_rw => vdu_rw, vdu_addr => vdu_addr, vdu_data_in => vdu_data_in, vdu_data_out => vdu_data_out, vga_red_o => vga_red_o, vga_green_o => vga_green_o, vga_blue_o => vga_blue_o, vga_hsync_o => vga_hsync_o, vga_vsync_o => vga_vsync_o ); vdu_delay_counter_update: process( clk, vdu_delay_counter ) begin if clk'event and clk = '1' then if vdu_delay_counter = 10 then vdu_delay_counter <= x"00000000"; vdu_delay_clk <= not vdu_delay_clk; else vdu_delay_counter <= vdu_delay_counter + 1; end if; end if; end process; cpu: process( clk ) begin if vdu_delay_clk'event and vdu_delay_clk = '0' then -- update counters if counter_1hz = 625000 then counter_1hz <= x"00000000"; seconds <= seconds + 1; else counter_1hz <= counter_1hz + 1; end if; free_counter <= free_counter + 1; -- CPU implementation case cpu_state is when load_data => case pc is when 0 => data <= LDA_CODE; when 1 => data <= BLACK_COLOR; when 2 => data <= STS_CODE; when 3 => data <= COLOR_SIGNAL; when 4 => data <= CLEAR_CODE; -- draw "a simple CPU" when 5 => data <= LDA_CODE; when 6 => data <= CYAN_COLOR; when 7 => data <= STS_CODE; when 8 => data <= COLOR_SIGNAL; when 9 => data <= LDA_CODE; when 10 => data <= 0; when 11 => data <= STS_CODE; when 12 => data <= CURSOR_X_SIGNAL; when 13 => data <= LDA_CODE; when 14 => data <= 0; when 15 => data <= STS_CODE; when 16 => data <= CURSOR_Y_SIGNAL; when 17 => data <= WRITE_CODE; when 18 => data <= 97; when 19 => data <= 32; when 20 => data <= 115; when 21 => data <= 105; when 22 => data <= 109; when 23 => data <= 112; when 24 => data <= 108; when 25 => data <= 101; when 26 => data <= 32; when 27 => data <= 67; when 28 => data <= 80; when 29 => data <= 85; when 30 => data <= 0; -- draw "charset:" at the next line when 31 => data <= LDA_CODE; when 32 => data <= 0; when 33 => data <= STS_CODE; when 34 => data <= CURSOR_X_SIGNAL; when 35 => data <= INCS_CODE; when 36 => data <= CURSOR_Y_SIGNAL; when 37 => data <= WRITE_CODE; when 38 => data <= 99; when 39 => data <= 104; when 40 => data <= 97; when 41 => data <= 114; when 42 => data <= 115; when 43 => data <= 101; when 44 => data <= 116; when 45 => data <= 58; when 46 => data <= 0; -- draw the character set when 47 => data <= LDA_CODE; when 48 => data <= 0; when 49 => data <= LDY_CODE; when 50 => data <= 0; when 51 => data <= INCS_CODE; when 52 => data <= CURSOR_Y_SIGNAL; when 53 => data <= TAX_CODE; when 54 => data <= LDA_CODE; when 55 => data <= 0; when 56 => data <= STS_CODE; when 57 => data <= CURSOR_X_SIGNAL; when 58 => data <= TAX_CODE; when 59 => data <= LDX_CODE; when 60 => data <= 0; when 61 => data <= WRITEA_CODE; when 62 => data <= INCA_CODE; when 63 => data <= INCX_CODE; when 64 => data <= CMPX_CODE; when 65 => data <= 64; when 66 => data <= BNE_CODE; when 67 => data <= 61; when 68 => data <= WAIT_CODE; when 69 => data <= 5; when 70 => data <= INCY_CODE; when 71 => data <= CMPY_CODE; when 72 => data <= 2; when 73 => data <= BNE_CODE; when 74 => data <= 51; -- draw the calculated character set when 75 => data <= LDA_CODE; when 76 => data <= CYAN_COLOR + 128; when 77 => data <= STS_CODE; when 78 => data <= COLOR_SIGNAL; when 79 => data <= LDA_CODE; when 80 => data <= 0; when 81 => data <= LDY_CODE; when 82 => data <= 0; when 83 => data <= INCS_CODE; when 84 => data <= CURSOR_Y_SIGNAL; when 85 => data <= TAX_CODE; when 86 => data <= LDA_CODE; when 87 => data <= 0; when 88 => data <= STS_CODE; when 89 => data <= CURSOR_X_SIGNAL; when 90 => data <= TAX_CODE; when 91 => data <= LDX_CODE; when 92 => data <= 0; when 93 => data <= WRITEA_CODE; when 94 => data <= INCA_CODE; when 95 => data <= INCX_CODE; when 96 => data <= CMPX_CODE; when 97 => data <= 64; when 98 => data <= BNE_CODE; when 99 => data <= 93; when 100 => data <= WAIT_CODE; when 101 => data <= 5; when 102 => data <= INCY_CODE; when 103 => data <= CMPY_CODE; when 104 => data <= 2; when 105 => data <= BNE_CODE; when 106 => data <= 83; -- draw timer when 107 => data <= LDA_CODE; when 108 => data <= CYAN_COLOR; when 109 => data <= STS_CODE; when 110 => data <= COLOR_SIGNAL; when 111 => data <= LDA_CODE; when 112 => data <= 0; when 113 => data <= STS_CODE; when 114 => data <= CURSOR_X_SIGNAL; when 115 => data <= LDA_CODE; when 116 => data <= 10; when 117 => data <= STS_CODE; when 118 => data <= CURSOR_Y_SIGNAL; when 119 => data <= LDX_CODE; when 120 => data <= 0; when 121 => data <= LDY_CODE; when 122 => data <= 0; when 123 => data <= LDS_CODE; when 124 => data <= SECONDS_SIGNAL; when 125 => data <= TEST_CODE; when 126 => data <= 31; when 127 => data <= TAY_CODE; when 128 => data <= LDA_CODE; when 129 => data <= 48; when 130 => data <= BNE_CODE; when 131 => data <= 134; when 132 => data <= LDA_CODE; when 133 => data <= 49; when 134 => data <= WRITEA_CODE; when 135 => data <= TAY_CODE; when 136 => data <= ROL_CODE; when 137 => data <= 1; when 138 => data <= INCX_CODE; when 139 => data <= CMPX_CODE; when 140 => data <= 32; when 141 => data <= BNE_CODE; when 142 => data <= 125; -- draw "tick/tack", with 'tick' or 'tack' inverted every second when 143 => data <= LDA_CODE; when 144 => data <= 0; when 145 => data <= STS_CODE; when 146 => data <= CURSOR_X_SIGNAL; when 147 => data <= LDA_CODE; when 148 => data <= 12; when 149 => data <= STS_CODE; when 150 => data <= CURSOR_Y_SIGNAL; when 151 => data <= LDS_CODE; when 152 => data <= SECONDS_SIGNAL; when 153 => data <= TEST_CODE; when 154 => data <= 0; when 155 => data <= LDX_CODE; when 156 => data <= CYAN_COLOR; when 157 => data <= LDY_CODE; when 158 => data <= CYAN_INVERSE_COLOR; when 159 => data <= BNE_CODE; when 160 => data <= 162; when 161 => data <= TXY_CODE; when 162 => data <= TAX_CODE; when 163 => data <= STS_CODE; when 164 => data <= COLOR_SIGNAL; when 165 => data <= TAX_CODE; when 166 => data <= WRITE_CODE; -- tick when 167 => data <= 116; when 168 => data <= 105; when 169 => data <= 99; when 170 => data <= 107; when 171 => data <= 0; when 172 => data <= LDA_CODE; when 173 => data <= CYAN_COLOR; when 174 => data <= STS_CODE; when 175 => data <= COLOR_SIGNAL; when 176 => data <= LDA_CODE; when 177 => data <= 47; -- '/' when 178 => data <= WRITEA_CODE; when 179 => data <= TXY_CODE; when 180 => data <= TAX_CODE; when 181 => data <= STS_CODE; when 182 => data <= COLOR_SIGNAL; when 183 => data <= WRITE_CODE; -- tack when 184 => data <= 116; when 185 => data <= 97; when 186 => data <= 99; when 187 => data <= 107; when 188 => data <= 0; when 189 => data <= JUMP_CODE; when 190 => data <= 107; when others => pc <= 0; data <= 0; end case; cpu_state <= execute_command; pc <= pc + 1; when execute_command => case execute_state is when decode_command => case data is when NOP_CODE => execute_state <= decode_command; cpu_state <= load_data; when CLEAR_CODE => x_pos <= 0; y_pos <= 0; char <= 32; execute_state <= clear_screen; when WRITE_CODE => execute_state <= write_string; cpu_state <= load_data; when WRITEA_CODE => execute_state <= write_accu; when LDA_CODE => execute_state <= lda_command; cpu_state <= load_data; when LDS_CODE => execute_state <= lds_command; cpu_state <= load_data; when STS_CODE => execute_state <= sts_command; cpu_state <= load_data; when ROR_CODE => execute_state <= ror_command; cpu_state <= load_data; when ROL_CODE => execute_state <= rol_command; cpu_state <= load_data; when TEST_CODE => execute_state <= test_command; cpu_state <= load_data; when LDX_CODE => execute_state <= ldx_command; cpu_state <= load_data; when LDY_CODE => execute_state <= ldy_command; cpu_state <= load_data; when INCX_CODE => x_register <= x_register + 1; execute_state <= decode_command; cpu_state <= load_data; when INCY_CODE => y_register <= y_register + 1; execute_state <= decode_command; cpu_state <= load_data; when INCA_CODE => accu <= accu + 1; execute_state <= decode_command; cpu_state <= load_data; when INCS_CODE => execute_state <= incs_command; cpu_state <= load_data; when CMPX_CODE => execute_state <= cmpx_command; cpu_state <= load_data; when CMPY_CODE => execute_state <= cmpy_command; cpu_state <= load_data; when CMPA_CODE => execute_state <= cmpa_command; cpu_state <= load_data; when BEQ_CODE => execute_state <= beq_command; cpu_state <= load_data; when BNE_CODE => execute_state <= bne_command; cpu_state <= load_data; when JUMP_CODE => execute_state <= jump_command; cpu_state <= load_data; when WAIT_CODE => execute_state <= wait_command; cpu_state <= load_data; when TXY_CODE => x_register <= y_register; y_register <= x_register; execute_state <= decode_command; cpu_state <= load_data; when TAX_CODE => accu <= x_register; x_register <= accu; execute_state <= decode_command; cpu_state <= load_data; when TAY_CODE => accu <= y_register; y_register <= accu; execute_state <= decode_command; cpu_state <= load_data; when others => cpu_state <= load_data; pc <= 0; end case; -- CLEAR implementation when clear_screen => execute_state <= clear_screen_step; cpu_return_state <= execute_command; cpu_state <= write_data; when clear_screen_step => char <= char + 1; if x_pos = 79 then if y_pos = 24 then cpu_state <= load_data; execute_state <= decode_command; else x_pos <= 0; y_pos <= y_pos + 1; execute_state <= clear_screen; end if; else x_pos <= x_pos + 1; execute_state <= clear_screen; end if; -- WRITE implementation when write_string => if data = 0 then execute_state <= decode_command; cpu_state <= load_data; else char <= data; execute_state <= write_string_step; cpu_state <= write_data; cpu_return_state <= execute_command; end if; when write_string_step => if x_pos = 79 then if y_pos = 24 then y_pos <= 0; else y_pos <= y_pos + 1; end if; x_pos <= 0; else x_pos <= x_pos + 1; end if; execute_state <= write_string; cpu_state <= load_data; -- WRITEA implementation when write_accu => char <= to_integer(accu(7 downto 0)); execute_state <= write_accu_step; cpu_state <= write_data; cpu_return_state <= execute_command; when write_accu_step => if x_pos = 79 then if y_pos = 24 then y_pos <= 0; else y_pos <= y_pos + 1; end if; x_pos <= 0; else x_pos <= x_pos + 1; end if; execute_state <= decode_command; cpu_state <= load_data; -- LDA implementation when lda_command => accu <= x"000000" & to_unsigned(data, 8); execute_state <= decode_command; cpu_state <= load_data; -- LDS implementation when lds_command => case data is when 0 => accu <= mem0; when 1 => accu <= mem1; when 2 => accu <= mem2; when 3 => accu <= mem3; when SECONDS_SIGNAL => accu <= seconds; when TIMER_SIGNAL => accu <= free_counter; when LED_SIGNAL => accu <= x"000000" & to_unsigned(led_cache, 8); when CURSOR_X_SIGNAL => accu <= x"000000" & to_unsigned(x_pos, 8); when CURSOR_Y_SIGNAL => accu <= x"000000" & to_unsigned(y_pos, 8); when COLOR_SIGNAL => accu <= x"000000" & to_unsigned(color, 8); when others => accu <= x"00000000"; end case; execute_state <= decode_command; cpu_state <= load_data; -- STS implementation when sts_command => case data is when 0 => mem0 <= accu; when 1 => mem1 <= accu; when 2 => mem2 <= accu; when 3 => mem3 <= accu; when SECONDS_SIGNAL => seconds <= accu; when TIMER_SIGNAL => free_counter <= accu; when LED_SIGNAL => led_cache <= to_integer(accu(7 downto 0)); led <= accu(7 downto 0); when CURSOR_X_SIGNAL => x_pos <= to_integer(accu(7 downto 0)); when CURSOR_Y_SIGNAL => y_pos <= to_integer(accu(7 downto 0)); when COLOR_SIGNAL => color <= to_integer(accu(7 downto 0)); when others => accu <= accu; end case; execute_state <= decode_command; cpu_state <= load_data; -- ROR implementation when ror_command => accu <= rotate_right(accu, data); execute_state <= decode_command; cpu_state <= load_data; -- ROL implementation when rol_command => accu <= rotate_left(accu, data); execute_state <= decode_command; cpu_state <= load_data; -- TEST implementation when test_command => if accu(data) = '1' then z_flag <= '1'; else z_flag <= '0'; end if; execute_state <= decode_command; cpu_state <= load_data; -- LDX implementation when ldx_command => x_register <= x"000000" & to_unsigned(data, 8); execute_state <= decode_command; cpu_state <= load_data; -- LDY implementation when ldy_command => y_register <= x"000000" & to_unsigned(data, 8); execute_state <= decode_command; cpu_state <= load_data; -- INCS implementation when incs_command => case data is when 0 => mem0 <= mem0 + 1; when 1 => mem1 <= mem1 + 1; when 2 => mem2 <= mem2 + 1; when 3 => mem3 <= mem3 + 1; when SECONDS_SIGNAL => seconds <= seconds + 1; when TIMER_SIGNAL => free_counter <= free_counter + 1; when LED_SIGNAL => led <= to_unsigned(led_cache + 1, 8); led_cache <= led_cache + 1; when CURSOR_X_SIGNAL => x_pos <= x_pos + 1; when CURSOR_Y_SIGNAL => y_pos <= y_pos + 1; when COLOR_SIGNAL => color <= color + 1; when others => accu <= accu; end case; execute_state <= decode_command; cpu_state <= load_data; -- CMPX implementation when cmpx_command => if x_register = data then z_flag <= '1'; else z_flag <= '0'; end if; execute_state <= decode_command; cpu_state <= load_data; -- CMPY implementation when cmpy_command => if y_register = data then z_flag <= '1'; else z_flag <= '0'; end if; execute_state <= decode_command; cpu_state <= load_data; -- CMPA implementation when cmpa_command => if accu = data then z_flag <= '1'; else z_flag <= '0'; end if; execute_state <= decode_command; cpu_state <= load_data; -- BEQ implementation when beq_command => if z_flag = '1' then pc <= data; end if; execute_state <= decode_command; cpu_state <= load_data; -- BNE implementation when bne_command => if z_flag = '0' then pc <= data; end if; execute_state <= decode_command; cpu_state <= load_data; -- JUMP implementation when jump_command => pc <= data; execute_state <= decode_command; cpu_state <= load_data; -- WAIT implementation when wait_command => wait01_counter <= to_unsigned(data, 32); wait_counter <= x"00000000"; execute_state <= wait_step; when wait_step => if wait_counter = 62500 then wait_counter <= x"00000000"; if wait01_counter = 0 then execute_state <= decode_command; cpu_state <= load_data; else wait01_counter <= wait01_counter - 1; end if; else wait_counter <= wait_counter + 1; end if; end case; when write_data => case write_state is -- write x_pos when 0 => vdu_cs <= '0'; write_state <= 1; when 1 => vdu_addr <= b"010"; vdu_data_in <= to_unsigned(x_pos, 8); write_state <= 2; when 2 => vdu_cs <= '1'; write_state <= 3; -- write y_pos when 3 => vdu_cs <= '0'; write_state <= 4; when 4 => vdu_addr <= b"011"; vdu_data_in <= to_unsigned(y_pos, 8); write_state <= 5; when 5 => vdu_cs <= '1'; write_state <= 6; -- write color when 6 => vdu_cs <= '0'; write_state <= 7; when 7 => vdu_addr <= b"001"; vdu_data_in <= to_unsigned(color, 8); write_state <= 8; when 8 => vdu_cs <= '1'; write_state <= 9; -- write char when 9 => vdu_cs <= '0'; write_state <= 10; when 10 => vdu_addr <= b"000"; vdu_data_in <= to_unsigned(char, 8); write_state <= 11; when 11 => vdu_cs <= '1'; cpu_state <= cpu_return_state; write_state <= 0; when others => cpu_state <= cpu_return_state; end case; end case; end if; end process; counter_1000hz_update: process ( clk ) begin if clk'event and clk = '1' then if counter_1000hz = 6250 then counter_1000hz <= x"00000000"; clk_1000hz <= not clk_1000hz; else counter_1000hz <= counter_1000hz + 1; end if; end if; end process; led_7segment_update: process ( clk ) begin if clk_1000hz'event and clk_1000hz = '1' then if digit_position = 4 then digit_position <= x"0"; else case digit_position is when x"0" => digit <= b"1110"; segment <= x"8c"; when x"1" => digit <= b"1101"; segment <= x"92"; when x"2" => digit <= b"1011"; segment <= x"cf"; when x"3" => digit <= b"0111"; segment <= x"c7"; when others => digit_position <= x"0"; end case; digit_position <= digit_position + 1; end if; end if; end process; end arch;