# 密码器

```vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

ENTITY lock IS
	 PORT (
		 code : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
		 mode : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
		 clk , rst : IN STD_LOGIC;
		 unlock : OUT STD_LOGIC;
		 err , alarm : BUFFER STD_LOGIC
	 );
	 SUBTYPE pwd1 is INTEGER RANGE 0 TO 15;
	 TYPE password IS ARRAY (3 DOWNTO 0) OF pwd1;
	 SUBTYPE states is INTEGER RANGE 0 TO 7;
END lock;

ARCHITECTURE bhv OF lock IS
	 CONSTANT admin_password : password := (1, 3, 1, 4);
	 SIGNAL cur_password : password := admin_password;
	 SIGNAL input_password : pwd1;
	 SIGNAL s1, s2 : STD_LOGIC;
	 SIGNAL state : states;
	 SIGNAL count : INTEGER RANGE 0 TO 2:= 0;

BEGIN
	input_password <= conv_integer(code);
	PROCESS (clk, rst)
	BEGIN
		 IF (rst = '1') THEN
			 unlock <= '0';
			 err <= '0';
			 state <= 0;
		 ELSIF (clk'event AND clk = '1') THEN
		 -- 设置密码
			IF (mode = "00" AND alarm = '0' AND count = 0) THEN
				CASE state IS
					 WHEN 0 | 1 | 2 =>
						 cur_password(state) <= input_password;
						 state <= state + 1;
					 WHEN 3 =>
						 cur_password(3) <= input_password;
						 state <= 7;
						 unlock <= '1';
					 WHEN OTHERS => NULL;
				END CASE;
		 -- 验证密码
			ELSIF (mode = "01") THEN
				CASE state IS
				 WHEN 0 =>
					IF ((input_password = cur_password(0) AND alarm = '0') OR input_password = admin_password(0)) 
            THEN
						 IF (input_password = cur_password(0) AND alarm = '0') THEN
							s2 <= '1';
						 ELSE
							s2 <= '0';
						 END IF;
						 IF (input_password = admin_password(0)) THEN
							s1 <= '1';
						 ELSE
							s1 <= '0';
						 END IF;
						 state <= 4;
						 err <= '0';
					 ELSE
						 err <= '1';
						 IF (count > 1) THEN
							alarm <= '1';
							count <= 0;
						 ELSE
							count <= count + 1;
						 END IF;
					 END IF;
				 WHEN 4 | 5 | 6 =>
					 IF ((input_password = cur_password(state-3) AND (s2 = '1')) OR (input_password = admin_password(state-3) AND (s1 = '1'))) THEN
						 IF (state = 6) THEN
							 unlock <= '1';
							 alarm <= '0';
							 count <= 0;
						 END IF;
						 state <= state + 1;
						 IF (input_password /= cur_password(state-3)) THEN
							s2 <= '0';
						 END IF;
						 IF (input_password /= admin_password(state-3)) THEN
							s1 <= '0';
						 END IF;
					 ELSE
						 err <= '1';
						 state <= 0;
						 IF (count > 1) THEN
							 alarm <= '1';
							 count <= 0;
						 ELSE
							 count <= count + 1;
						 END IF;
					 END IF;
				  WHEN OTHERS => NULL;
				END CASE;
			END IF;
		END IF;
	END PROCESS;
END bhv;
```