各位好我是Toporanger 本人只会写代码 不会教人 毕竟自己的代码也是改来改去最终成功的 如果有不够精简的地方还请见谅
我会先贴下代码 然后贴上管脚的绑定图 无论是拿来救急还是作为参考都希望帮助到你们
题目:设计一个密码保险箱。
调研市场需求,自行确定保险箱的功能。能被市场认可的产品才是好产品;销量越大,产品设计越成功。你的箱子你做主!要求:
1. 用文字准确描述密码箱的功能和安全性。
2. 用Verilog HDL实现并在FPGA开发板上验证。
代码:
主函数:
`timescale 1ns / 1ps
// 模块hw_4: 实现一个简单的密码锁功能,包括密码输入、状态显示和密码修改
module hw_4 (
input clk, // 时钟信号
input rst, // 复位信号
input key1, // 按键1,用于密码修改模式
input key2, // 按键2,用于确认密码修改
input key3, // 按键3,用于密码输入验证
input sw1, sw2, sw3, sw4, // 开关,用于密码输入
output reg led1, led2, led3, led4, // LED灯,显示开关状态
output reg seg_led1, // 密码状态灯,正确时熄灭
output reg seg_led2, // 密码锁状态灯,解锁时熄灭
output reg seg_led3 // 密码修改状态灯,修改模式时熄灭
);
// 密码和尝试次数寄存器
reg [3:0] password;
reg [3:0] count;
// 按键脉冲信号(假设有外部电路或逻辑生成这些脉冲信号)
wire key1_pulse;
wire key2_pulse;
wire key3_pulse;
// 主逻辑
always @(posedge clk) begin
if (!rst) begin
// 复位逻辑,初始化状态和密码
seg_led1 <= 1'b1;
seg_led3 <= 1'b1;
password <= 4'b0100; // 初始密码设为"0100"
seg_led2 <= 1'b1;
count <= 4'b0000;
end
else if (count == 4'b0110) begin
// 密码输入次数超限,锁定
seg_led2 <= 1'b0;
end
else begin
// 密码输入逻辑
if (seg_led1 && seg_led3 && key3_pulse) begin
count <= count + 1'b1;
end
// 显示开关状态
led1 <= sw1;
led2 <= sw2;
led3 <= sw3;
led4 <= sw4;
// 密码验证逻辑
if (seg_led2 && seg_led3 && key3_pulse) begin
case ({sw1, sw2, sw3, sw4})
password: seg_led1 <= 1'b0; // 密码正确
default: seg_led1 <= 1'b1; // 密码错误
endcase
end
// 进入密码修改模式
if (seg_led2 && !seg_led1 && key1_pulse) begin
seg_led3 <= 1'b0;
end
// 确认并修改密码
if (seg_led2 && !seg_led1 && !seg_led3 && key2_pulse) begin
seg_led3 <= 1'b1;
seg_led1 <= 1'b1;
password <= {sw1, sw2, sw3, sw4}; // 更新密码
count <= 4'b0000; // 重置尝试次数
end
end
end
endmodule
消抖模块:
module debounce (clk,rst,key,key_pulse);
parameter N = 1; //要消除的按键的数量
input clk;
input rst;
input [N-1:0] key; //输入的按键
output [N-1:0] key_pulse; //按键动作产生的脉冲
reg [N-1:0] key_rst_pre; //定义一个寄存器型变量存储上一个触发时的按键值
reg [N-1:0] key_rst; //定义一个寄存器变量储存储当前时刻触发的按键值
wire [N-1:0] key_edge; //检测到按键由高到低变化是产生一个高脉冲
//利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中
always @(posedge clk or negedge rst)
begin
if (!rst) begin
key_rst <= {N{1'b1}}; //初始化时给key_rst赋值全为1,{}中表示N个1
key_rst_pre <= {N{1'b1}};
end
else begin
key_rst <= key; //第一个时钟上升沿触发之后key的值赋给key_rst,同时key_rst的值赋给key_rst_pre
key_rst_pre <= key_rst; //非阻塞赋值。相当于经过两个时钟触发,key_rst存储的是当前时刻key的值,key_rst_pre存储的是前一个时钟的key的值
end
end
assign key_edge = key_rst_pre & (~key_rst);//脉冲边沿检测。当key检测到下降沿时,key_edge产生一个时钟周期的高电平
reg [17:0] cnt; //产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器
//产生20ms延时,当检测到key_edge有效是计数器清零开始计数
always @(posedge clk or negedge rst)
begin
if(!rst)
cnt <= 18'h0;
else if(key_edge)
cnt <= 18'h0;
else
cnt <= cnt + 1'h1;
end
reg [N-1:0] key_sec_pre; //延时后检测电平寄存器变量
reg [N-1:0] key_sec;
//延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如果按键状态是高的话说明按键无效
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec <= {N{1'b1}};
else if (cnt==18'h3ffff)
key_sec <= key;
end
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec_pre <= {N{1'b1}};
else
key_sec_pre <= key_sec;
end
assign key_pulse = key_sec_pre & (~key_sec);
endmodule
管脚图