VHDL交通灯

Posted KEKE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VHDL交通灯相关的知识,希望对你有一定的参考价值。

转载请注明出处。

很讨厌码迷这种爬虫网站爬取整篇程序,所以还是加些字会好一点;

做的期末EDA实训关于交通灯;题目要求的是要做一个东西南北向的交通灯;有数码管倒计时,LED定时换颜色;复位和交通管制等功能;

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY JTD IS
    PORT (CLK1KHZ  : IN  STD_LOGIC;  --1KHZ输入
            KEY      : IN  STD_LOGIC;  --1KHZ输入
          Y1,G1,R1 : OUT STD_LOGIC;  --东西向灯
            R2,Y2,G2 : OUT STD_LOGIC;  --南北向灯
            MOTOR    : OUT STD_LOGIC;  --MOTOR
            PWM      : OUT STD_LOGIC;  --MOTOR
            WOK,RESET: IN  STD_LOGIC;  --复位和管制          
            SEG      : OUT STD_LOGIC_VECTOR (6 DOWNTO 0) := "0000000";--段选
            CSG      : OUT STD_LOGIC_VECTOR (2 DOWNTO 0) := "111";    --位选
         RRCK,RSI,RSCK,GRCK,GSI,GSCK : OUT STD_LOGIC;  --红绿控制位
            RCK1,SI1,SCK1,RCK2,SI2,SCK2 : OUT STD_LOGIC;  --12io位
            RCK3,SI3,SCK3,RCK4,SI4,SCK4 : OUT STD_LOGIC;  --34io位
            Q    : OUT STD_LOGIC_VECTOR (15 DOWNTO 0));    --流水灯
    END;

以上声明库,实体等,我加了一些其他东西,流水灯;16x16红绿点阵,直流电机等,为了实训能多加点分而已,都有注释,可以选择性的用自己的一些端口和功能;

ARCHITECTURE DECL OF JTD IS 
    SIGNAL CLK1HZ  : STD_LOGIC:= 0;           --分频1HZ
    SIGNAL CLK10HZ : STD_LOGIC:= 0;           --分频HZ
    SIGNAL CLK100HZ : STD_LOGIC:= 0;           --分频HZ
    SIGNAL STATUS  : INTEGER RANGE 1 TO 19 := 1;--数码管计时秒
    SIGNAL STAWE   : INTEGER RANGE 0 TO 35 := 0;--交通灯一轮计时36秒
    SIGNAL STATUS1 : STD_LOGIC_VECTOR(1 DOWNTO 0) := "00";
   SIGNAL EW      : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00011000";
    SIGNAL NS      : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00010101";
    

以上声明结构体,用到了中间信号和一些变量,有注释,选择性修改;

  PROCESS(CLK1KHZ)
        VARIABLE COUNT : INTEGER RANGE 0 TO 1000 := 1;
        VARIABLE COUNT1: INTEGER RANGE 0 TO 100  := 1;
        VARIABLE COUNT2: INTEGER RANGE 0 TO 10   := 1;
        BEGIN
            IF(RISING_EDGE(CLK1KHZ)) THEN
                IF (COUNT >= 1000) THEN COUNT  := 1; CLK1HZ  <= NOT CLK1HZ; --分频1hz
                ELSE COUNT := COUNT + 1;
                END IF;
                IF (COUNT1 >= 100) THEN COUNT1 := 1; CLK10HZ <= NOT CLK10HZ;--分频10HZ
                ELSE COUNT1 := COUNT1 + 1;
                END IF;
                IF (COUNT2 >= 10) THEN COUNT2 := 1; CLK100HZ <= NOT CLK100HZ;--分频100HZ
                ELSE COUNT2 := COUNT2 + 1;
                END IF;
            END IF;
    END PROCESS;

以上process将1khz分频为1,10,100hz;

------36秒轮回一次交通灯计时
   PROCESS(CLK1HZ,WOK,STAWE,RESET)
        BEGIN
        IF (WOK = 0) THEN               --按下工作键
        IF(RISING_EDGE(CLK1HZ)) THEN    --一次1hz时钟上升沿
                STAWE <= STAWE + 1;                
                END IF;
                IF STAWE = 36 THEN STAWE <= 0; END IF;   
        END IF;
       IF (RESET = 0) THEN STAWE <= 1; END IF;    --按下复位键那么时间归零,黄灯亮起
    END PROCESS;

以上process将做一次交通灯轮回计时,包含了工作键和复位键

  PROCESS(CLK10HZ,WOK)
        VARIABLE QS : STD_LOGIC_VECTOR (15 DOWNTO 0);
    BEGIN
      IF RISING_EDGE (CLK10HZ) THEN
            IF QS = 0 THEN QS := "1000000000000000";
            ELSIF QS  = "1111111111111111" THEN 
                  QS := "0000000000000000";
            ELSE  QS (14 DOWNTO 0) := QS (15 DOWNTO 1); --移位操作
           END IF;
      END IF;
    Q<=QS;
   END PROCESS;

以上process为流水灯,0.1秒闪一个,用到的是移位思想;

    -----STATUS状态计时
   PROCESS(CLK1HZ,WOK,RESET)
    BEGIN    
       IF (WOK = 0) THEN   
           IF (RESET = 0) THEN STATUS <= 1;        
            ELSIF(RISING_EDGE(CLK1HZ)) THEN
                CASE STATUS IS
                    WHEN 1  => EW <= "00011000"; NS <= "00010101";  STATUS <= STATUS + 1;
                    WHEN 2  => EW <= "00010111"; NS <= "00010100";  STATUS <= STATUS + 1;
                    WHEN 3  => EW <= "00010110"; NS <= "00010011";  STATUS <= STATUS + 1;
                    WHEN 4  => EW <= "00010101"; NS <= "00010010";  STATUS <= STATUS + 1;
                    WHEN 5  => EW <= "00010100"; NS <= "00010001";  STATUS <= STATUS + 1;
                    WHEN 6  => EW <= "00010011"; NS <= "00010000";  STATUS <= STATUS + 1;
                    WHEN 7  => EW <= "00010010"; NS <= "00001001";  STATUS <= STATUS + 1;
                    WHEN 8  => EW <= "00010001"; NS <= "00001000";  STATUS <= STATUS + 1;
                    WHEN 9  => EW <= "00010000"; NS <= "00000111";  STATUS <= STATUS + 1;
                    WHEN 10 => EW <= "00001001"; NS <= "00000110";  STATUS <= STATUS + 1;
                    WHEN 11 => EW <= "00001000"; NS <= "00000101";  STATUS <= STATUS + 1;
                    WHEN 12 => EW <= "00000111"; NS <= "00000100";  STATUS <= STATUS + 1;
                    WHEN 13 => EW <= "00000110"; NS <= "00000011";  STATUS <= STATUS + 1;
                    WHEN 14 => EW <= "00000101"; NS <= "00000010";  STATUS <= STATUS + 1;
                    WHEN 15 => EW <= "00000100"; NS <= "00000001";  STATUS <= STATUS + 1;
                    WHEN 16 => EW <= "00000011"; NS <= "00010101";  STATUS <= STATUS + 1;
                    WHEN 17 => EW <= "00000010"; NS <= "00011000";  STATUS <= STATUS + 1;
                    WHEN 18 => EW <= "00000001"; NS <= "00010111";  STATUS <= STATUS + 1;
                    WHEN OTHERS => STATUS <= 1;
                END CASE;
            END IF;
      ELSE STATUS  <= 1;
       END IF;
   END PROCESS;
    
    -------数码管
    PROCESS(EW,NS,CLK1KHZ)
        VARIABLE Q1 : STD_LOGIC_VECTOR(3 DOWNTO 0);
        BEGIN
        IF(RISING_EDGE(CLK1KHZ)) THEN
            CASE STATUS1 IS
                WHEN "00" => Q1 := EW(7 DOWNTO 4); CSG <= "110"; STATUS1 <= STATUS1 + 1;WHEN "01" => Q1 := EW(3 DOWNTO 0); CSG <= "111"; STATUS1 <= STATUS1 + 1;
                WHEN "10" => Q1 := NS(7 DOWNTO 4); CSG <= "000"; STATUS1 <= STATUS1 + 1;WHEN "11" => Q1 := NS(3 DOWNTO 0); CSG <= "001"; STATUS1 <= "00";
                WHEN OTHERS => Q1 := EW(7 DOWNTO 4); CSG <= "110"; STATUS1 <= "00";
            END CASE;
            CASE Q1 IS
                WHEN "0000" => SEG <= "0111111"; WHEN "0001" => SEG <= "0000110"; WHEN "0010" => SEG <= "1011011"; WHEN "0011" => SEG <= "1001111"; --3
                WHEN "0100" => SEG <= "1100110"; WHEN "0101" => SEG <= "1101101"; WHEN "0110" => SEG <= "1111101"; WHEN "0111" => SEG <= "0000111"; --7
                WHEN "1000" => SEG <= "1111111"; WHEN "1001" => SEG <= "1101111"; WHEN OTHERS => SEG <= "0000000"; 
            END CASE;
        END IF;
    END PROCESS;

以上两个process为数码管status和位选段选等,包含了复位等操作;

PROCESS(CLK1HZ,STAWE,WOK)
    BEGIN
        IF (WOK = 0) THEN--工作键工作
            IF RISING_EDGE(CLK1HZ) THEN
                IF (STAWE < 36 ) AND (STAWE >= 18) THEN Y1 <= 0; R1 <= 0;G1 <= 1;--35-18秒绿灯
                ELSIF (STAWE < 18) AND (STAWE >=4) THEN Y1 <= 0; R1 <= 1;G1 <= 0;--4 -17秒红灯
                ELSE  Y1 <= 1; R1 <= 0;G1 <= 0;                                  --0 - 3秒黄灯
                END IF;
                --南北向灯差4秒                                                                       
                IF (STAWE < 32 ) AND (STAWE >= 14)  THEN Y2 <= 0; R2 <= 0;G2 <= 1;--31-14秒绿灯
                ELSIF (STAWE < 14) AND (STAWE >= 0) THEN Y2 <= 0; R2 <= 1;G2 <= 0;--0 -13秒红灯
                ELSE  Y2 <= 1; R2 <= 0;G2 <= 0;                                   --32-35秒黄灯
                END IF;
            END IF;
        ELSE Y2 <= 0; R2 <= 1;G2 <= 0;Y1 <= 0; R1 <= 1;G1 <= 0;--交通管制红灯全亮
        END IF;     
   END PROCESS;    

以上process为交通灯情况;结合36秒计时那个进程理解;

    PROCESS(WOK)
    BEGIN
        IF (WOK= 1) THEN--工作键工作
         MOTOR<=1;PWM<=1;
         ELSE  MOTOR<=0; PWM<=0;                                --32-35秒黄灯
         END IF;
   END PROCESS;

以上process为直流电机;交通管制下电机转动;

代码都有注释,理解上修改。端口等在Pin plan自己修改;祝好运,科科

转载请注明出处。

以上是关于VHDL交通灯的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Icarus Verilog 在 Verilog 中转换 VHDL 代码?

用于键盘接口的 vhdl 代码

带有 VHDL 代码的 FPGA 上的声音发生器

在 VHDL 中保持动作

VHDL基础1

VHDL实现智能药盒