diff --git a/sap_1.gprj b/sap_1.gprj
index 6c2240e..66f8cd9 100644
--- a/sap_1.gprj
+++ b/sap_1.gprj
@@ -5,8 +5,10 @@
5
gw1nr9c-004
-
+
+
+
diff --git a/sap_1.gprj.user b/sap_1.gprj.user
index bb19da1..62cdfa8 100644
--- a/sap_1.gprj.user
+++ b/sap_1.gprj.user
@@ -4,8 +4,8 @@
1.0
-
-
+
+
@@ -20,5 +20,5 @@
- 000000ff00000001fd0000000200000000000001000000025ffc0200000001fc0000003f0000025f0000009a01000018fa000000010200000003fb00000030004600700067006100500072006f006a006500630074002e00500061006e0065006c002e00440065007300690067006e0100000000ffffffff0000006600fffffffb00000032004600700067006100500072006f006a006500630074002e00500061006e0065006c002e00500072006f00630065007300730100000000ffffffff0000006200fffffffb00000036004600700067006100500072006f006a006500630074002e00500061006e0065006c002e0048006900650072006100720063006800790100000000ffffffff0000008100ffffff000000030000050000000110fc0100000001fc00000000000005000000009e00fffffffa000000000100000002fb00000032004600700067006100500072006f006a006500630074002e00500061006e0065006c002e00470065006e006500720061006c0100000000ffffffff0000004d00fffffffb0000002e004600700067006100500072006f006a006500630074002e00500061006e0065006c002e004900730073007500650100000000ffffffff0000009e00ffffff000003fa0000025f00000004000000040000000800000008fc000000010000000200000004000000220043006f00720065002e0054006f006f006c006200610072002e00460069006c00650100000000ffffffff0000000000000000000000220043006f00720065002e0054006f006f006c006200610072002e004500640069007401000000b6ffffffff0000000000000000000000240043006f00720065002e0054006f006f006c006200610072002e0054006f006f006c00730100000195ffffffff0000000000000000ffffffff0100000264ffffffff0000000000000000
+ 000000ff00000001fd0000000200000000000001000000025ffc0200000001fc0000003f0000025f0000000000fffffffaffffffff0200000003fb00000030004600700067006100500072006f006a006500630074002e00500061006e0065006c002e00440065007300690067006e0100000000ffffffff0000000000000000fb00000032004600700067006100500072006f006a006500630074002e00500061006e0065006c002e00500072006f00630065007300730100000000ffffffff0000000000000000fb00000036004600700067006100500072006f006a006500630074002e00500061006e0065006c002e0048006900650072006100720063006800790100000000ffffffff0000000000000000000000030000050000000110fc0100000001fc00000000000005000000009e00fffffffa000000000100000002fb00000032004600700067006100500072006f006a006500630074002e00500061006e0065006c002e00470065006e006500720061006c0100000000ffffffff0000004d00fffffffb0000002e004600700067006100500072006f006a006500630074002e00500061006e0065006c002e004900730073007500650100000000ffffffff0000009e00ffffff000003fa0000025f00000004000000040000000800000008fc000000010000000200000003000000220043006f00720065002e0054006f006f006c006200610072002e00460069006c00650100000000ffffffff0000000000000000000000220043006f00720065002e0054006f006f006c006200610072002e004500640069007401000000b6ffffffff0000000000000000000000240043006f00720065002e0054006f006f006c006200610072002e0054006f006f006c00730100000195ffffffff0000000000000000
diff --git a/src/Binary_To_7_Segment_Decoder.vhd b/src/Binary_To_7_Segment_Decoder.vhd
new file mode 100644
index 0000000..b629a8b
--- /dev/null
+++ b/src/Binary_To_7_Segment_Decoder.vhd
@@ -0,0 +1,83 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity Binary_To_7_Segment_Decoder is
+ port (
+ i_Clk : in std_logic; -- Clock
+ i_Num : in std_logic_vector(15 downto 0); -- 4 Digit hex number
+ o_D1, o_D2, o_D3, o_D4 : out std_logic; -- 7 segment display selector
+ o_A, o_B, o_C, o_D, o_E, o_F, o_G : out std_logic -- 7 segment display segments
+ );
+end Binary_To_7_Segment_Decoder;
+
+architecture rtl of Binary_To_7_Segment_Decoder is
+ signal w_First_Digit, w_Second_Digit, w_Third_Digit, w_Fourth_Digit : std_logic_vector(3 downto 0);
+ signal w_Current_Digit_Content : std_logic_vector(3 downto 0);
+ signal r_Current_Viewing_Digit : std_logic_vector(1 downto 0) := "00";
+ signal w_Output : std_logic_vector(6 downto 0);
+begin
+
+ -- Split the number into 4 digits
+ w_First_Digit <= i_Num(15 downto 12);
+ w_Second_Digit <= i_Num(11 downto 8);
+ w_Third_Digit <= i_Num(7 downto 4);
+ w_Fourth_Digit <= i_Num(3 downto 0);
+
+ -- Selects the current digit to display
+ w_Current_Digit_Content <= w_First_Digit when r_Current_Viewing_Digit = "00" else
+ w_Second_Digit when r_Current_Viewing_Digit = "01" else
+ w_Third_Digit when r_Current_Viewing_Digit = "10" else
+ w_Fourth_Digit;
+
+ -- Enable the digit to display (active low)
+ o_D1 <= '0' when r_Current_Viewing_Digit = "00" else
+ '1';
+ o_D2 <= '0' when r_Current_Viewing_Digit = "01" else
+ '1';
+ o_D3 <= '0' when r_Current_Viewing_Digit = "10" else
+ '1';
+ o_D4 <= '0' when r_Current_Viewing_Digit = "11" else
+ '1';
+
+ -- 7 segment display decoder
+ w_Output <= "1111110" when w_Current_Digit_Content = "0000" else -- 0x7E
+ "0110000" when w_Current_Digit_Content = "0001" else -- 0x30
+ "1101101" when w_Current_Digit_Content = "0010" else -- 0x6D
+ "1111001" when w_Current_Digit_Content = "0011" else -- 0x79
+ "0110011" when w_Current_Digit_Content = "0100" else -- 0x33
+ "1011011" when w_Current_Digit_Content = "0101" else -- 0x5B
+ "1011111" when w_Current_Digit_Content = "0110" else -- 0x5F
+ "1110000" when w_Current_Digit_Content = "0111" else -- 0x70
+ "1111111" when w_Current_Digit_Content = "1000" else -- 0x7F
+ "1111011" when w_Current_Digit_Content = "1001" else -- 0x7B
+ "1110111" when w_Current_Digit_Content = "1010" else -- 0x77
+ "0011111" when w_Current_Digit_Content = "1011" else -- 0x1F
+ "1001110" when w_Current_Digit_Content = "1100" else -- 0x4E
+ "0111101" when w_Current_Digit_Content = "1101" else -- 0x3D
+ "1001111" when w_Current_Digit_Content = "1110" else -- 0x4F
+ "1000111" when w_Current_Digit_Content = "1111" else -- 0x47
+ "0000000";
+
+ -- 7 segment display output
+ o_A <= w_Output(6);
+ o_B <= w_Output(5);
+ o_C <= w_Output(4);
+ o_D <= w_Output(3);
+ o_E <= w_Output(2);
+ o_F <= w_Output(1);
+ o_G <= w_Output(0);
+
+ process (i_Clk)
+ begin
+ if rising_edge(i_Clk) then
+
+ -- Rotate the digit to display
+ r_Current_Viewing_Digit <= "01" when r_Current_Viewing_Digit = "00" else
+ "10" when r_Current_Viewing_Digit = "01" else
+ "11" when r_Current_Viewing_Digit = "10" else
+ "00";
+ end if;
+ end process;
+
+end rtl;
\ No newline at end of file
diff --git a/src/SAP_1_Top.vhd b/src/SAP_1_Top.vhd
index 02bca3c..ac31441 100644
--- a/src/SAP_1_Top.vhd
+++ b/src/SAP_1_Top.vhd
@@ -2,6 +2,7 @@
library ieee;
use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
entity sap_1_top is
port (
@@ -18,6 +19,10 @@ architecture rtl of sap_1_top is
signal r_Reg_B : std_logic_vector(7 downto 0); -- General purpose register B
signal r_Reg_MAR : std_logic_vector(3 downto 0); -- Memory address register (4-bit)
+ -- Program counter
+ signal r_Program_Counter : std_logic_vector(3 downto 0); -- Program counter (4-bit)
+ signal r_Program_Counter_Enable : std_logic; -- Enable signal for the program counter
+
-- ALU
signal w_ALU_Out : std_logic_vector(7 downto 0); -- Output of the ALU
@@ -29,6 +34,7 @@ architecture rtl of sap_1_top is
signal w_Bus : std_logic_vector(7 downto 0);
signal r_Bus_Enable_ALU : std_logic := '0'; -- Enable the bus to be driven by the ALU
signal r_Bus_Enable_RAM : std_logic := '0'; -- Enable the bus to be driven by the RAM
+ signal r_Bus_Enable_PC : std_logic := '0'; -- Enable the bus to be driven by the program counter
-- Flags
signal w_Carry : std_logic; -- Carry flag (set if the ALU operation results in a carry)
@@ -70,6 +76,17 @@ begin
-- Bus
w_Bus <= w_ALU_Out when r_Bus_Enable_ALU = '1' else
w_RAM_Out when r_Bus_Enable_RAM = '1' else
+ ("0000" & r_Program_Counter) when r_Bus_Enable_PC = '1' else
(others => 'Z');
+ -- Program counter
+ Process_Counter : process (w_Clk)
+ begin
+ if rising_edge(w_Clk) then
+ if r_Program_Counter_Enable = '1' then
+ r_Program_Counter <= std_logic_vector(to_unsigned(to_integer(unsigned( r_Program_Counter )) + 1, 4));
+ end if;
+ end if;
+ end process Process_Counter;
+
end rtl;
\ No newline at end of file
diff --git a/src/sim/Binary_To_7_Segment_Decoder_TB.vhd b/src/sim/Binary_To_7_Segment_Decoder_TB.vhd
new file mode 100644
index 0000000..d7cde27
--- /dev/null
+++ b/src/sim/Binary_To_7_Segment_Decoder_TB.vhd
@@ -0,0 +1,86 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library vunit_lib;
+context vunit_lib.vunit_context;
+
+entity Binary_To_7_Segment_Decoder_TB is
+ generic (runner_cfg : string);
+end entity;
+
+architecture tb of Binary_To_7_Segment_Decoder_TB is
+
+ signal r_Clk : std_logic := '0';
+ signal r_Num : std_logic_vector(15 downto 0) := (others => '0');
+ signal w_D1, w_D2, w_D3, w_D4 : std_logic;
+ signal w_A, w_B, w_C, w_D, w_E, w_F, w_G : std_logic;
+
+begin
+ -- Instantiate the UUT
+ UUT : entity work.Binary_To_7_Segment_Decoder
+ port map(
+ i_Clk => r_Clk, -- Clock
+ i_Num => r_Num, -- 4 Digit hex number
+ o_D1 => w_D1, o_D2 => w_D2, o_D3 => w_D3, o_D4 => w_D4, -- 7 segment display selector
+ o_A => w_A, o_B => w_B, o_C => w_C, o_D => w_D, o_E => w_E, o_F => w_F, o_G => w_G -- 7 segment display segments
+ );
+
+ -- Clock
+ -- r_Clk <= not r_Clk after 5 ns;
+
+ main : process
+ begin
+ test_runner_setup(runner, runner_cfg);
+ wait for 10 ns;
+
+ r_Num <= x"F1E8";
+ wait for 10 ns;
+
+ -- First digit
+ assert (w_D1 = '0' and w_D2 = '1' and w_D3 = '1' and w_D4 = '1') report "Error: First digit is not the first" severity failure;
+ assert (w_A = '1' and w_B = '0' and w_C = '0' and w_D = '0' and w_E = '1' and w_F = '1' and w_G = '1') report "Error: First digit display wrong segments" severity failure;
+
+ -- Switch to second digit
+ r_Clk <= '0';
+ wait for 10 ns;
+ r_ClK <= '1';
+ wait for 10 ns;
+ assert (w_D1 = '1' and w_D2 = '0' and w_D3 = '1' and w_D4 = '1') report "Error: Second digit is not the second" severity failure;
+ assert (w_A = '0' and w_B = '1' and w_C = '1' and w_D = '0' and w_E = '0' and w_F = '0' and w_G = '0') report "Error: Second digit display wrong segments" severity failure;
+
+ -- Switch to third digit
+ r_Clk <= '0';
+ wait for 10 ns;
+ r_ClK <= '1';
+ wait for 10 ns;
+ assert (w_D1 = '1' and w_D2 = '1' and w_D3 = '0' and w_D4 = '1') report "Error: Third digit is not the third" severity failure;
+ assert (w_A = '1' and w_B = '0' and w_C = '0' and w_D = '1' and w_E = '1' and w_F = '1' and w_G = '1') report "Error: Third digit display wrong segments" severity failure;
+
+ -- Switch to fourth digit
+ r_Clk <= '0';
+ wait for 10 ns;
+ r_ClK <= '1';
+ wait for 10 ns;
+ assert (w_D1 = '1' and w_D2 = '1' and w_D3 = '1' and w_D4 = '0') report "Error: Fourth digit is not the fourth" severity failure;
+ assert (w_A = '1' and w_B = '1' and w_C = '1' and w_D = '1' and w_E = '1' and w_F = '1' and w_G = '1') report "Error: Fourth digit display wrong segments" severity failure;
+
+ -- Return to first digit
+ r_Clk <= '0';
+ wait for 10 ns;
+ r_ClK <= '1';
+ wait for 10 ns;
+ assert(w_D1 = '0' and w_D2 = '1' and w_D3 = '1' and w_D4 = '1') report "Error: First digit is not the first" severity failure;
+ assert(w_A = '1' and w_B = '0' and w_C = '0' and w_D = '0' and w_E = '1' and w_F = '1' and w_G = '1') report "Error: First digit display wrong segments" severity failure;
+
+ -- Switch number without clock
+ r_Num <= x"1234";
+ wait for 10 ns;
+ assert(w_D1 = '0' and w_D2 = '1' and w_D3 = '1' and w_D4 = '1') report "Error: First digit is not the first" severity failure;
+ assert(w_A = '0' and w_B = '1' and w_C = '1' and w_D = '0' and w_E = '0' and w_F = '0' and w_G = '0') report "Error: First digit display wrong segments" severity failure;
+
+ wait for 10 ns;
+
+ test_runner_cleanup(runner); -- Simulation ends here
+ end process;
+end architecture;
\ No newline at end of file