diff --git a/src/controller/control_unit.vhd b/src/controller/control_unit.vhd index d8d6975..ce20432 100644 --- a/src/controller/control_unit.vhd +++ b/src/controller/control_unit.vhd @@ -8,8 +8,8 @@ entity control_unit is port ( clk, rst : in std_logic; - cpu_to_controller : in cpu_to_controller_t; - controller_to_cpu : out controller_to_cpu_t; + manager_to_controller : in manager_to_controller_t; + controller_to_manager : out controller_to_manager_t; drivers_to_controller : in drivers_to_controller_t; controller_to_drivers : out controller_to_drivers_t ); @@ -31,7 +31,7 @@ architecture behave of control_unit is begin - comb_proc: process(cpu_to_controller, drivers_to_controller, state) + comb_proc: process(manager_to_controller, drivers_to_controller, state) begin ored := '0'; ready_reduction: for i in 0 to number_of_drivers - 1 loop @@ -40,7 +40,7 @@ begin controller_to_drivers.socbridge.request <= state.curr_driver; controller_to_drivers.socbridge.address <= state.address; controller_to_drivers.socbridge.seq_mem_access_count <= state.seq_mem_access_count; - controller_to_cpu.ready <= state.ready; + controller_to_manager.ready <= state.ready; controller_to_drivers.socbridge.instruction <= state.instruction; end process comb_proc; @@ -56,10 +56,10 @@ begin else state.ready <= not ored; if ored = '0' then - state.address <= cpu_to_controller.address; - state.seq_mem_access_count <= cpu_to_controller.seq_mem_access_count; - state.curr_driver <= cpu_to_controller.driver_id(0); - with cpu_to_controller.cmd select + state.address <= manager_to_controller.address; + state.seq_mem_access_count <= manager_to_controller.seq_mem_access_count; + state.curr_driver <= manager_to_controller.driver_id(0); + with manager_to_controller.cmd select state.instruction <= WRITE when "01", READ when "10", NO_OP when others; diff --git a/src/controller/control_unit_tb.vhd b/src/controller/control_unit_tb.vhd index 71ecc4b..2c1c072 100644 --- a/src/controller/control_unit_tb.vhd +++ b/src/controller/control_unit_tb.vhd @@ -14,13 +14,13 @@ architecture tb of control_unit_tb is constant cycle: Time := 10 ns; signal clock: std_logic := '0'; signal reset: std_logic := '0'; - signal cpu_to_controller: cpu_to_controller_t := ( + signal manager_to_controller: manager_to_controller_t := ( (others => '0'), (others => '0'), 0, "00"); signal drivers_to_controller: drivers_to_controller_t := (socbridge => (is_active => '0')); - signal controller_to_cpu: controller_to_cpu_t; + signal controller_to_manager: controller_to_manager_t; signal controller_to_drivers: controller_to_drivers_t; signal current_driver : std_logic_vector(0 downto 0) := "0"; shared variable word_counter: natural := 0; @@ -40,8 +40,8 @@ begin port map( clk => clock, rst => reset, - cpu_to_controller => cpu_to_controller, - controller_to_cpu => controller_to_cpu, + manager_to_controller => manager_to_controller, + controller_to_manager => controller_to_manager, drivers_to_controller => drivers_to_controller, controller_to_drivers => controller_to_drivers ); @@ -50,11 +50,11 @@ stimulus_proc: process begin wait for cycle; - cpu_to_controller.driver_id <= "1"; + manager_to_controller.driver_id <= "1"; drivers_to_controller.socbridge.is_active <= '0'; - cpu_to_controller.address <= x"F0F0F0F0"; - cpu_to_controller.seq_mem_access_count <= 3; - cpu_to_controller.cmd <= "01"; + manager_to_controller.address <= x"F0F0F0F0"; + manager_to_controller.seq_mem_access_count <= 3; + manager_to_controller.cmd <= "01"; word_counter := 3; wait for cycle; current_driver <= "1"; diff --git a/src/ganimede/ganimede.vhd b/src/ganimede/ganimede.vhd index 96f02e3..7a9e8fe 100644 --- a/src/ganimede/ganimede.vhd +++ b/src/ganimede/ganimede.vhd @@ -10,8 +10,8 @@ entity ganimede_toplevel is port ( clk : in std_logic; rst : in std_logic; - cpu_to_ganimede : in cpu_to_controller_t; - ganimede_to_cpu : out controller_to_cpu_t; + manager_to_ganimede : in manager_to_controller_t; + ganimede_to_manager : out controller_to_manager_t; ext_to_ganimede : in ext_to_ganimede_t; ganimede_to_ext : out ganimede_to_ext_t; ip_to_ganimede : in ip_to_ganimede_t; @@ -54,7 +54,7 @@ begin ganimede_to_ext <= drivers_to_ext; --- DRIVER INSTANTIATION --- - socbridge_inst: entity socbridge.socbridge_driver + socbridge_inst: entity gan_socbridge.socbridge_driver port map( clk => clk, rst => rst, @@ -70,8 +70,8 @@ begin port map( clk => clk, rst => rst, - cpu_to_controller => cpu_to_ganimede, - controller_to_cpu => ganimede_to_cpu, + manager_to_controller => manager_to_ganimede, + controller_to_manager => ganimede_to_manager, drivers_to_controller => drivers_to_controller, controller_to_drivers => controller_to_drivers ); diff --git a/src/ganimede/ganimede_tb.vhd b/src/ganimede/ganimede_tb.vhd index b0f07ae..f9e1b50 100644 --- a/src/ganimede/ganimede_tb.vhd +++ b/src/ganimede/ganimede_tb.vhd @@ -3,8 +3,8 @@ use IEEE.std_logic_1164.all; use IEEE.NUMERIC_STD.all; library ganimede; use ganimede.io_types.all; -library socbridge; -use socbridge.socbridge_driver_tb_pkg.all; +library gan_socbridge; +use gan_socbridge.socbridge_driver_tb_pkg.all; library controller; entity ganimede_tb is diff --git a/src/ganimede/io_type_pkg.vhd b/src/ganimede/io_type_pkg.vhd index 62ab39d..c87248c 100644 --- a/src/ganimede/io_type_pkg.vhd +++ b/src/ganimede/io_type_pkg.vhd @@ -23,16 +23,16 @@ package io_types is end record interface_inst_t; --- CONTROL UNIT --- - type cpu_to_controller_t is record + type manager_to_controller_t is record driver_id : std_logic_vector(number_of_drivers - 1 downto 0); address : std_logic_vector(address_width - 1 downto 0); seq_mem_access_count : integer; - cmd : std_logic_vector(1 downto 0); - end record cpu_to_controller_t; + cmd : std_logic_vector(1 downto 0); --Noop: 00; Write: 01; Read: 10 + end record manager_to_controller_t; - type controller_to_cpu_t is record + type controller_to_manager_t is record ready : std_logic; - end record controller_to_cpu_t; + end record controller_to_manager_t; --- PROTOCOL INFORMATION --- constant interface_inst : interface_inst_t := ( diff --git a/src/gantry.toml b/src/gantry.toml index 22d138a..7d703e5 100644 --- a/src/gantry.toml +++ b/src/gantry.toml @@ -4,7 +4,7 @@ maintainer = "" email = "" version = "0.0.1" -[libraries.socbridge] +[libraries.gan_socbridge] vhdl-version = "93c" path = "socbridge" @@ -183,3 +183,7 @@ path = "grlib-com-nx-2024.4-b4295/lib/micron" [libraries.ahb2ahb] vhdl-version = "93c" path = "grlib-com-nx-2024.4-b4295/verification/ahb2ahb" + +[libraries.manager] +vhdl-version = "93c" +path = "manager" diff --git a/src/manager/management_unit.vhd b/src/manager/management_unit.vhd new file mode 100644 index 0000000..49df662 --- /dev/null +++ b/src/manager/management_unit.vhd @@ -0,0 +1,86 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.MATH_REAL.all; +use ieee.numeric_std.all; +library manager; +use manager.management_types.all; +library ganimede; +use ganimede.io_types.all; + +entity management_unit is + port ( + clk, rst : in std_logic; + manager_to_controller : out manager_to_controller_t; + controller_to_manager : in controller_to_manager_t; + socbridge_driver_to_manager : in socbridge_driver_to_manager_t; + manager_to_socbridge_driver : out manager_to_socbridge_driver_t + ); + +end entity management_unit; + +architecture rtl of management_unit is + signal manager_state : manager_state_t; + signal write_address : manager_word_t; + signal read_address : manager_word_t; + signal msg_size : manager_word_t; + -- Address indexing whole words, not bytes + signal word_address : natural; +begin + +word_address <= to_integer(shift_right(unsigned(socbridge_driver_to_manager.address), address_shift)); +read_address <= manager_state.memory(word_address); +write_address <= manager_state.memory(word_address); + + +comb_proc: process(controller_to_manager, socbridge_driver_to_manager) +begin + -- Read data from manager to SoCBridge driver + manager_to_socbridge_driver.ready <= '1'; + manager_to_socbridge_driver.data <= manager_state.memory(word_address); + manager_to_socbridge_driver.valid <= '1'; +end process comb_proc; + +-- tre sorters sätt att avsluta en skrivning: +-- timeout om vi villha det +-- en lastbit genooom axi interface +-- vi har fått all data vi begärde. + +seq_proc: process(clk) +begin + if rising_edge(clk) then + if rst = '1' then + manager_state <= manager_state_reset_val; + else + -- Write data from SoCBridge driver to address + if socbridge_driver_to_manager.valid = '1' then + manager_state.memory(word_address) <= socbridge_driver_to_manager.data; + if socbridge_driver_to_manager.address = read_address_index + or socbridge_driver_to_manager.address = write_address_index then + -- CLEAR BUFFER TO IP CORE + end if; + end if; + + -- Is there a read instruction in memory + if read_address /= empty_word and controller_to_manager.ready = '1' then + manager_to_controller.address <= read_address; + manager_to_controller.driver_id <= "1"; -- Only supprts one driver at present + manager_to_controller.seq_mem_access_count <= to_integer(unsigned(msg_size)); + manager_to_controller.cmd <= "10"; + -- Is there a write instruction in memory + elsif write_address /= empty_word and controller_to_manager.ready = '1' then + manager_to_controller.address <= write_address; + manager_to_controller.driver_id <= "1"; -- Only supports one driver at present + manager_to_controller.seq_mem_access_count <= to_integer(unsigned(msg_size)); + manager_to_controller.cmd <= "01"; + else + -- No instruction present in memory, all zeroes to control unit + manager_to_controller.address <= (others => '0'); + manager_to_controller.driver_id <= "0"; -- Only supprts one driver at present + manager_to_controller.seq_mem_access_count <= 0; + manager_to_controller.cmd <= "00"; + end if; + end if; + end if; +end process seq_proc; + +end architecture rtl ; diff --git a/src/manager/management_unit_pkg.vhd b/src/manager/management_unit_pkg.vhd new file mode 100644 index 0000000..1981d0e --- /dev/null +++ b/src/manager/management_unit_pkg.vhd @@ -0,0 +1,45 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.MATH_REAL.all; +library ganimede; +use ganimede.io_types.all; + +package management_types is + constant WORD_SIZE : natural := 32; + -- Amount to right shift addres to convert e.g 0x00000004 to 0x00000001 for 32-bit words + constant address_shift : natural := natural(FLOOR(LOG2(real(WORD_SIZE) / real(8)))); + subtype manager_word_t is std_logic_vector(WORD_SIZE - 1 downto 0); + constant empty_word : std_logic_vector(WORD_SIZE - 1 downto 0) := (others => '0'); + constant mem_words : natural := 64; + type memory_t is array (0 to mem_words - 1) of manager_word_t; + + -- Index in memory array where memory read address is kept. + -- Read is active while it is not all zero. + constant read_address_index : std_logic_vector(WORD_SIZE - 1 downto 0) := x"00000000"; + -- Index in memory array where memory write address is kept. + -- Write is active while it is not all zero. Mutex with read address + constant write_address_index : std_logic_vector(WORD_SIZE - 1 downto 0) := x"00000001"; + constant access_size : std_logic_vector(WORD_SIZE - 1 downto 0) := x"00000002"; + + -- Status register for debugging + type manager_state_t is record + memory : memory_t; + data_out : manager_word_t; + end record manager_state_t; + + -- reset value of status register + constant manager_state_reset_val : manager_state_t := ((others => (others => '0')), x"00000000"); + + type socbridge_driver_to_manager_t is record + address : manager_word_t; + data : manager_word_t; + valid: std_logic; + end record socbridge_driver_to_manager_t; + + type manager_to_socbridge_driver_t is record + data : manager_word_t; + valid : std_logic; + ready : std_logic; + end record manager_to_socbridge_driver_t; + +end package; diff --git a/src/manager/management_unit_tb.vhd b/src/manager/management_unit_tb.vhd new file mode 100644 index 0000000..dd91dd2 --- /dev/null +++ b/src/manager/management_unit_tb.vhd @@ -0,0 +1,124 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.MATH_REAL.all; +use IEEE.numeric_std.all; +library ganimede; +use ganimede.io_types.all; +library manager; +use manager.management_types.all; + +entity management_unit_tb is +end entity management_unit_tb; + +architecture tb of management_unit_tb is + signal clk : std_logic := '0'; + signal rst : std_logic; + + signal manager_to_controller : manager_to_controller_t; + signal controller_to_manager : controller_to_manager_t := (ready => '0'); + signal socbridge_driver_to_manager : socbridge_driver_to_manager_t := ( + address => (others => '0'), + data => (others => '0'), + valid => '0' + ); + signal manager_to_socbridge_driver : manager_to_socbridge_driver_t; + + constant halfcycle: Time := 5 ns; + constant cycle: Time := 2 * halfcycle; + + function to_string ( a: std_logic_vector) return string is + variable b : string (1 to a'length) := (others => NUL); + variable stri : integer := 1; + begin + for i in a'range loop + b(stri) := std_logic'image(a((i)))(2); + stri := stri+1; + end loop; + return b; + end function; + +begin + + clock_proc: process + begin + for i in 0 to 50 loop + wait for halfcycle; + clk <= not clk; + end loop; + wait; + end process clock_proc; + + management_unit_inst: entity manager.management_unit + port map( + clk => clk, + rst => rst, + manager_to_controller => manager_to_controller, + controller_to_manager => controller_to_manager, + socbridge_driver_to_manager => socbridge_driver_to_manager, + manager_to_socbridge_driver => manager_to_socbridge_driver + ); + +tb_proc: process +begin + controller_to_manager.ready <= '0'; + rst <= '1'; + wait for cycle; + rst <= '0'; + + report "Testing write to 0x00000014"; + socbridge_driver_to_manager.data <= x"FA0FA0FA"; + socbridge_driver_to_manager.address <= x"00000014"; + socbridge_driver_to_manager.valid <= '1'; + wait for cycle; + socbridge_driver_to_manager.valid <= '0'; + socbridge_driver_to_manager.data <= x"00000000"; + socbridge_driver_to_manager.address <= x"00000000"; + wait for halfcycle; + assert manager_to_socbridge_driver.data = x"FA0FA0FA" report "Write to address 0x00000005 failed! expected 0xFA0FA0FA but got " & natural'image(to_integer(unsigned(manager_to_socbridge_driver.data))) severity error; + + wait for 5 * cycle; + + report "Testing submission of write instruction of 10 words to address 0x40000000"; + controller_to_manager.ready <= '1'; + socbridge_driver_to_manager.data <= x"40000000"; + socbridge_driver_to_manager.address <= x"00000004"; + socbridge_driver_to_manager.valid <= '1'; + wait for cycle; + socbridge_driver_to_manager.data <= x"0000000A"; + socbridge_driver_to_manager.address <= x"00000008"; + socbridge_driver_to_manager.address <= x"00000000"; + socbridge_driver_to_manager.valid <= '1'; + wait for cycle; + socbridge_driver_to_manager.valid <= '0'; + socbridge_driver_to_manager.data <= x"00000000"; + wait for cycle; + controller_to_manager.ready <= '1'; + wait for halfcycle; + assert manager_to_controller.address = x"40000000" report "Controller got the wrong address! Expected 0x40000000 but got " & to_string(manager_to_controller.address) severity error; + assert manager_to_controller.cmd = "10" report "Controller got the wrong command! Expected 0b10 but got " & to_string(manager_to_controller.cmd) severity error; + assert manager_to_controller.seq_mem_access_count = 10 report "Controller got the wrong message size! expected 10 but got " & natural'image(manager_to_controller.seq_mem_access_count) severity error; + + wait for 5 * cycle; + controller_to_manager.ready <= '0'; + + report "Testing submission of read instruction of 20 words from address 0x50000000"; + socbridge_driver_to_manager.data <= x"50000000"; + socbridge_driver_to_manager.address <= x"00000000"; + socbridge_driver_to_manager.valid <= '1'; + wait for cycle; + socbridge_driver_to_manager.data <= x"00000014"; + socbridge_driver_to_manager.address <= x"00000008"; + socbridge_driver_to_manager.valid <= '1'; + wait for cycle; + socbridge_driver_to_manager.valid <= '0'; + socbridge_driver_to_manager.address <= x"00000000"; + socbridge_driver_to_manager.data <= x"00000000"; + controller_to_manager.ready <= '1'; + wait for halfcycle; + assert manager_to_controller.address = x"50000000" report "Controller got the wrong address! Expected 0x50000000 but got " & to_string(manager_to_controller.address) severity error; + assert manager_to_controller.cmd = "01" report "Controller got the wrong command! Expected 0b01 but got " & to_string(manager_to_controller.cmd) severity error; + assert manager_to_controller.seq_mem_access_count = 20 report "Controller got the wrong message size! expected 20 but got " & natural'image(manager_to_controller.seq_mem_access_count) severity error; + wait; +end process tb_proc; + +end architecture tb ; diff --git a/src/socbridge/socbridge_driver_tb.vhd b/src/socbridge/socbridge_driver_tb.vhd index 2f77720..67b5f8c 100644 --- a/src/socbridge/socbridge_driver_tb.vhd +++ b/src/socbridge/socbridge_driver_tb.vhd @@ -5,7 +5,7 @@ library work; use work.socbridge_driver_tb_pkg.all; library ganimede; use ganimede.io_types.all; -library socbridge; +library gan_socbridge; entity socbridge_driver_tb is diff --git a/src/vhdl_ls.toml b/src/vhdl_ls.toml index c7d51b0..c460396 100644 --- a/src/vhdl_ls.toml +++ b/src/vhdl_ls.toml @@ -13,6 +13,9 @@ gan_socbridge.files = [ controller.files = [ 'controller/*.vhd', ] +manager.files = [ + 'manager/*.vhd', +] grlib.files = [ 'grlib-com-nx-2024.4-b4295/lib/grlib/**/*.vhd', ]