aoc2020/day2/vhdl/parser.vhd

87 lines
1.9 KiB
VHDL
Raw Permalink Normal View History

2020-12-02 11:09:36 +01:00
library ieee;
use ieee.std_logic_1164.all;
entity parser is
port (
clk : in std_logic;
reset : in std_logic;
is_record : in std_logic;
is_data : out std_logic;
char : in character;
num1, num2 : out natural range 0 to 99;
letter : out character
);
end entity;
architecture behaviour of parser is
type state_t is (S_NUM1, S_NUM2, S_LETTER, S_COLON, S_END_SPACE, S_DATA);
signal state : state_t := S_NUM1;
subtype digit is natural range 0 to 9;
type multiples_lookup_t is array(digit) of natural range 0 to 90;
constant TEN_MULTIPLES : multiples_lookup_t := (0, 10, 20, 30, 40, 50, 60, 70, 80, 90);
-- most significant digit of number
signal prev_digit : digit := 0;
signal current_digit : digit;
signal complete_num : natural range 0 to 99;
function char_to_digit(input : in character) return digit is
begin
if input >= '0' and input <= '9' then
2020-12-02 11:09:36 +01:00
return character'pos(input) - character'pos('0');
else
return 0;
end if;
end function;
begin
current_digit <= char_to_digit(char);
complete_num <= TEN_MULTIPLES(prev_digit) + current_digit;
process(clk)
begin
if rising_edge(clk) then
if reset then
prev_digit <= 0;
state <= S_NUM1;
else
prev_digit <= 0;
case state is
when S_NUM1 =>
if is_record then
if char = '-' then
state <= S_NUM2;
else
num1 <= complete_num;
prev_digit <= current_digit;
end if;
end if;
when S_NUM2 =>
if char = ' ' then
state <= S_LETTER;
else
num2 <= complete_num;
prev_digit <= current_digit;
end if;
when S_LETTER =>
letter <= char;
state <= S_COLON;
when S_COLON =>
state <= S_END_SPACE;
when S_END_SPACE =>
state <= S_DATA;
when S_DATA =>
if not is_record then
state <= S_NUM1;
end if;
end case;
end if;
end if;
end process;
is_data <= '1' when state = S_DATA else '0';
end architecture;