要求:
VHDL代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY TRAFFIC_LIGHT IS
PORT(CLK,RST: IN STD_LOGIC;
LED: OUT STD_LOGIC_VECTOR(5 DOWNTO 0); --定义6个LED灯
main_shi: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --主干倒计时的十位
main_ge: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --主干倒计时的个位
branch_shi: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --支干倒计时的十位
branch_ge: OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); --支干倒计时的个位
END ENTITY TRAFFIC_LIGHT;
ARCHITECTURE bhv OF TRAFFIC_LIGHT IS
TYPE state IS(S0,S1,S2,S3); --枚举状态类型
SIGNAL current_s,next_s:state;
SIGNAL COUNT21:STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
COUNT: PROCESS(RST,CLK) --辅助进程
BEGIN
IF RST= '1' THEN --异步清零
COUNT21<="00000000";
ELSIF CLK'EVENT AND CLK='1' THEN
IF COUNT21<"00010100" THEN --21进制计数器
COUNT21<=COUNT21+1;
ELSE
COUNT21<="00000000";
END IF;
END IF;
END PROCESS;
REG: PROCESS (RST,CLK) --主控时序进程,用于机械地控制状态转换
BEGIN
IF RST= '1' THEN
current_s <= s0;
ELSIF clk='1' AND clk'EVENT THEN
current_s <= next_s;
END IF;
END PROCESS;
COM:PROCESS(current_s, COUNT21) --主控组合进程,用于设定状态转换的下一个状态
VARIABLE main_cd,branch_cd:STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
CASE current_s IS
WHEN s0 => LED<= "010100";--主干绿灯亮,支干红灯亮
main_cd:=8-COUNT21; --主干绿灯倒计时,用于数码管显示
branch_cd:=11-COUNT21; --支干红灯倒计时,一共要亮十一秒,这里亮八秒
IF COUNT21 ="00001000" THEN --B00100111=39 控制状态转变
next_s<=s1;
ELSE
next_s<=s0;
END IF;
WHEN s1 => LED <= "001100"; --主干黄灯,支干红灯
main_cd:=11-COUNT21;--主干黄灯要亮三秒
branch_cd:=11-COUNT21; --支干红灯还要再亮三秒
IF COUNT21 = "00001011" THEN --B00101011=43
next_s<=s2;
ELSE
next_s<=s1;
END IF;
WHEN s2 => LED <= "100010"; --主干红灯,支干绿灯
main_cd:=20-COUNT21;
branch_cd:=17-COUNT21;
IF COUNT21 ="00010001" THEN --B00111111=64
next_s <= s3;
ELSE
next_s <= s2;
END IF;
WHEN s3 => LED <= "100001"; --主干红灯,支干黄灯
main_cd:=20-COUNT21;
branch_cd:=20-COUNT21;
IF COUNT21 ="00010100" THEN --B01000011=67
next_s<= s0;
ELSE
next_s <= s3;
END IF;
WHEN OTHERS=> LED <="100100"; --否则都不能通行
END case;
IF main_cd>39 THEN --译码器的功能:将当前的倒计时转换成十进制,低四位和高四位分别是数码管的个位与十位,
--38+18=56D=38H=00111000B
--使数码管按照当前的计数(十进制)按二进制计数进行倒计时
main_cd:=main_cd+24;
ELSIF main_cd>29 THEN
main_cd:=main_cd+18;
ELSIF main_cd>19 THEN
main_cd:=main_cd+12;
ELSIF main_cd>9 THEN
main_cd:=main_cd+6;
ELSE NULL;
END IF;
IF branch_cd>39 THEN
branch_cd:=branch_cd+24;
ELSIF branch_cd>29 THEN
branch_cd:=branch_cd+18;
ELSIF branch_cd>19 THEN
branch_cd:=branch_cd+12;
ELSIF branch_cd>9 THEN
branch_cd:=branch_cd+6;
ELSE NULL;
END IF;
main_shi<=main_cd(7 DOWNTO 4);
main_ge<=main_cd(3 DOWNTO 0);
branch_shi<=branch_cd(7 DOWNTO 4);
branch_ge<=branch_cd(3 DOWNTO 0);
END PROCESS;
END ARCHITECTURE bhv;