Skip to content

Instantly share code, notes, and snippets.

@fohte
Created January 18, 2017 13:28
Show Gist options
  • Save fohte/8089276bf5c30e3bbbe2c6de1c23879e to your computer and use it in GitHub Desktop.
Save fohte/8089276bf5c30e3bbbe2c6de1c23879e to your computer and use it in GitHub Desktop.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity calc is
generic (
DIV_BITS: integer := 20;
SEGMENT_CLEAR: std_logic_vector(7 downto 0) := "11111111";
SEGMENT_0: std_logic_vector(7 downto 0) := "00000011";
SEGMENT_1: std_logic_vector(7 downto 0) := "10011111";
SEGMENT_2: std_logic_vector(7 downto 0) := "00100101";
SEGMENT_3: std_logic_vector(7 downto 0) := "00001101";
SEGMENT_4: std_logic_vector(7 downto 0) := "10011001";
SEGMENT_5: std_logic_vector(7 downto 0) := "01001001";
SEGMENT_6: std_logic_vector(7 downto 0) := "01000001";
SEGMENT_7: std_logic_vector(7 downto 0) := "00011111";
SEGMENT_8: std_logic_vector(7 downto 0) := "00000001";
SEGMENT_9: std_logic_vector(7 downto 0) := "00001001";
SEGMENT_PLUS: std_logic_vector(7 downto 0) := "10011101";
SEGMENT_MINUS: std_logic_vector(7 downto 0) := "11111101";
SEGMENT_TIMES: std_logic_vector(7 downto 0) := "10010001";
SEGMENT_DIVIDE: std_logic_vector(7 downto 0) := "10110101"
);
port (
clk: in std_logic;
sw1, sw2, sw3, sw4: in std_logic;
led_left, led_center, led_right: out std_logic_vector(7 downto 0)
);
end calc;
architecture rtl of calc is
-- state machine
type NUMBER_STATE is (NUM_0, NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9);
type OPERATOR_STATE is (OP_PLUS, OP_MINUS, OP_TIMES, OP_DIVIDE);
type MODE_STATE is (MODE_INPUT, MODE_RESULT);
-- mode
signal current_mode: MODE_STATE := MODE_INPUT;
signal next_mode: MODE_STATE;
-- for result mode
signal result: integer := 0;
signal first_digit_led, second_digit_led: std_logic_vector(7 downto 0);
signal first_digit, second_digit: integer := 0;
-- for input mode
signal left_item_state, left_item_next_state, right_item_state, right_item_next_state: NUMBER_STATE;
signal op_state, op_next_state: OPERATOR_STATE;
signal left_item, right_item: integer := 0;
signal left_item_led, right_item_led, center_item_led: std_logic_vector(7 downto 0);
-- switch
signal clk_sw: std_logic := '0';
signal div_counter: std_logic_vector(DIV_BITS - 1 downto 0) := (others => '0');
signal sw1_latch_on, sw2_latch_on, sw3_latch_on, sw4_latch_on: std_logic := '0';
signal sw1_node, sw2_node, sw3_node, sw4_node: std_logic := '1';
begin
process (clk)
begin
if clk'event and clk = '1' then
div_counter <= div_counter + 1;
end if;
end process;
clk_sw <= div_counter(DIV_BITS - 1);
process (clk_sw)
begin
if clk_sw'event and clk_sw = '1' then
sw1_node <= sw1;
sw2_node <= sw2;
sw3_node <= sw3;
sw4_node <= sw4;
end if;
end process;
process (clk)
begin
if clk'event and clk = '1' then
if sw1_node = '0' and sw1_latch_on = '0' then
sw1_latch_on <= '1';
elsif sw1_node = '1' and sw1_latch_on = '1' then
sw1_latch_on <= '0';
elsif sw1_node = '0' and sw1_latch_on = '1' then
sw1_latch_on <= '1';
end if;
end if;
end process;
process (clk)
begin
if clk'event and clk = '1' then
if sw2_node = '0' and sw2_latch_on = '0' then
sw2_latch_on <= '1';
elsif sw2_node = '1' and sw2_latch_on = '1' then
sw2_latch_on <= '0';
elsif sw2_node = '0' and sw2_latch_on = '1' then
sw2_latch_on <= '1';
end if;
end if;
end process;
process (clk)
begin
if clk'event and clk = '1' then
if sw3_node = '0' and sw3_latch_on = '0' then
sw3_latch_on <= '1';
elsif sw3_node = '1' and sw3_latch_on = '1' then
sw3_latch_on <= '0';
elsif sw3_node = '0' and sw3_latch_on = '1' then
sw3_latch_on <= '1';
end if;
end if;
end process;
process (clk)
begin
if clk'event and clk = '1' then
if sw4_node = '0' and sw4_latch_on = '0' then
sw4_latch_on <= '1';
elsif sw4_node = '1' and sw4_latch_on = '1' then
sw4_latch_on <= '0';
elsif sw4_node = '0' and sw4_latch_on = '1' then
sw4_latch_on <= '1';
end if;
end if;
end process;
-- press the switching left number button (SW4)
process (sw4_latch_on)
begin
if sw4_latch_on = '1' then
left_item_state <= left_item_next_state;
end if;
end process;
-- change the left number
process (left_item_state)
begin
case left_item_state is
when NUM_0 =>
left_item_led <= SEGMENT_0;
left_item <= 0;
left_item_next_state <= NUM_1;
when NUM_1 =>
left_item_led <= SEGMENT_1;
left_item <= 1;
left_item_next_state <= NUM_2;
when NUM_2 =>
left_item_led <= SEGMENT_2;
left_item <= 2;
left_item_next_state <= NUM_3;
when NUM_3 =>
left_item_led <= SEGMENT_3;
left_item <= 3;
left_item_next_state <= NUM_4;
when NUM_4 =>
left_item_led <= SEGMENT_4;
left_item <= 4;
left_item_next_state <= NUM_5;
when NUM_5 =>
left_item_led <= SEGMENT_5;
left_item <= 5;
left_item_next_state <= NUM_6;
when NUM_6 =>
left_item_led <= SEGMENT_6;
left_item <= 6;
left_item_next_state <= NUM_7;
when NUM_7 =>
left_item_led <= SEGMENT_7;
left_item <= 7;
left_item_next_state <= NUM_8;
when NUM_8 =>
left_item_led <= SEGMENT_8;
left_item <= 8;
left_item_next_state <= NUM_9;
when NUM_9 =>
left_item_led <= SEGMENT_9;
left_item <= 9;
left_item_next_state <= NUM_0;
when others => null;
end case;
end process;
-- press the switching right number button (SW2)
process (sw2_latch_on)
begin
if sw2_latch_on = '1' then
right_item_state <= right_item_next_state;
end if;
end process;
-- change the right number
process (right_item_state)
begin
case right_item_state is
when NUM_0 =>
right_item_led <= SEGMENT_0;
right_item <= 0;
right_item_next_state <= NUM_1;
when NUM_1 =>
right_item_led <= SEGMENT_1;
right_item <= 1;
right_item_next_state <= NUM_2;
when NUM_2 =>
right_item_led <= SEGMENT_2;
right_item <= 2;
right_item_next_state <= NUM_3;
when NUM_3 =>
right_item_led <= SEGMENT_3;
right_item <= 3;
right_item_next_state <= NUM_4;
when NUM_4 =>
right_item_led <= SEGMENT_4;
right_item <= 4;
right_item_next_state <= NUM_5;
when NUM_5 =>
right_item_led <= SEGMENT_5;
right_item <= 5;
right_item_next_state <= NUM_6;
when NUM_6 =>
right_item_led <= SEGMENT_6;
right_item <= 6;
right_item_next_state <= NUM_7;
when NUM_7 =>
right_item_led <= SEGMENT_7;
right_item <= 7;
right_item_next_state <= NUM_8;
when NUM_8 =>
right_item_led <= SEGMENT_8;
right_item <= 8;
right_item_next_state <= NUM_9;
when NUM_9 =>
right_item_led <= SEGMENT_9;
right_item <= 9;
right_item_next_state <= NUM_0;
when others => null;
end case;
end process;
-- press the switching operator button (SW3)
process (sw3_latch_on)
begin
if sw3_latch_on = '1' then
op_state <= op_next_state;
end if;
end process;
-- change the operator
process (op_state)
begin
case op_state is
when OP_PLUS =>
center_item_led <= SEGMENT_PLUS;
op_next_state <= OP_MINUS;
when OP_MINUS =>
center_item_led <= SEGMENT_MINUS;
op_next_state <= OP_TIMES;
when OP_TIMES =>
center_item_led <= SEGMENT_TIMES;
op_next_state <= OP_DIVIDE;
when OP_DIVIDE =>
center_item_led <= SEGMENT_DIVIDE;
op_next_state <= OP_PLUS;
when others => null;
end case;
end process;
-- press the mode change button (SW1)
process (sw1_latch_on)
begin
if sw1_latch_on = '1' then
current_mode <= next_mode;
end if;
end process;
-- change mode
process (current_mode)
begin
case current_mode is
when MODE_INPUT =>
next_mode <= MODE_RESULT;
when MODE_RESULT =>
case op_state is
when OP_PLUS =>
result <= left_item + right_item;
when OP_MINUS =>
result <= left_item - right_item;
when OP_TIMES =>
result <= left_item * right_item;
when OP_DIVIDE =>
result <= left_item / right_item;
when others => null;
end case;
-- first_digit <= result mod 10;
first_digit <= (result - (10 * (result / 10)));
-- second_digit <= result mod 100 - first_digit;
second_digit <= (result - (100 * (result / 100))) - first_digit;
next_mode <= MODE_INPUT;
when others => null;
end case;
end process;
process (first_digit)
begin
case first_digit is
when 0 =>
first_digit_led <= SEGMENT_0;
when 1 =>
first_digit_led <= SEGMENT_1;
when 2 =>
first_digit_led <= SEGMENT_2;
when 3 =>
first_digit_led <= SEGMENT_3;
when 4 =>
first_digit_led <= SEGMENT_4;
when 5 =>
first_digit_led <= SEGMENT_5;
when 6 =>
first_digit_led <= SEGMENT_6;
when 7 =>
first_digit_led <= SEGMENT_7;
when 8 =>
first_digit_led <= SEGMENT_8;
when 9 =>
first_digit_led <= SEGMENT_9;
when others => null;
end case;
end process;
process (second_digit)
begin
case second_digit is
when 0 =>
second_digit_led <= SEGMENT_CLEAR;
when 1 =>
second_digit_led <= SEGMENT_1;
when 2 =>
second_digit_led <= SEGMENT_2;
when 3 =>
second_digit_led <= SEGMENT_3;
when 4 =>
second_digit_led <= SEGMENT_4;
when 5 =>
second_digit_led <= SEGMENT_5;
when 6 =>
second_digit_led <= SEGMENT_6;
when 7 =>
second_digit_led <= SEGMENT_7;
when 8 =>
second_digit_led <= SEGMENT_8;
when 9 =>
second_digit_led <= SEGMENT_9;
when others => null;
end case;
end process;
-- output led
process (sw1_latch_on, sw2_latch_on, sw3_latch_on, sw4_latch_on)
begin
case current_mode is
when MODE_INPUT =>
led_left <= left_item_led;
led_center <= center_item_led;
led_right <= right_item_led;
when MODE_RESULT =>
led_right <= first_digit_led;
led_center <= second_digit_led;
led_left <= SEGMENT_CLEAR;
when others => null;
end case;
end process;
end rtl;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment