特级茶叶 2022-11-12 18:04 采纳率: 78.6%
浏览 93
已结题

用verilog HDL语法编写5

请编写程序,可以给出仿真图,题目如下图,请按题目要求编写,并给出程序。
请注意题目必须用按键!

img

  • 写回答

3条回答 默认 最新

  • 老皮芽子 2022-11-15 16:51
    关注

    3 个按键,选择,取消,确认
    采用数码滚动的方式,通过选择键选择数字

    
    //初始密码是 1234
    //需要录入修改密码,将sw[0]拨到 0 ,操作键盘输入密码,按确认就能将当前密码保存。
    //将sw[0]拨到 1 是正常密码锁
    //3 个按键
    //k0 选择//k1 取消//k2 确认    
    //按下 K0 时,当前位数码管开始 0 - 9 的半秒循环跳变一次,抬起 K0 数码管停止跳动记录当前这位密码,密码计数加 1
    //输入四位密码后,按下 K2 比较密码,成功 LED 0 亮,或失败错误计数器加1
    //在没按确认前,按 K1 会将所有的密码取消,回到没有输入密码的状态,密码计数归 0,需要重新输入 4 位密码。
    //没输够 4 位密码时,按 K2 无效果
    //sw[0] 修改密码开关 = 0 录入修改密码,= 1 正常密码锁
    //sw[1] 解锁键盘开关,在加电状态将开关拨到 0 后再拨回到 1
    //sw[0]/sw[1]这俩开关拨到 1 时才能正常工作
    module passwd_lock    //密码锁
    (
        input            clk,    //50MHz 时钟
        input    [2:0]    k,        //轻触按键    k[0][选择]/k[1][取消]/k[2][确认]/
        input    [1:0]    sw,        //开关,sw[0]:修改密码开关/sw[1]:解锁键盘开关
                                //修改密码开关 = 0 录入修改密码,= 1 正常密码锁
                                //解锁键盘开关 = 0 解锁,=1正常
        output    [1:0]    led,    //输出1 LED 亮。led[0]密码正确、led[1]密码三次错误锁键盘
        output    [6:0]    led_7a,            //七段数码管 A 最左边
        output    [6:0]    led_7b,            //七段数码管 B 左边第二
        output    [6:0]    led_7c,            //七段数码管 C 左边第三
        output    [6:0]    led_7d            //七段数码管 D 最右边
    );
    
    
    parameter CLK_IN_FREQ    = 50*1000*1000;
    parameter CLK_KEY_FREQ    = 100;
    
    reg[15:0]    passwd_dat_save            = 16'h4321;    //初始密码 1234
    reg    [3:0]    err_cnt=0;    //密码错误计数器
    reg            lock_key=0;    //键盘锁,1锁,0解锁
    reg            passwd_ok=0;
    
    wire[15:0]    key_dat;            //键盘输出的4位数
    wire        key_valid;            //键盘输出有效
    wire        k_clk;
    wire[2:0]    k_up;
    wire[2:0]    k_down;
    
    wire[6:0]    led_7a_i;
    wire[6:0]    led_7b_i;
    wire[6:0]    led_7c_i;
    wire[6:0]    led_7d_i;
    wire        en;
    
    
    key_num    u2    //滚动数字键盘
    (
        .clk        (k_clk),
        .en            (en),
        .k            (k),            //k0 sel 选择按键,k1 cancel 取消按键,k[2] ok 确认按键
        .k_up        (k_up),            //对应 K[2:0] 的抬起键脉冲
        .k_down        (k_down),        //对应 K[2:0] 的按下键脉冲
        .key_valid    (key_valid),
        .key_dat    (key_dat)
    );
    
    
    led_7s  led_a
    (
        .dat    (key_dat[3:0]),
        .led7s    (led_7a_i)        //七段数码管 A 最左边
    );
    
    led_7s  led_b
    (
        .dat    (key_dat[7:4]),
        .led7s    (led_7b_i)        //七段数码管 B 左边第二
    );
    
    led_7s  led_c
    (
        .dat    (key_dat[11:8]),
        .led7s    (led_7c_i)        //七段数码管 C 左边第三
    );
    
    led_7s  led_d
    (
        .dat    (key_dat[15:12]),
        .led7s    (led_7d_i)        //七段数码管 D 最右边
    );
    
    
    assign    led_7a    = ~led_7a_i;    //共阳输出需要翻转
    assign    led_7b    = ~led_7b_i;    //共阳输出需要翻转
    assign    led_7c    = ~led_7c_i;    //共阳输出需要翻转
    assign    led_7d    = ~led_7d_i;    //共阳输出需要翻转
    
    assign    led[0]    = passwd_ok;
    assign    led[1]    = lock_key;
    assign    en        = ~lock_key & sw[1];
    
    
    reg        clk1    = 0;
    reg[31:0]cnt    = 0;
    assign    k_clk = clk1;
    
    //时钟分频模块    //输入时钟频率 50MHz 输出时钟 100Hz,键盘用 100Hz 低频有去抖动的效果
    
    always @(posedge clk)
    begin
        if(cnt < CLK_IN_FREQ/CLK_KEY_FREQ/2 -1)
            cnt        <= cnt + 1;
        else
        begin
            cnt        <= 0;
            clk1    <= !clk1;
        end
    end
    
    always @(posedge k_clk)
    begin
        if(sw[0]==0)    //修改密码
        begin
            lock_key    <= 0;    //修改密码时不锁键盘
            err_cnt        <= 0;
            passwd_ok    <= 0;
            if(key_valid == 1)
                passwd_dat_save <= key_dat;    //保存密码
        end
        else if(sw[1]==0)    //解锁键盘
        begin
            lock_key    <= 0;
            err_cnt        <= 0;
            passwd_ok    <= 0;
        end
        else    //正常的密码锁
        begin
            if(key_valid == 1)
            begin
                if(key_dat == passwd_dat_save)
                begin
                    lock_key    <= 0;
                    err_cnt        <= 0;
                    passwd_ok    <= 1;    //开锁
                end
                else if(err_cnt < 3-1)
                begin
                    lock_key    <= 0;
                    err_cnt        <= err_cnt + 1;    //密码错误,计数器+1
                    passwd_ok    <= 0;
                end
                else
                begin
                    lock_key    <= 1;    //3次密码错误,锁键盘
                    err_cnt        <= 3;
                    passwd_ok    <= 0;
                end
            end
            else if(k_up[2]==1)    //判断[确认]抬起,开锁结束
                passwd_ok    <= 0;
        end
    end
    endmodule
    
    
    module led_7s    //led 7 段数码管译码 0-F,共阴数码管
    (
        input        [3:0]    dat,
        output reg    [6:0]    led7s    //{a,b,c,d,e,f,g} //7段LED 排列 a->led7s[6] g->led7s[0] 
    );
    always@(*)
    begin
        case(dat)
            4'b0000:led7s=7'b0111111;    //0
            4'b0001:led7s=7'b0000110;    //1
            4'b0010:led7s=7'b1011011;    //2
            4'b0011:led7s=7'b1001111;    //3
            4'b0100:led7s=7'b1100110;    //4
            4'b0101:led7s=7'b1101101;    //5
            4'b0110:led7s=7'b1111101;    //6
            4'b0111:led7s=7'b0000111;    //7
            4'b1000:led7s=7'b1111111;    //8
            4'b1001:led7s=7'b1101111;    //9
            4'b1010:led7s=7'b1110111;    //A
            4'b1011:led7s=7'b1111100;    //B
            4'b1100:led7s=7'b0111001;    //C
            4'b1101:led7s=7'b1011110;    //D
            4'b1110:led7s=7'b1111001;    //E
            4'b1111:led7s=7'b1110001;    //F
        endcase
    end
    endmodule
    
    module key_num    //滚动数字键盘
    (
        input                clk,
        input                en,
        input[2:0]            k,        //k0 sel 选择按键,k1 cancel 取消按键,k[2] ok 确认按键
        output                key_valid,
        output[2:0]            k_up,
        output[2:0]            k_down,
        output    [15:0]        key_dat
    );
    
    parameter CLK_IN_FREQ    =100;    //100Hz
    
    reg    [2:0]        k_r0=0;
    reg    [2:0]        k_r1=0;
    
    reg    [3:0]        kb_dat[3:0];
    reg    [3:0]        kb_cnt=0;
    
    wire            k_sel;
    wire            k_sel_up;
    wire            k_sel_down;
    wire            k_cancel_up;
    wire            k_cancel_down;
    wire            k_ok_up;
    wire            k_ok_down;
    reg                key_valid_r=0;
    
    reg                clk_s=0;
    reg    [7:0]        cnts=0;
    
    initial
    begin
        kb_dat[0]=0;
        kb_dat[1]=0;
        kb_dat[2]=0;
        kb_dat[3]=0;
    end
    assign    k_sel            = k_r1[0];                //k[0]sel   [选择]按键,按下开始数字滚动,抬起滚动停止,0为按下,1为抬起
    assign    k_sel_up        = k_r0[0] & ~k_r1[0];    //k[0]sel    [选择]按键抬起脉冲,1 有效
    assign    k_sel_down        =~k_r0[0] &  k_r1[0];    //k[0]sel    [选择]按键按下脉冲,1 有效
    assign    k_cancel_up        = k_r0[1] & ~k_r1[1];    //k[1]cancel[取消]按键抬起脉冲,1 有效
    assign    k_cancel_down    =~k_r0[1] &  k_r1[1];    //k[1]cancel[取消]按键按下脉冲,1 有效
    assign    k_ok_up            = k_r0[2] & ~k_r1[2];    //k[2]ok    [确认]按键抬起脉冲,1 有效
    assign    k_ok_down        =~k_r0[2] &  k_r1[2];    //k[2]ok    [确认]按键按下脉冲,1 有效
    
    assign    k_up[0]        = k_sel_up;
    assign    k_down[0]    = k_sel_down;
    assign    k_up[1]        = k_cancel_up;
    assign    k_down[1]    = k_cancel_down;
    assign    k_up[2]        = k_ok_up;
    assign    k_down[2]    = k_ok_down;
    
    assign    key_dat            = {kb_dat[3],kb_dat[2],kb_dat[1],kb_dat[0]};
    assign    key_valid        = key_valid_r;
    
    always @(posedge clk)
    begin
        if(cnts < CLK_IN_FREQ/2-1)
        begin
            cnts    <= cnts + 1;
            clk_s    <= 0;
        end
        else
        begin
            cnts    <= 0;
            clk_s    <= 1;    //2Hz脉冲,用于数字滚动
        end
    end
    
    always @(posedge clk)
    begin
        k_r0    <= k;
        k_r1    <= k_r0;
    end
    
    always @(posedge clk)
    begin
        if(en == 1)        //en = 1 允许键盘
        begin
            if(k_cancel_up == 1 || (k_ok_up == 1 && kb_cnt >= 4))    //[取消]抬起键||[确认]抬起并且输入了4位数
                kb_cnt    <= 0;
            else if(k_sel_up == 1 && kb_cnt < 4)    //用抬起[选择]的脉冲来计数
                kb_cnt    <= kb_cnt + 1;
        end
        else            //en = 0 锁键盘
            kb_cnt    <= 0;
    end
     
    always @(posedge clk)
    begin
        if(en == 1)        //en = 1 允许键盘
        begin
            if(k_cancel_up == 1)    
                key_valid_r    <= 0;
            else if(k_ok_down == 1 && kb_cnt >= 4)    
                key_valid_r    <= 1;
            else
                key_valid_r    <= 0;
        end
        else            //en = 0 锁键盘
            key_valid_r        <= 0;
    end
    
    always @(posedge clk)
    begin
        if(en == 1)        //en = 1 允许键盘
        begin
            if(k_cancel_up == 1 || k_ok_up == 1)
            begin
                kb_dat[0]    <= 0;
                kb_dat[1]    <= 0;
                kb_dat[2]    <= 0;
                kb_dat[3]    <= 0;
            end
            else if(kb_cnt < 4)
            begin
                if(k_sel == 0 && clk_s == 1)    //选择键按下,2Hz脉冲
                begin
                    if(kb_dat[kb_cnt] <10-1)
                        kb_dat[kb_cnt]    <= kb_dat[kb_cnt] + 1;
                    else
                        kb_dat[kb_cnt]    <= 0;
                end
            end
        end
        else        //en = 0 锁键盘
        begin
            kb_dat[0]    <= 0;
            kb_dat[1]    <= 0;
            kb_dat[2]    <= 0;
            kb_dat[3]    <= 0;
        end
    end
    endmodule
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月23日
  • 已采纳回答 11月15日
  • 赞助了问题酬金15元 11月14日
  • 创建了问题 11月12日

悬赏问题

  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开
  • ¥50 pointpillars等目标检测算法怎么融合注意力机制
  • ¥20 Vs code Mac系统 PHP Debug调试环境配置
  • ¥60 大一项目课,微信小程序
  • ¥15 求视频摘要youtube和ovp数据集