library ieee; use work.hcore_package.all; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity hcore_reglock is port ( -- global clk : in std_logic; reset : in std_logic; stall_in : in std_logic; -- in i_ra : in std_logic_vector(6 downto 0); i_rb : in std_logic_vector(6 downto 0); i_rc : in std_logic_vector(6 downto 0); i_rc_we : in std_logic; i_imm : in std_logic_vector(31 downto 0); i_a_as_reg : in std_logic; i_b_as_reg : in std_logic; i_c_as_reg : in std_logic; i_condition : in hcondition_t; i_opcode : in hopcode_t; -- lock / unlock i_rx_lock : in std_logic_vector(6 downto 0); i_rx_do_lock : in std_logic; i_rx_unlock : in std_logic_vector(6 downto 0); i_rc_do_unlock : in std_logic; -- -- in o_ra : out std_logic_vector(6 downto 0); o_rb : out std_logic_vector(6 downto 0); o_rc : out std_logic_vector(6 downto 0); o_rc_we : out std_logic; o_imm : out std_logic_vector(31 downto 0); o_a_as_reg : out std_logic; o_b_as_reg : out std_logic; o_c_as_reg : out std_logic; o_condition : out hcondition_t; o_opcode : out hopcode_t; o_stall : out std_logic ); end entity; architecture rtl of hcore_reglock is signal t_ra : std_logic_vector(6 downto 0) := (others => '0'); signal t_rb : std_logic_vector(6 downto 0) := (others => '0'); signal t_ra_tst : std_logic := '0'; signal t_rb_tst : std_logic := '0'; signal state_tst : std_logic := '0'; begin o_stall <= state_tst; process(all) type locks_t is array(0 to 127) of std_logic; variable locks : locks_t := (others => '0'); begin if rising_edge(clk) then if reset = '1' then for i in 0 to 127 loop -- clear all locks locks(i) := '0'; end loop; state_tst <= '0'; o_ra <= (others => '0'); o_rb <= (others => '0'); o_rc <= (others => '0'); o_rc_we <= '0'; o_imm <= (others => '0'); o_a_as_reg <= '0'; o_b_as_reg <= '0'; o_c_as_reg <= '0'; o_condition <= hcc_ever; o_opcode <= hope_nop; else state_tst <= '0'; if stall_in = '0' then -- default o_ra <= i_ra; o_rb <= i_rb; o_a_as_reg <= i_a_as_reg; o_b_as_reg <= i_b_as_reg; -- unlock before if i_rc_do_unlock = '1' then locks(conv_integer(i_rx_unlock)) := '0'; end if; -- test state if state_tst = '1' then -- we have to check last register if (locks(conv_integer(t_ra)) = '1' and t_ra_tst = '1') or (locks(conv_integer(t_rb)) = '1' and t_rb_tst = '1') then o_ra <= t_ra; o_rb <= t_rb; o_a_as_reg <= t_ra_tst; o_b_as_reg <= t_rb_tst; state_tst <= '1'; -- stall again else if (locks(conv_integer(i_ra)) = '1' and i_a_as_reg = '1') or (locks(conv_integer(i_rb)) = '1' and i_b_as_reg = '1') then t_ra <= i_ra; t_rb <= i_rb; t_ra_tst <= i_a_as_reg; t_rb_tst <= i_b_as_reg; state_tst <= '1'; -- we have to check it next cycle end if; end if; end if; -- lock after if i_rx_do_lock = '1' then locks(conv_integer(i_rx_lock)) := '1'; end if; -- buffer o_rc <= i_rc; o_rc_we <= i_rc_we; o_imm <= i_imm; o_c_as_reg <= i_c_as_reg; o_condition <= i_condition; o_opcode <= i_opcode; end if; end if; end if; end process; end rtl;