1.为什么要分频?
主要是为了给其他模块一个时钟源,不同的模块需要不同的时钟源,比如时间计数,时间分为一秒一秒的,LED的现实模块,LED是通过人的视觉差来达到让人觉
的它在亮的效果,实际上说它是扫描比较的闪烁比较好。

2.怎么分频?
通过计数器来实现分频,所需要的频率与基础频率之间的计数关系,因为采用的是上升沿或者下降沿触发计数,两者有些不同,上升沿触发的分频时钟输出,如果
N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50%,得到的分频时钟正周期比负周期多一个clk时钟,下降沿触发的分频时钟输出,和用上
升沿触发的相差半个时钟,如果是上升沿和下降沿混合用的,需要注意这个问题,特别是模块分不同的人写的时候,因为我们这个都是我自己写的,所以都是采用
的上升沿。(12MHz)

3.键盘扫描模块的原理
扫描并锁存行值,该行按下为1,否则为0,列同理,然后用case选择情况根据键盘所代表的数字在寄存器里存数字

4.密码模块
密码模块用了一个24位的寄存器,密码一共有4位,每位可以输入0-9十个任意数。

5.报警模块
判断锁的状态位,因为频率慢的时钟不能在快频率模块进行判断、赋值这些操作,我们把报警器和报警器所需要的计时模块放在了一起
在频率快的模块中赋值的量不能在在频率慢的模块中再进行赋值,慢频率模块的值可以在快模块中进行判断操作

6.状态灯模块

5.状态的判定
锁的状态、是否重置、是否开始输入密码、确认密码

3.总的流程?
实现电子密码锁密码输入、密码储存、密码删除、密码重置,要求在5秒内输入正确密码,则绿灯亮,锁打开;密码错误或者未在规定时间内输完都算解锁失败,
红灯亮,报警20秒,20秒后可重新输入,rst 键按下当前输入密码设置为电子锁的密码
主要模块:
1.分频模块
2.LED灯模块,LED灯显示输入密码和时间计数
3.键盘扫描模块
4.密码模块
5.辅助模块(防抖模块)【此次代码未添加该模块】

功能模块部分

module code123(sw1,sw2,sw3,clk,row,col,rst,key,alarm,clear,xianshi,play2,play3,play4,green_led,yellow_led,red_led,ring);
//parameter N=5
input  sw1;
input sw2;
input sw3;
input rst;//复位
input clk;//时钟
input clear;//清除
input [3:0]row;
output reg[3:0]col;
output  reg ring;
input [3:0] key;
reg [3:0] key0=4'b1111;//预存密码都为1
reg [4:0] counter=5'b00000;
output [8:0]xianshi;
wire[8:0]shumaguan;
assign xianshi=shumaguan;//一个计算秒数,还有4位显示密码
output [8:0]play2;
wire[8:0] led2;
assign play2=led2;
output [7:0]play3;
wire[7:0] led3;
assign play3=led3;
output [7:0]play4;
wire[7:0] led4;
assign play4=led4;
reg clk1;
reg flag=0;
reg flag1=0;
reg flag2=0;
reg [23:0] previous_password=24'd0;
reg [23:0] password=24'd0;
reg flag_in=1'b0;
reg [3:0] keyboard_val;
//=========================
reg [3:0]cout=4'b0000;
//output [2:0] cout0;
//assign  cout0=cout;
//=========================
reg [3:0] temp=4'b0000;
//wire temp1;
//assign temp=temp1;
//output [3:0] temp1;
//assign temp1=temp;
wire clk2;
//========================
output reg green_led;
output reg yellow_led;
output reg red_led;output reg alarm;
//  assign ring=alarm;
reg [19:0] count1=20'b0;
reg [29:0] count2=30'b0;
reg [4:0] break1=5'b0;
reg [4:0] break2=5'b0;
reg [5:0] current_state, next_state;    // 现态、次态
reg key_pressed_flag=0;             // 键盘按下标志
reg [3:0] col_val, row_val; // 列值、行值
reg [19:0] cnt;
parameter NO_KEY_PRESSED = 6'b000_001;  // 没有按键按下
parameter SCAN_COL0      = 6'b000_010;  // 扫描第0列
parameter SCAN_COL1      = 6'b000_100;  // 扫描第1列
parameter SCAN_COL2      = 6'b001_000;  // 扫描第2列
parameter SCAN_COL3      = 6'b010_000;  // 扫描第3列
parameter KEY_PRESSED    = 6'b100_000;  // 有按键按下
//---------------------------------
parameter time1=1'd5;//在5秒内输入密码并确认
parameter time2=2'd20;//警报响触发后警报响20S
parameter N=5'd50000;
//警报置初始状态,alarm为灯,ring为铃
initial begin
alarm<=1'b1;
ring<=1'b0;
end
//==================================
//模块调用部分
LED u1(.seg_data_1(counter[3:0]),.seg_data_2(cout),.seg_led_1(shumaguan),.seg_led_2(led2));
divide #(.WIDTH(32),.N(12000000)) u2(.clk(clk),.rst_n(rst),.clkout(clk2));
LED_Display u3(.an(led4),.clk(clk),.seg(led3),.temp(password [23:20]));/*anjian u3(
.i_clk(clk),
.i_rst_n(rst),
.row(row),
.col(col),
.password(password),
.flag1(flag1)
);*/
//============================
//分频1:
always @(posedge clk)
begincount1<=count1+1'b1;if (count1==N)beginclk1<=~clk1;count1<=20'd0;end
end always@(posedge clk2)begin//采用的秒作时钟
if(flag1==1) begin  //flag=1时,开始输入密码counter=counter+1;if(counter<5)beginif(green_led==0)begin  //绿灯亮ring<=1'b0;flag2=0;  //电铃是否响的标志counter=5'b00000;end endelse if(counter<25 && counter>=5)beginring<=1'b1;flag2=1;  endelse begin  //保持初始状态ring<=1'b0;flag2=0;counter=5'b00000;endend
else begin
counter=5'b00000;
ring<=1'b0;
flag2=0;
end
endalways @ (posedge clk)cnt <= cnt + 1'b1;
wire key_clk = cnt[15];
always @ (posedge key_clk) begin
if(rst==1'b1)current_state <= next_state;end
always @ * begincase (current_state) NO_KEY_PRESSED :                    // 没有按键按下if (row != 4'hF)next_state = SCAN_COL0;elsenext_state = NO_KEY_PRESSED;SCAN_COL0 :                         // 扫描第0列 if (row != 4'hF)next_state = KEY_PRESSED;elsenext_state = SCAN_COL1;SCAN_COL1 :                         // 扫描第1列 if (row != 4'hF)next_state = KEY_PRESSED;elsenext_state = SCAN_COL2;    SCAN_COL2 :                         // 扫描第2列if (row != 4'hF)next_state = KEY_PRESSED;elsenext_state = SCAN_COL3;SCAN_COL3 :                         // 扫描第3列if (row != 4'hF)next_state = KEY_PRESSED;elsenext_state = NO_KEY_PRESSED;KEY_PRESSED :                       // 有按键按下if (row != 4'hF)next_state = KEY_PRESSED;elsenext_state = NO_KEY_PRESSED;                      endcaseend// 根据次态,给相应寄存器赋值
always @ (posedge key_clk) begin
if(rst==1'b1)begincase (next_state)NO_KEY_PRESSED :                  // 没有按键按下begincol              <= 4'h0;key_pressed_flag <= 1'b0;       // 清键盘按下标志endSCAN_COL0 :                       // 扫描第0列col <= 4'b1110;SCAN_COL1 :                       // 扫描第1列col <= 4'b1101;SCAN_COL2 :                       // 扫描第2列col <= 4'b1011;SCAN_COL3 :                       // 扫描第3列col <= 4'b0111;KEY_PRESSED :                     // 有按键按下begincol_val          <= col;        // 锁存列值row_val          <= row;        // 锁存行值key_pressed_flag <= 1'b1;          // 置键盘按下标志  endendcaseendend
//--------------------------------------
// 状态机部分 结束
//--------------------------------------//++++++++++++++++++++++++++++++++++++++
// 扫描行列值部分 开始
//++++++++++++++++++1++++++++++++++++++++
always @ (posedge key_clk) begin
if(rst==1'b1)beginif (key_pressed_flag==1'b1)begincase ({col_val, row_val})8'b1110_1110 : begin keyboard_val <= 4'h0; flag<=1; end8'b1110_1101 : begin keyboard_val <= 4'h4; flag<=1; end8'b1110_1011 : begin keyboard_val <= 4'h8; flag<=1; end// 8'b1110_0111 : keyboard_val <= 4'hC;8'b1101_1110 : begin keyboard_val <= 4'h1; flag<=1;end8'b1101_1101 : begin keyboard_val <= 4'h5;flag<=1;end8'b1101_1011 : begin keyboard_val <= 4'h9;flag<=1;end// 8'b1101_0111 : keyboard_val <= 4'hD;8'b1011_1110 : begin keyboard_val <= 4'h2;flag<=1;end8'b1011_1101 : begin keyboard_val <= 4'h6;flag<=1;end// 8'b1011_1011 : keyboard_val <= 4'hA;//  8'b1011_0111 : keyboard_val <= 4'hE;8'b0111_1110 : begin keyboard_val <= 4'h3; flag<=1;end8'b0111_1101 : begin keyboard_val <= 4'h7;flag<=1;end//  8'b0111_1011 : keyboard_val <= 4'hB;//  8'b0111_0111 : keyboard_val <= 4'hF;default:flag=0;        endcaseendelse flag=0;endend
//--------------------------------------
//  扫描行列值部分 结束
//--------------------------------------//写入密码模块 always@(posedge flag)//flag 是判断一个数字按下并且生效时begincase(cout)0:beginpassword [23:20]<=keyboard_val;cout<=cout+1;flag1=1;end1:beginpassword[19:16]<=keyboard_val;cout<=cout+1;end2:beginpassword[15:12]<=keyboard_val;cout<=cout+1;end3:beginpassword[11:8]<=keyboard_val;cout<=cout+1;end4:beginpassword[7:4]<=keyboard_val;cout<=cout+1;end5:beginpassword[3:0]<=keyboard_val;cout<=4'd0;enddefault:begin cout<=4'd0;flag1=0;end
endcase
end
//判断部分//密码操作部分:当按rst时当前的密码被设置为初始密码,否则将输入的密码与初始密码进行比较always@(posedge clk)beginif(rst==1'b1)beginif(sw1==1'b0)beginprevious_password<=password;//当按下rst时当前的密码被存为所密码endif(sw1==1'b1) begin if(sw2==1'b0)beginif(previous_password==password)beginred_led<=1'b1;green_led<=1'b0; endelse  beginred_led<=1'b0;green_led<=1'b1;  end endelse beginred_led<=1'b1;green_led<=1'b1;  endend
if(flag2==1) begin
green_led<=1'b1;
yellow_led<=1'b1;
red_led<=1'b1; end
end
end
endmodule

数码管模块

module LED (seg_data_1,seg_data_2,seg_led_1,seg_led_2);input [3:0] seg_data_1;                       //数码管需要显示0~9十个数字,所以最少需要4位输入做译码input [3:0] seg_data_2;                        //小脚丫上第二个数码管output [8:0] seg_led_1;                     //在小脚丫上控制一个数码管需要9个信号 MSB~LSB=DIG、DP、G、F、E、D、C、B、Aoutput [8:0] seg_led_2;                       //在小脚丫上第二个数码管的控制信号  MSB~LSB=DIG、DP、G、F、E、D、C、B、Areg [8:0] seg [9:0];                                            //定义了一个reg型的数组变量,相当于一个10*9的存储器,存储器一共有10个数,每个数有9位宽initial                                                         //在过程块中只能给reg型变量赋值,Verilog中有两种过程块always和initial//initial和always不同,其中语句只执行一次beginseg[0] = 9'h3f;                                           //对存储器中第一个数赋值9'b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字  0seg[1] = 9'h06;                                           //7段显示数字  1seg[2] = 9'h5b;                                           //7段显示数字  2seg[3] = 9'h4f;                                           //7段显示数字  3seg[4] = 9'h66;                                           //7段显示数字  4seg[5] = 9'h6d;                                           //7段显示数字  5seg[6] = 9'h7d;                                           //7段显示数字  6seg[7] = 9'h07;                                           //7段显示数字  7seg[8] = 9'h7f;                                           //7段显示数字  8seg[9] = 9'h6f;                                           //7段显示数字  9endassign seg_led_1 = seg[seg_data_1];          //连续赋值,这样输入不同四位数,就能输出对于译码的9位输出assign seg_led_2 = seg[seg_data_2];endmodule

分频模块

module divide (clk,rst_n,clkout);input   clk,rst_n;                       //输入信号,其中clk连接到FPGA的C1脚,频率为12MHzoutput   clkout;                          //输出信号,可以连接到LED观察分频的时钟//parameter是verilog里常数语句parameter WIDTH   = 3;             //计数器的位数,计数的最大值为 2**WIDTH-1parameter   N   = 12000000/8;          //分频系数,请确保 N < 2**WIDTH-1,否则计数会溢出// reg N1=N/count;reg    [WIDTH-1:0] cnt_p,cnt_n;     //cnt_p为上升沿触发时的计数器,cnt_n为下降沿触发时的计数器reg  clk_p,clk_n;     //clk_p为上升沿触发时分频时钟,clk_n为下降沿触发时分频时钟//上升沿触发时计数器的控制always @ (posedge clk or negedge rst_n )         //posedge和negedge是verilog表示信号上升沿和下降沿//当clk上升沿来临或者rst_n变低的时候执行一次always里的语句beginif(!rst_n)cnt_p<=0;else if (cnt_p==(N-1))cnt_p<=0;else cnt_p<=cnt_p+1;             //计数器一直计数,当计数到N-1的时候清零,这是一个模N的计数器end//上升沿触发的分频时钟输出,如果N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50%always @ (posedge clk or negedge rst_n)beginif(!rst_n)clk_p<=0;else if (cnt_p<N>>1)          //N>>1表示右移一位,相当于除以2去掉余数clk_p<=0;else clk_p<=1;               //得到的分频时钟正周期比负周期多一个clk时钟end   //下降沿触发时计数器的控制          always @ (negedge clk or negedge rst_n)beginif(!rst_n)cnt_n<=0;else if (cnt_n==(N-1))cnt_n<=0;else cnt_n<=cnt_n+1;end//下降沿触发的分频时钟输出,和clk_p相差半个时钟always @ (negedge clk)beginif(!rst_n)clk_n<=0;else if (cnt_n<N>>1)  clk_n<=0;else clk_n<=1;                //得到的分频时钟正周期比负周期多一个clk时钟endassign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p;      //条件判断表达式//当N=1时,直接输出clk//当N为偶数也就是N的最低位为0,N(0)=0,输出clk_p//当N为奇数也就是N最低位为1,N(0)=1,输出clk_p&clk_n。正周期多所以是相与
endmodule

Verliog 写电子密码锁相关推荐

  1. 51单片机50个实例代码_【附代码】51单片机电子密码锁教程

    简介 大家好,这篇文章的内容是关于如何用51单片机来制作一个电子密码锁的教程,通过这篇教程可以让刚入门的朋友了解矩阵键盘.LCD1602的使用方法,以及密码输入和修改的程序介绍,我会对每个部分进行详细 ...

  2. “药药切克闹”系列-基于STM32触摸屏的超级无敌智能电子密码锁(仿手机键盘26键设计,密码支持英文大写+英文小写+数字)

    项目名称:"药药切克闹"系列-基于STM32触摸屏的超级无敌智能电子密码锁(密码支持英文大写+英文小写+数字) CSDN:YANG-03                      ...

  3. 51单片机:设计电子密码锁

    文章目录 一.课程设计内容 功能阐述 二.开发板原理图与设计流程图 三.设计思路和方法 1.EEPROM初始化 2.LCD1602初始化 3.矩阵按键扫描 4.输入密码 5.密码比对 四.源代码附录 ...

  4. 基于FPGA的电子密码锁

    基于FPGA的电子密码锁 实现的功能: 1. 设计制作一个数字密码锁,共有8位密码,要求该密码是字母与数字的结合.输入密码由LCD显示 2. 系统上电后,8位初始密码为0000_0000. 3. 输入 ...

  5. 【制作】基于金沙滩51单片机的电子密码锁程序

    基于金沙滩51单片机的电子密码锁程序 很久之前做的一个课设,在B站发了效果视频,发现忘记分享代码了,现在整理分享一下. 零.设计报告 1.设计要求 这部分是讲的整个系统实现了什么功能. 1.1.密码的 ...

  6. 电子密码锁课设单片机c语言,基于51单片机的电子密码锁综合课程设计

    5.大容量片内EEPROM,擦写次数10万次以上 EEPROM,擦写次数10万次以上,擦写次数10万次以上 6.ISP/IAP,在系统可编程/在应用可编程,无需编程器/仿真器 7.共8通道10位高速A ...

  7. 西电A测 | 基于Arduino uno的电子密码锁仿真系统 | 使用Proteus仿真 | Arduino IDE编写

    西电A测 | 基于Arduino uno的电子密码锁仿真系统 | 使用Proteus仿真 | Arduino IDE编写 | ATMEGA328P 电子密码锁系统 Arduino UNO Arduin ...

  8. 基于C语言STC89C52单片机电子密码锁的设计与仿真

    arm实现较为简单, 功能较为完善, 因此使用单片机控制较多. 显示器少数用数码管. 而本文所介绍的电子密码锁使用移植性及可读性强的高级语言C语言编写, 使用更加方便. 从经济适用的角度出发, 采用S ...

  9. VHDL电子密码锁设计

    主要内容: 采用先进的EDA技术,利用MAX+PLUSⅡ工作平台和VHDL语言,设计一种新型的电子密码锁.该密码锁具有密码预置和误码报警等功能,用一片FPGA芯片实现. 摘要 本文介绍一种利用EDA技 ...

  10. 基于stm32的c语言程序设计,基于stm32的电子密码锁设计 main.c 代码奉上,做课设的直接用...

    电子密码锁设计 **功能:支持3~20位的密码设置,初始密码为123456:若要重设密码,需先输入正确密码开锁. ** 正常显示情况下,按下确认键上锁:按下密码键,开始输入密码. **接线:PE[0. ...

最新文章

  1. ieda中快捷搜索_IntelliJ IDEA IDE设置系列教程(十):在工具窗口中快速搜索
  2. python接口自动化用例管理_python接口自动化测试(六)-unittest-单个用例管理
  3. oracle 数据库查询 COALESCE字符函数
  4. sqlserver 2008安装总是弹出重启提示
  5. pta段错误是什么意思_用Python执行Django数据迁移时报!(1091错误及解决方法)...
  6. 拉普拉斯算子属于卷积方法吗_2020 年 GNN 开卷有益与再谈图卷积
  7. 根据xml文件生成对应javabean类
  8. jrtplib的使用
  9. PHP在线预览word文档的功能
  10. 利用讯飞语音听写接口实现实时语音转写。
  11. 《浪潮之巅》读书笔记
  12. 多元线性回归分析spss结果解读_SPSS 多元线性回归结果重要参数解读
  13. orocos安装_动脑共享单车环境搭建
  14. C# 简单判断枚举值是否被定义
  15. JQuery 判断访问的浏览器是pc还是手机
  16. 分布式系统数据层设计模式
  17. 2011网易校园招聘笔试题
  18. 权限管理中的RBAC与ABAC
  19. Linux开发者的CI/CD(8)静态代码检查工具cppcheck使用大全
  20. excel 置信区间 计算_如何用excel计算95%的置信区间 | 在excle中如何进行区间估计...

热门文章

  1. 幂函数导数公式的推导
  2. c语言圆周长面积公式,怎么用c语言计算圆周长和面积
  3. 基于PLC的锅炉控制,基于s7-200的锅炉压力控制的设计,基于西门子S7-200plc与MCGS锅炉压力PID控制系统设计
  4. I'm just a baby——8月份英语总结
  5. 数据分析实战——淘宝母婴用品购买情况
  6. Linux系统zip压缩命令
  7. HTML链接会议申请,会议流程.html
  8. 桌面上出现两个计算机图标,电脑桌面图标出现成双显示要怎么解决
  9. 智能汽车域控制器的认识
  10. 上市公司环境数据集:环境绩效明细表、排放明细表、资源消耗明细表等多项指标数据