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