北邮数电实验——油烟机

2018-11-05  本文已影响0人  脑阔不疼

概述

程序模块图

系统模块图(油烟机).png

源文件分析

主程序

entity main is
    port(
        clk_system,btn3,btn0,btn7,btn6:in std_logic;
        col_r,col_g,row,which_digit,digit_mask:out std_logic_vector(7 downto 0);
        ld6,ld1,ld2,ld3: out std_logic
        );
end main;
        a1:elimination_buffeting port map(clk_system,btn0,btn3,btn6,btn7,btn0_elimit,btn3_elimit,btn6_elimit,btn7_elimit);
        a2:clk_division port map(clk_system,clk_half_hz,clk_1hz,clk_2hz,clk_const);
        a3:mode_switch port map(clk_const,clk_half_hz,clk_1hz,clk_2hz,btn7_elimit,btn0_elimit,btn3_elimit,clk_chosen,countdown_temp,cur_mode);
        a4:ventilator port map(clk_chosen,clk_system,col_r,col_g,row);
        a5:digital_display port map(countdown_temp,which_digit,digit_mask);
        a6:light port map(cur_mode,btn6_elimit,ld6,ld1,ld2,ld3);

按键防抖

entity elimination_buffeting is
    port(
        clk_system:in std_logic;
        btn0,btn3,btn6,btn7 : in std_logic;
        btn0_elimit,btn3_elimit,btn6_elimit,btn7_elimit: out std_logic :='0'
        );
end elimination_buffeting;

architecture a of elimination_buffeting is      
    signal cnt0 : integer range 0 to 10000;
    signal cnt3 : integer range 0 to 10000;
    signal cnt6 : integer range 0 to 10000;
    signal cnt7 : integer range 0 to 10000;
begin
    p1:process(btn0,clk_system)
    begin
    if btn0 ='1' then 
        if rising_edge(clk_system)  then 
            if cnt0 = 10000 then 
                cnt0 <= cnt0;
            else cnt0 <= cnt0+1;
            end if;
            if cnt0<10000 then btn0_elimit <= '0';
            else btn0_elimit <='1';
            end if;
        end if;
    else 
        cnt0 <= 0;
        btn0_elimit <= '0';
    end if;
    end process p1;
    
end a;  

分频(0.5hz,1hz,2hz,'1'信号)

entity clk_division is
port(
    clk: in std_logic;
    clk_out_half_hz, clk_out_1hz, clk_out_2hz, clk_const: out std_logic
);
end clk_division;

    p1:process(clk)   -- in one process, no tow edge can be used
        begin
            if rising_edge(clk) then  -- at edge -> no else
                if cnt_half = 2000000 then
                    cnt_half <= 0;
                elsif cnt_1hz = 1000000 then
                    cnt_1hz <= 0;
                elsif cnt_2hz = 500000 then
                    cnt_2hz <= 0;               
                else
                    cnt_half <= cnt_half + 1;
                    cnt_1hz <= cnt_1hz + 1;
                    cnt_2hz <= cnt_2hz + 1;                 
                end if;
            end if;             
        end process p1;
        
    p2:process(cnt_half)
        begin
            if cnt_half < 1000000 then
                clk_out_half_hz<='0';
            else clk_out_half_hz<='1';
            end if;
        end process p2;

档位控制(核心)

entity mode_switch is
port(
    clk_const: in std_logic;
    clk_half_hz: in std_logic;      
    clk_1hz: in std_logic;  -- clk_1hz as delayed sig
    clk_2hz: in std_logic;
    btn7, btn0, btn3: in std_logic;
    clk_out: out std_logic;
    count_down: out std_logic_vector(2 downto 0) := "000";
    cur_mode: out std_logic_vector(1 downto 0) := "00"
);
end mode_switch;

signal mode: integer range 0 to 3;
signal count_down_buf: integer range 0 to 6:= 0;
signal is_counting: std_logic;
p1: process(btn0, btn3, btn7, count_down_buf)                
    begin
        if btn0 = '1' then
            mode <= 0;
            is_counting <= '0';
        elsif btn3 = '1' then
            is_counting <= '1'; 
        elsif count_down_buf = 6 and is_counting = '1' then  
            mode <= 0;
            is_counting <= '0';
        elsif rising_edge(btn7) and is_counting = '0' then
            if mode = 3 then
                mode <= 0;
            else
                mode <= mode + 1;
            end if;
        end if;
    end process p1;
    p2: process(clk_1hz, is_counting, btn0)
    begin
        if btn0 = '1' then
            count_down_buf <= 0;
        elsif rising_edge(clk_1hz) then
            if is_counting = '1' then
                count_down_buf <= count_down_buf + 1;
            elsif count_down_buf = 6 then
                count_down_buf <= 0;
            end if;
        end if;
    end process p2;
    p3: process(mode)
    begin
        case mode is
            when 0 =>
                clk_out <= clk_const;
            when 1 => 
                clk_out <= clk_2hz;
            when 2 =>
                clk_out <= clk_1hz;
            when 3 =>
                clk_out <= clk_half_hz;
            end case;
    end process p3;

    p4: process(count_down_buf)
    begin
        count_down <= std_logic_vector(to_unsigned(count_down_buf, count_down'length));
    end process p4;

    p5: process(mode)
    begin
        cur_mode <= std_logic_vector(to_unsigned(mode, cur_mode'length));
    end process p5;

点阵

entity ventilator is
port(
    clk_switch, clk_system:in std_logic; 
    col_r:out std_logic_vector(7 downto 0); 
    col_g:out std_logic_vector(7 downto 0); 
    row:out std_logic_vector(7 downto 0) 
);
end ventilator;
signal row_num:integer range 0 to 7;
signal state_int: integer range 0 to 3;
signal state_vec: std_logic_vector(1 downto 0);
    process(clk_switch)
    begin
        if rising_edge(clk_switch) then
            if state_int = 3 then
                state_int <= 0;
            else
                state_int <= state_int + 1;
            end if;
        end if;
    end process;
          
    process(clk_system) ------------对点阵8行进行高频重复扫描
    begin
        if rising_edge(clk_system) then
            if row_num = 7 then
                row_num <= 0;
            else
                row_num <= row_num + 1;
            end if;
        end if;
    end process;

        state_vec <= std_logic_vector(to_unsigned(state_int, state_vec'length));
        case state_vec is
            when "00"=>
                case row_num is
                    when 0=>
                        col_r<="00000001";
                        col_g<="11100000";
                        row<="01111111";
                    when 1=>
                        col_r<="00000011";
                        col_g<="01100000";
                        row<="10111111";
                    when 2=>
                        col_r<="00000111";
                        col_g<="00100000";
                        row<="11011111";
                    when 3=>
                        col_r<="00001000";
                        col_g<="00010000";
                        row<="11101111";
                    when 4=>
                        col_r<="00010000";
                        col_g<="00001000";
                        row<="11110111";
                    when 5=>
                        col_r<="11100000";
                        col_g<="00000100";
                        row<="11111011";
                    when 6=>
                        col_r<="11000000";
                        col_g<="00000110";
                        row<="11111101";
                    when 7=>
                        col_r<="10000000";
                        col_g<="00000111";
                        row<="11111110";
                end case;

数码管

entity digital_display is
port(
     count_down: in std_logic_vector(2 downto 0);
     which_digit: out std_logic_vector(7 downto 0);
     digit_mask: out std_logic_vector(7 downto 0) := "11110111"
);
end digital_display;
architecture a of digital_display is
    signal which_digit_temp: std_logic_vector(7 downto 0);
    begin
        process(count_down) 
        begin
            case count_down is
                when "000"=>
                    which_digit_temp<="00000000";
                when "001"=>
                    which_digit_temp<="10111110";
                when "010"=>
                    which_digit_temp<="10110110";
                when "011"=>
                    which_digit_temp<="01100110";
                when "100"=>
                    which_digit_temp<="11110010";
                when "101"=>
                    which_digit_temp<="11011010";
                when "110"=>
                    which_digit_temp<="01100000";
                when others =>
                    which_digit_temp<="00000000";
            end case;
            which_digit <= which_digit_temp;
        end process;
    end a;

LED灯(照明,档位显示)

entity light is
    port(
        cur_mode:in std_logic_vector(1 downto 0);
        btn6 : in std_logic;
        ld6,ld1,ld2,ld3: out std_logic
        );
end light;
    signal lightflag : integer range 0 to 1:=0;
begin
    p1:process(btn6)
    begin
    if rising_edge(btn6) then 
        if lightflag = 0 then lightflag <= 1;
        else 
            lightflag <=0;
        end if;
    end if;
    end process p1;
    
    p2:process(lightflag)
    begin
    if lightflag = 1 then ld6 <= '1';
    else ld6 <= '0';
    end if;
    end process p2;

    p3:process(cur_mode)
    begin
    case cur_mode is
        when "00"=>
            ld1 <= '0';
            ld2 <= '0';
            ld3 <= '0';         
        when "01"=>
            ld1 <= '1';
            ld2 <= '1';
            ld3 <= '1';
        when "10"=>
            ld1 <= '1';
            ld2 <= '1';
            ld3 <= '0';         
        when "11"=>
            ld1 <= '1';
            ld2 <= '0';
            ld3 <= '0';                             
        end case;
    end process p3;

问题及其解决

程序逻辑复杂

按键消抖

点阵刷新问题

上一篇 下一篇

猜你喜欢

热点阅读