基于FPGA的智能电子密码指纹锁
一、功能描述
1.6位密码,可修改,数码管显示输入密码过程,错误一定次数后报警
2.指纹验证,验证正确与错误对应的灯闪烁
3.4*4数字键盘,输入密码使用
4.板卡按键,负责状态切换
硬件资源需求
AS608 指纹模块
4*4数字键盘模块
再就是开发板上的一些按键、LED灯等等资源了。
二、整体框架
根据模块以及功能分别编写代码,TOP顶层模块、AS608指纹模块、串口通信模块、指纹检测模块、密码输入检测模块、修改密码模块以及数码管显示模块。如图所示,vavido根据代码调用关系自动生成的原理图。
知识准备
AS608指纹模块
通信方式:UART
通信速率:9600*N(N:1~12),默认57600
通信格式:遵循手册按照数据格式发送不同的指令数据,根据返回的数据包判断实际状态。
使用流程:
存指纹:读取指纹图像->生成特征1->读取指纹图像->生成特征2->对比特征->生成指纹模版
刷指纹:读取指纹图像->生成特征->搜索指纹图像
删除指纹:删除指纹/删除整个指纹库
例如:读取指纹图像
可以通过TTL与指纹模块连接,通过串口调试助手进行实验:
发:EF 01 FF FF FF FF 01 00 03 01 00 05
收:EF 01 FF FF FF FF 07 00 03 00 00 0A
因此后续模块代码编写就是基于功能发送不同的指令包数据
4*4数字键盘模块
如图,要明确该模块通过4+4根线控制,读取16个按键状态。其中4条行线作为output,4条列线作为input。
整体读取按键流程:给P10这一行高电平,扫描列,如果检测到P15为高电平,说明第一行第二个按键按下。也就是代码要循环给予不同行高电平,然后确定列状态,进而确定按键。output:1000,input是0100,就说明第一行第二个按键被按下。
三、Verilog代码实现以及仿真验证
1.AS608_data模块
实现思想:状态机
一路顺利就是这么个流程,不顺利的话就回到上个可以重新开始的流程。
c
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/12/01 21:43:28
// Design Name:
// Module Name: AS608_data
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module AS608_data(
input clk,
input rst_n,
input WAK,
input key1,
input key2,
input key3,
input key4,
input key5,
input uart_tx_done,
input [7:0] uart_rx_data,
input uart_rx_done,
output reg led_hand1,
output reg led_hand2,
output reg led_hand3,
output reg hand_flag_r1,
output reg check_hand_flag,
output reg uart_tx_en,
output reg [7:0] uart_tx_data
);
parameter IDLE = 8'd0;
parameter WAK_HAND1 = 8'd20;
parameter WAK_HAND2 = 8'd21;
parameter WAK_FEATURE1 = 8'd22;
parameter WAK_FEATURE2 = 8'd23;
parameter WAK_COMPARE = 8'd24;
parameter WAK_SAVE = 8'd25;
parameter WAK_SEND = 8'd26;
parameter WAK_FIND = 8'd27;
parameter HAND1_LED = 8'd28;
parameter HAND2_LED = 8'd29;
parameter SAVE_LED = 8'd30;
parameter GET_HAND1 = 8'd1;
parameter GET_HAND2 = 8'd2;
parameter GET_HAND_DONE = 8'd3;
parameter SEND_HAND = 8'd4;
parameter SEND_HAND_DONE = 8'd5;
parameter MAKE_FEATURE1 = 8'd6;
parameter MAKE_FEATURE2 = 8'd7;
parameter MAKE_DONE = 8'd8;
parameter COMPARE_FEATURE = 8'd9;
parameter SEND_FEATURE = 8'd10;
parameter SAVE_FEATURE = 8'd11;
parameter FIND_HAND = 8'd12;
parameter DELDETE_FEATURE = 8'd13;
parameter DELDETE_ALL_FEATURE = 8'd14;
reg [95:0] cmd_state ={8'hEF,8'h01,8'hFF,8'hFF,8'hFF,8'hFF,8'h01,8'h00,8'h03,8'h01,8'h00,8'h05};
//应答格式 EF01 FFFFFFFF 07 03 XX SUM, XX= 00success 01error 02wait 03unsuccess
reg [103:0] cmd_make1 ={8'hEF,8'h01,8'hFF,8'hFF,8'hFF,8'hFF,8'h01,8'h00,8'h04,8'h02,8'h01,8'h00,8'h08};
reg [103:0] cmd_make2 ={8'hEF,8'h01,8'hFF,8'hFF,8'hFF,8'hFF,8'h01,8'h00,8'h04,8'h02,8'h02,8'h00,8'h09};
reg [95:0] cmd_compare ={8'hEF,8'h01,8'hFF,8'hFF,8'hFF,8'hFF,8'h01,8'h00,8'h03,8'h03,8'h00,8'h07};
reg [95:0] cmd_save ={8'hEF,8'h01,8'hFF,8'hFF,8'hFF,8'hFF,8'h01,8'h00,8'h03,8'h05,8'h00,8'h09};
reg [119:0] cmd_send ={8'hEF,8'h01,8'hFF,8'hFF,8'hFF,8'hFF,8'h01,8'h00,8'h06,8'h06,8'h02,8'h00,8'h01,8'h00,8'h10};
reg [135:0] cmd_find ={8'hEF,8'h01,8'hFF,8'hFF,8'hFF,8'hFF,8'h01,8'h00,8'h08,8'h1B,8'h01,8'h00,8'h00,8'h00,8'h63,8'h00,8'h88};
//应答格式 EF01 FFFFFFFF 07 07 XX ID MATH SUM, XX= 00success 01error 02wait 03unsuccess 16btye
reg [3:0] blink_counter; // 用于计数闪烁次数
reg [15:0] blink_timer; // 用于生成 1 秒钟的闪烁周期
reg [15:0] error_timer; // 用于生成 1 秒钟的闪烁周期
reg hand_flag;
reg hand_flag_r;
reg uart_tx_vaild;
reg uart_tx_en_temp;
reg [7:0] state;
reg [5:0] tx_count;
reg [5:0] rx_count;
reg return_flag;
reg [1:0] tx_en_count;
reg [7:0] return_data;
reg find_flag;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
hand_flag_r1<=1'b0;
hand_flag_r<=1'b0;
end else begin
hand_flag_r1<=hand_flag;
hand_flag_r<=hand_flag_r1;
end
end
//各个状态return_data
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
uart_tx_data <= 8'd0;
end
else if((state==GET_HAND1 || state==GET_HAND2) && tx_count<6'd12 ) begin
uart_tx_data <= cmd_state[95 - tx_count *8 -:8];
end
else if((state==FIND_HAND) && tx_count<6'd17 ) begin
uart_tx_data <= cmd_find[135 - tx_count *8 -:8];
end
else if((state==COMPARE_FEATURE) && tx_count<6'd12 ) begin
uart_tx_data <= cmd_compare[95 - tx_count *8 -:8];
end
else if((state==SAVE_FEATURE) && tx_count<6'd12 ) begin
uart_tx_data <= cmd_save[95 - tx_count *8 -:8];
end
else if((state==SEND_FEATURE) && tx_count<6'd15 ) begin
uart_tx_data <= cmd_send[119 - tx_count *8 -:8];
end
else if((state==MAKE_FEATURE1) && tx_count<6'd13 ) begin
uart_tx_data <= cmd_make1[103 - tx_count *8 -:8];
end
else if((state==MAKE_FEATURE2) && tx_count<6'd13 ) begin
uart_tx_data <= cmd_make2[103 - tx_count *8 -:8];
end
else begin
uart_tx_data <= uart_tx_data;
end
end
//各个状态return_flag
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
find_flag <= 1'b0;
end
else if(key2==1'b1)begin
find_flag <= ~find_flag;
end
else begin
find_flag <= find_flag;
end
end
//各个状态return_flag
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
return_flag <= 1'b0;
end
else if((state==WAK_HAND1 ||state==WAK_HAND2) && return_data==8'h00&& rx_count==11 && uart_rx_done==1'b1) begin
return_flag <= 1'b1;
end
else if((state==WAK_FEATURE1 ||state==WAK_FEATURE2 || state== WAK_COMPARE || state==WAK_SAVE || state==WAK_SEND ) && return_data==8'h00 && rx_count==11 && uart_rx_done==1'b1) begin
return_flag <= 1'b1;
end
else if((state==WAK_FIND) && return_data==8'h00 && rx_count==15 && uart_rx_done==1'b1) begin
return_flag <= 1'b1;
end
else begin
return_flag <= 1'b0;
end
end
//各个状态return_data
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
return_data <= 8'b0;
end
else if((state==WAK_HAND1 ||state==WAK_HAND2) && rx_count==10 ) begin
return_data <= uart_rx_data;
end
else if((state==WAK_FEATURE1 ||state==WAK_FEATURE2 || state== WAK_COMPARE || state==WAK_SAVE || state==WAK_FIND) && rx_count==10 ) begin
return_data <= uart_rx_data;
end
else begin
return_data <= return_data;
end
end
//各个状态data_tx_en
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
uart_tx_en_temp <= 1'b0;
uart_tx_en <= uart_tx_en_temp;
end
else if((state==GET_HAND1 || state==GET_HAND2 || state==COMPARE_FEATURE || state==SAVE_FEATURE) && tx_en_count==1) begin
uart_tx_en_temp <= 1'b1;
uart_tx_en <= uart_tx_en_temp;
end
else if((state==MAKE_FEATURE1 || state==MAKE_FEATURE2 || state==SEND_FEATURE || state==FIND_HAND ) && tx_en_count==1) begin
uart_tx_en_temp <= 1'b1;
uart_tx_en <= uart_tx_en_temp;
end
else if((state==GET_HAND1 || state==GET_HAND2 || state==COMPARE_FEATURE || state==SAVE_FEATURE) && tx_count<6'd11 && uart_tx_done==1)begin
uart_tx_en_temp <= 1'b1;
uart_tx_en <= uart_tx_en_temp;
end
else if((state==MAKE_FEATURE1 || state==MAKE_FEATURE2) && tx_count<6'd12 && uart_tx_done==1)begin
uart_tx_en_temp <= 1'b1;
uart_tx_en <= uart_tx_en_temp;
end
else if((state==SEND_FEATURE) && tx_count<6'd14 && uart_tx_done==1)begin
uart_tx_en_temp <= 1'b1;
uart_tx_en <= uart_tx_en_temp;
end
else if((state==FIND_HAND) && tx_count<6'd16 && uart_tx_done==1)begin
uart_tx_en_temp <= 1'b1;
uart_tx_en <= uart_tx_en_temp;
end
else begin
uart_tx_en_temp <= 1'b0;
uart_tx_en <= uart_tx_en_temp;
end
end
//各个状态rx_count
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
rx_count <= 6'd0;
end
else if((state==WAK_HAND1 ||state==WAK_HAND2 || state==WAK_FEATURE1 ||state==WAK_FEATURE2 || state== WAK_COMPARE || state==WAK_SAVE || state==WAK_SEND) ) begin
if(uart_rx_done==1'd1)
rx_count <= rx_count+1'b1;
else if(rx_count==6'd12) begin
rx_count <= 6'b0;
end
else begin
rx_count <= rx_count;
end
end
else if((state==WAK_FIND) ) begin
if(uart_rx_done==1'd1)
rx_count <= rx_count+1'b1;
else if(rx_count==6'd16) begin
rx_count <= 6'b0;
end
else begin
rx_count <= rx_count;
end
end
end
//各个状态tx_count
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
tx_count <= 6'd0;
end
else if((state==GET_HAND1 || state==GET_HAND2 || state==COMPARE_FEATURE || state==SAVE_FEATURE) ) begin
if(uart_tx_done==1'd1)
tx_count <= tx_count+1'b1;
else if(tx_count==6'd12) begin
tx_count <= 6'b0;
end
else begin
tx_count <= tx_count;
end
end
else if((state==MAKE_FEATURE1 || state==MAKE_FEATURE2) ) begin
if(uart_tx_done==1'd1)
tx_count <= tx_count+1'b1;
else if(tx_count==6'd13) begin
tx_count <= 6'b0;
end
else begin
tx_count <= tx_count;
end
end
else if((state==SEND_FEATURE) ) begin
if(uart_tx_done==1'd1)
tx_count <= tx_count+1'b1;
else if(tx_count==6'd15) begin
tx_count <= 6'b0;
end
else begin
tx_count <= tx_count;
end
end
else if((state==FIND_HAND) ) begin
if(uart_tx_done==1'd1)
tx_count <= tx_count+1'b1;
else if(tx_count==6'd17) begin
tx_count <= 6'b0;
end
else begin
tx_count <= tx_count;
end
end
end
//tx_en time
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
tx_en_count <= 2'b0;
end
else if((state==GET_HAND1 || state==GET_HAND2 || state==MAKE_FEATURE1 || state==MAKE_FEATURE2 || state==COMPARE_FEATURE || state==SAVE_FEATURE|| state==SEND_FEATURE || state==FIND_HAND) && tx_en_count<2'd1 && tx_count==6'd0) begin
tx_en_count <=tx_en_count+ 2'd1;
end
else if((state==GET_HAND1 || state==GET_HAND2 || state==MAKE_FEATURE1 || state==MAKE_FEATURE2 || state==COMPARE_FEATURE || state==SAVE_FEATURE|| state==SEND_FEATURE || state==FIND_HAND) && tx_en_count==2'd1 && tx_count==6'd0) begin
tx_en_count <= 2'd3;
end
else if((state==WAK_HAND1 ||state==WAK_HAND2 || state==WAK_FEATURE1 ||state==WAK_FEATURE2 || state==WAK_COMPARE || state==WAK_SAVE || state==WAK_SEND || state==WAK_FIND))begin
tx_en_count <= 2'd0;
end
else begin
tx_en_count <= tx_en_count;
end
end
//state go
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
state <= IDLE;
hand_flag<=1'b0;
led_hand1<=1'b0;
led_hand2<=1'b0;
led_hand3<=1'b0;
check_hand_flag<=1'b0;
blink_counter <= 0;
end
else begin
case(state)
IDLE:begin
blink_counter <= 0;
hand_flag<=1'b0;
check_hand_flag<=1'b0;
if(key1==1'b1 && WAK==1'b1)begin
state <= GET_HAND1;
end
else begin
state <= IDLE;
end
end
GET_HAND1:begin
if(tx_count==6'd12)begin
state <= WAK_HAND1;
end
else begin
state <= GET_HAND1;
end
end
WAK_HAND1:begin
if(rx_count==6'd12 && return_flag==1'b1)begin
state <= MAKE_FEATURE1;
end
else if(rx_count==6'd12 && return_flag==1'b0)begin
state <= IDLE;
end
else begin
state <= WAK_HAND1;
end
end
HAND1_LED: begin
if (blink_counter < 2) begin
if (blink_timer == 16'd0) begin
led_hand1 = ~led_hand1; // 每秒反转一次 led
blink_counter = blink_counter + 1;
end
end else begin
state = MAKE_FEATURE1; // 完成 10 次闪烁后返回 IDLE 状态
end
end
MAKE_FEATURE1:begin
if(tx_count==6'd13)begin
state <= WAK_FEATURE1;
end
else begin
state <= MAKE_FEATURE1;
end
end
WAK_FEATURE1:begin
if(find_flag==1'b0) begin
if(rx_count==6'd12 && return_flag==1'b1)begin
state <= GET_HAND2;
end
else if(rx_count==6'd12 && return_flag==1'b0)begin
state <= IDLE;
end
else begin
state <= WAK_FEATURE1;
end
end
else begin
if(rx_count==6'd12 && return_flag==1'b1)begin
state <= FIND_HAND;
end
else if(rx_count==6'd12 && return_flag==1'b0)begin
state <= IDLE;
end
else begin
state <= WAK_FEATURE1;
end
end
end
GET_HAND2:begin
blink_counter <= 0;
if(tx_count==6'd12)begin
state <= WAK_HAND2;
end
else begin
state <= GET_HAND2;
end
end
WAK_HAND2:begin
if(rx_count==6'd12 && return_flag==1'b1)begin
state <= MAKE_FEATURE2;
end
else if(rx_count==6'd12 && return_flag==1'b0)begin
state <= GET_HAND2;
end
else begin
state <= WAK_HAND2;
end
end
HAND2_LED: begin
if (blink_counter < 2) begin
if (blink_timer == 16'd0) begin
led_hand2 = ~led_hand2; // 每秒反转一次 led
blink_counter = blink_counter + 1;
end
end else begin
state = MAKE_FEATURE2; // 完成 10 次闪烁后返回 IDLE 状态
end
end
MAKE_FEATURE2:begin
if(tx_count==6'd13)begin
state <= WAK_FEATURE2;
end
else begin
state <= MAKE_FEATURE2;
end
end
WAK_FEATURE2:begin
if(rx_count==6'd12 && return_flag==1'b1)begin
state <= COMPARE_FEATURE;
end
else if(rx_count==6'd12 && return_flag==1'b0)begin
state <= IDLE;
end
else begin
state <= WAK_FEATURE2;
end
end
COMPARE_FEATURE:begin
if(tx_count==6'd12)begin
state <= WAK_COMPARE;
end
else begin
state <= COMPARE_FEATURE;
end
end
WAK_COMPARE:begin
if(rx_count==6'd12 && return_flag==1'b1)begin
state <= SAVE_FEATURE;
end
else if(rx_count==6'd12 && return_flag==1'b0)begin
state <= IDLE;
end
else begin
state <= WAK_COMPARE;
end
end
SAVE_FEATURE:begin
if(tx_count==6'd12)begin
state <= WAK_SAVE;
end
else begin
state <= SAVE_FEATURE;
end
end
WAK_SAVE:begin
if(rx_count==6'd12 && return_flag==1'b1)begin
state <= SEND_FEATURE;
end
else if(rx_count==6'd12 && return_flag==1'b0)begin
state <= IDLE;
end
else begin
state <= WAK_SAVE;
end
end
SEND_FEATURE:begin
if(tx_count==6'd15)begin
state <= WAK_SEND;
end
else begin
state <= SEND_FEATURE;
end
end
WAK_SEND:begin
if(rx_count==6'd12 && return_flag==1'b1)begin
state <= IDLE;
end
else if(rx_count==6'd12 && return_flag==1'b0)begin
state <= IDLE;
end
else begin
state <= WAK_SEND;
end
end
SAVE_LED: begin
if (blink_counter < 2) begin
if (blink_timer == 16'd0) begin
led_hand3 = ~led_hand3; // 每秒反转一次 led
blink_counter = blink_counter + 1;
end
end else begin
state = IDLE; // 完成 10 次闪烁后返回 IDLE 状态
end
end
FIND_HAND:begin
if(tx_count==6'd17)begin
state <= WAK_FIND;
end
else begin
state <= FIND_HAND;
end
end
WAK_FIND:begin
if(rx_count==6'd16 && return_flag==1'b1)begin
state <= IDLE;
check_hand_flag<=1'b1;
hand_flag<=1'b1;
end
else if(rx_count==6'd16 && return_flag==1'b0)begin
state <= IDLE;
check_hand_flag<=1'b1;
hand_flag<=1'b0;
end
else begin
state <= WAK_FIND;
end
end
default:state <= IDLE;
endcase
end
end
// 计时器,用于实现 1 秒钟的闪烁周期
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
blink_timer <= 0;
end else begin
if (state == HAND2_LED ||state == HAND1_LED ||state == SAVE_LED) begin
if (blink_timer == 16'd49999) // 假设时钟频率是 50MHz,每 1 秒
blink_timer <= 0;
else
blink_timer <= blink_timer + 1;
end else begin
blink_timer <= 0;
end
end
end
endmodule
2.check_hand模块
通过check_hand_flag控制进入检验CHECK状态,通过hand_flag确定指纹验证是否正确。正确就led_hand_right闪,错误就led_hand_error。这两个标志是通过AS608模块传出来的。
代码如下(示例):
c
module check_hand(
input clk,
input rst_n,
input hand_flag,
input check_hand_flag,
output reg led_hand_right,
output reg led_hand_error
);
// 状态定义
parameter IDLE = 2'b00; // 等待状态
parameter CHECK = 2'b01; // 检测状态
parameter BLINK = 2'b10; // 闪烁状态
parameter ERROR = 2'b11; // 错误状态
// 状态寄存器
reg [1:0] state;
reg [3:0] blink_counter; // 用于计数闪烁次数
reg [15:0] blink_timer; // 用于生成 1 秒钟的闪烁周期
reg [15:0] error_timer; // 用于生成 1 秒钟的闪烁周期
// 计时器,用于实现 1 秒钟的闪烁周期
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
blink_timer <= 0;
end else begin
if (state == BLINK) begin
if (blink_timer == 16'd49999) // 假设时钟频率是 50MHz,每 1 秒
blink_timer <= 0;
else
blink_timer <= blink_timer + 1;
end else begin
blink_timer <= 0;
end
end
end
// 错误状态计时器(10秒)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
error_timer <= 0;
end else if (state == ERROR) begin
if (error_timer == 16'd49999) // 假设时钟频率是 50MHz,10秒
error_timer <= 0; // 超过 10 秒后,计时器重置
else
error_timer <= error_timer + 1;
end else begin
error_timer <= 0; // 不是错误状态时,计时器清零
end
end
// 状态转移与输出逻辑
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
state <=IDLE;
led_hand_right <= 0;
led_hand_error <=0;
end
else begin
case(state)
IDLE: begin
if (check_hand_flag) begin
state <=CHECK; // 如果检测标志位为1,进入检测状态
end
else begin
state <=IDLE;
end
end
CHECK: begin
if (hand_flag) begin
state <= BLINK; // 如果手势正确,进入闪烁状态
end else begin
state <= ERROR; // 如果手势错误,进入错误状态
end
end
BLINK: begin
if (blink_counter < 10) begin
if (blink_timer == 16'd0) begin
led_hand_right = ~led_hand_right; // 每秒反转一次 led
blink_counter = blink_counter + 1;
end
end else begin
state = IDLE; // 完成 10 次闪烁后返回 IDLE 状态
end
end
ERROR: begin
if (blink_counter < 10) begin
if (error_timer == 16'd0) begin
led_hand_error <= ~led_hand_error; // 错误时,led_hand_error 10次
blink_counter <= blink_counter + 1;
end
end else begin
state <= IDLE; // 完成 10 次闪烁后返回 IDLE 状态
end
end
endcase
end
end
// 控制闪烁次数
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
blink_counter <= 0;
end else if (state == IDLE) begin
blink_counter <= 0; // 重置闪烁计数器
end
end
endmodule
3.four_four_key模块
矩阵按键模块,通过给予不同行高电平,然后检测列状态,得出按键的状态。
c
`timescale 1ns / 1ps
//
// Company: NanJing University of Information Science & Technology
// Engineer: Yang Cheng Yu
//
// Create Date: 2020/01/13 20:01:50
// Design Name: keyboard_4_4
// Module Name: keyboard_4_4
// Project Name: Clock
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module four_four_key(
input clk,//时钟
input rst,//复位
output reg[3:0] c_pin,//行引脚
input[3:0] r_pin,//列引脚
output reg[3:0] key_out,//按键编号输出
output wire[3:0] key_pulse//按键编号输出
);
reg[3:0] key_out_r;
reg[15:0] div_cnt;//分频计数器
reg[2:0] state;
reg[2:0] state_r;
reg cnt_full;//分频计数器计满逻辑
wire clear_flag;
localparam CHECK_R1=3'b000;//检测R1
localparam CHECK_R2=3'b001;//检测R2
localparam CHECK_R3=3'b011;//检测R3
localparam CHECK_R4=3'b010;//检测R4
always @(posedge clk or negedge rst)
begin
if(!rst) begin
state_r <= 3'b0;
end
else begin
state_r <= state;
end
end
assign clear_flag= (state_r==state)?1:0;
always @(posedge clk or negedge rst)
begin
if(!rst) begin
key_out_r <= 4'b0;
end
else begin
key_out_r <= key_out;
end
end
//Detect the negedge of low_sw, generate pulse
// assign key_pulse= key_out_r & ( ~key_out);
assign key_pulse= (key_out_r==key_out)?1:0;
//分频计数器逻辑
always@(posedge clk or negedge rst)begin//此处设计每次拉高一行时间为1ms
if(!rst)begin
div_cnt <= 16'd0;
cnt_full <= 1'b0;
end
else
if(div_cnt==16'd49999)begin
div_cnt <= 16'd0;
cnt_full <= 1'b1;
end
else begin
div_cnt <= div_cnt + 1'b1;
cnt_full <= 1'b0;
end
end
//状态组合判断
always@(posedge cnt_full or negedge rst)begin
if(!rst)begin
state <= CHECK_R1;
end
else begin
case(state)
CHECK_R1:
if(cnt_full)begin
state <= CHECK_R2;
end
else begin
state <= CHECK_R1;
end
CHECK_R2:
if(cnt_full)begin
state <= CHECK_R3;
end
else begin
state <= CHECK_R2;
end
CHECK_R3:
if(cnt_full)begin
state <= CHECK_R4;
end
else begin
state <= CHECK_R3;
end
CHECK_R4:
if(cnt_full)begin
state <= CHECK_R1;
end
else begin
state <= CHECK_R4;
end
default: begin
state <= state;
end
endcase
end
end
//状态机输出逻辑
always@(posedge clk or negedge rst)begin
if(!rst)begin
c_pin <= 4'b0000;
key_out <= 4'd0;
end
else begin
case(state)
CHECK_R1:begin
c_pin <= 4'b1000;
case(r_pin)
4'b1000:key_out <= 4'd0;
4'b0100:key_out <= 4'd1;
4'b0010:key_out <= 4'd2;
4'b0001:key_out <= 4'd3;
default:key_out <= key_out;
endcase
end
CHECK_R2:begin
c_pin <= 4'b0100;
case(r_pin)
4'b1000:key_out <= 4'd4;
4'b0100:key_out <= 4'd5;
4'b0010:key_out <= 4'd6;
4'b0001:key_out <= 4'd7;
default:key_out <= key_out;
endcase
end
CHECK_R3:begin
c_pin <= 4'b0010;
case(r_pin)
4'b1000:key_out <= 4'd8;
4'b0100:key_out <= 4'd9;
4'b0010:key_out <= 4'd10;
4'b0001:key_out <= 4'd11;
default:key_out <= key_out;
endcase
end
CHECK_R4:begin
c_pin <= 4'b0001;
case(r_pin)
4'b1000:key_out <= 4'd12;
4'b0100:key_out <= 4'd13;
4'b0010:key_out <= 4'd14;
4'b0001:key_out <= 4'd15;
default:key_out <= key_out;
endcase
end
default:begin
c_pin <= 4'b0000;
key_out <= 4'd0;
end
endcase
end
end
endmodule
4.check_mima模块
key3控制进入输入密码状态,检测到6次按下后自动检测密码是否正确。正确就回到IDLE,并输出一个mima_flag 一个clk的高电平。可以根据这个标志进行操作。错误就累加,累加到一定次进入WARNING,报警状态。
c
module check_mima(
input clk, // 时钟信号
input rst_n, // 异步复位信号,低有效
input key3, // 启动密码输入的按键
input [3:0] r_pin, // 键盘输入(数字键的按下信号)
input [3:0] key_out, // 键盘输出的具体数字
input [23:0] correct_password,
output wire [23:0] mima, // 24位密码存储寄存器
output reg mima_flag // 密码验证标志
);
// 定义状态机状态
parameter IDLE = 2'b00; // 初始状态,等待key3按下
parameter STORE = 2'b01; // 密码输入存储状态
parameter CHECK = 2'b10; // 密码校验状态
parameter WARNING = 2'b11; // 密码校验状态
reg [1:0] state;
reg [1:0] next_state;
reg [3:0] digit_count; // 用于记录输入密码的数字数量
reg [3:0] mima_1;
reg [3:0] mima_2;
reg [3:0] mima_3;
reg [3:0] mima_4;
reg [3:0] mima_5;
reg [3:0] mima_6;
reg [2:0] mima_error_count;
reg [3:0] blink_counter; // 用于计数闪烁次数
reg [15:0] blink_timer; // 用于生成 1 秒钟的闪烁周期
reg [15:0] error_timer; // 用于生成 1 秒钟的闪烁周期
reg led_warning;
// 初始密码,预设为 "123456"(24位)
// reg [23:0] correct_password = 24'h123456;
// 计时器,用于实现 1 秒钟的闪烁周期
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
blink_timer <= 0;
end else begin
if (state == WARNING) begin
if (blink_timer == 16'd20) // 假设时钟频率是 50MHz,每 1 秒
blink_timer <= 0;
else
blink_timer <= blink_timer + 1;
end else begin
blink_timer <= 0;
end
end
end
// 状态机逻辑
always @(posedge clk or negedge rst_n) begin
if (~rst_n)
state <= IDLE; // 异步复位时,状态机回到IDLE状态
else
state <= next_state; // 按时钟更新状态
end
// 下一个状态的逻辑
always @(posedge clk) begin
case(state)
IDLE: begin
if (key3) // 按下key3启动密码输入
next_state <= STORE;
else
next_state <= IDLE;
end
STORE: begin
if (digit_count == 6) // 密码输入6位后,进入校验状态
next_state <= CHECK;
else
next_state <= STORE;
end
CHECK: begin
if((mima_error_count==2) && (mima != correct_password))begin
next_state <= WARNING; // 校验完成后回到IDLE状态
end else begin
next_state <= IDLE;
end
end
WARNING: begin
if (blink_counter == 10) begin
next_state <= IDLE;
end
else begin
next_state <= WARNING;
end
end
default: next_state <= IDLE;
endcase
end
// 密码输入存储逻辑
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
mima_1<=4'd0;
mima_2<=4'd0;
mima_3<=4'd0;
mima_4<=4'd0;
mima_5<=4'd0;
mima_6<=4'd0;
digit_count <= 0; // 清空输入的位数
mima_flag <= 0; // 初始时密码校验标志为低
led_warning<=1'b0;
blink_counter<=0;
mima_error_count<=0;
end else begin
case(state)
IDLE: begin
mima_flag <= 0;
digit_count <= 0; // 清空输入的位数
led_warning<=1'b0;
blink_counter<=0;
mima_1<=4'd0;
mima_2<=4'd0;
mima_3<=4'd0;
mima_4<=4'd0;
mima_5<=4'd0;
mima_6<=4'd0;
end
STORE: begin
if (r_pin != 4'b0000 && digit_count < 6) begin
digit_count <= digit_count + 1;
end
case(digit_count)
6:begin
mima_6<=key_out;
end
1:begin
mima_1<=key_out;
end
2:begin
mima_2<=key_out;
end
3:begin
mima_3<=key_out;
end
4:begin
mima_4<=key_out;
end
5:begin
mima_5<=key_out;
end
default:begin
mima_1<=4'd0;
mima_2<=4'd0;
mima_3<=4'd0;
mima_4<=4'd0;
mima_5<=4'd0;
mima_6<=4'd0;
end
endcase
end
CHECK: begin
mima_1<=4'd0;
mima_2<=4'd0;
mima_3<=4'd0;
mima_4<=4'd0;
mima_5<=4'd0;
mima_6<=4'd0;
if (mima == correct_password) // 密码正确
mima_flag <= 1; // 密码验证通过,设置mima_flag为高
else if(mima_error_count<3)begin
mima_error_count<=mima_error_count+1;
mima_flag <= 0; // 密码验证失败,保持mima_flag为低
end
end
WARNING: begin
mima_error_count<=0;
if (blink_counter < 10) begin
if (blink_timer == 16'd0) begin
led_warning = ~led_warning; // 每秒反转一次 led
blink_counter = blink_counter + 1;
end
end
end
default: begin
mima_flag <= 0; // 在其他状态下,密码标志保持低
end
endcase
end
end
assign mima={mima_1,mima_2,mima_3,mima_4,mima_5,mima_6};
endmodule
5.change_mima模块
类似check_mima模块
c
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/12/07 15:23:36
// Design Name:
// Module Name: change_mima
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module change_mima(
input clk,
input rst_n,
input key4,
input [3:0] r_pin, // 键盘输入(数字键的按下信号)
input [3:0] key_out, // 键盘输出的具体数字
output reg led_change,
output wire [23:0] correct_password
);
parameter IDLE = 2'b00; // 初始状态,等待key3按下
parameter STORE = 2'b01; // 新密码存储状态
parameter CHANGE_OK = 2'b10; // 密码修改完毕状态
reg [3:0] blink_counter; // 用于计数闪烁次数
reg [15:0] blink_timer; // 用于生成 1 秒钟的闪烁周期
reg [1:0] state;
reg [1:0] next_state;
reg [3:0] digit_count; // 用于记录输入密码的数字数量
reg [3:0] mima_1;
reg [3:0] mima_2;
reg [3:0] mima_3;
reg [3:0] mima_4;
reg [3:0] mima_5;
reg [3:0] mima_6;
assign correct_password={mima_1,mima_2,mima_3,mima_4,mima_5,mima_6};
// 计时器,用于实现 1 秒钟的闪烁周期
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
blink_timer <= 0;
end else begin
if (state == CHANGE_OK) begin
if (blink_timer == 16'd100) // 假设时钟频率是 50MHz,每 1 秒
blink_timer <= 0;
else
blink_timer <= blink_timer + 1;
end else begin
blink_timer <= 0;
end
end
end
// 状态机逻辑
always @(posedge clk or negedge rst_n) begin
if (~rst_n)
state <= IDLE; // 异步复位时,状态机回到IDLE状态
else
state <= next_state; // 按时钟更新状态
end
// 下一个状态的逻辑
always @(posedge clk) begin
case(state)
IDLE: begin
if (key4) // 按下key3启动密码输入
next_state = STORE;
else
next_state = IDLE;
end
STORE: begin
if (digit_count == 6) // 密码输入6位后,进入校验状态
next_state <= CHANGE_OK;
else
next_state <= STORE;
end
CHANGE_OK: begin
if(blink_counter == 10)
next_state <= IDLE; // 校验完成后回到IDLE状态
else begin
next_state <= CHANGE_OK;
end
end
default: next_state <= IDLE;
endcase
end
// 密码输入存储逻辑
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
mima_1<=4'd1;
mima_2<=4'd2;
mima_3<=4'd3;
mima_4<=4'd4;
mima_5<=4'd5;
mima_6<=4'd6;
led_change<=1'b0;
blink_counter<=0;
digit_count <= 0; // 清空输入的位数
end else begin
case(state)
IDLE: begin
mima_1<=mima_1;
mima_2<=mima_2;
mima_3<=mima_3;
mima_4<=mima_4;
mima_5<=mima_5;
mima_6<=mima_6;
led_change<=1'b0;
digit_count <= 0; // 清空输入的位数
end
STORE: begin
if (r_pin != 4'b0000 && digit_count < 6) begin
digit_count <= digit_count + 1;
end
case(digit_count)
6:begin
mima_6<=key_out;
end
1:begin
mima_1<=key_out;
end
2:begin
mima_2<=key_out;
end
3:begin
mima_3<=key_out;
end
4:begin
mima_4<=key_out;
end
5:begin
mima_5<=key_out;
end
default:begin
mima_1<=mima_1;
mima_2<=mima_2;
mima_3<=mima_3;
mima_4<=mima_4;
mima_5<=mima_5;
mima_6<=mima_6;
end
endcase
end
CHANGE_OK: begin
if (blink_counter < 10) begin
if (blink_timer == 16'd0) begin
led_change<= ~led_change; // 每秒反转一次 led
blink_counter <= blink_counter + 1;
end
end else begin
blink_counter <= blink_counter;
end
end
default: begin
state<=IDLE;
end
endcase
end
end
endmodule
6.seg_ctrl模块
数码管显示模块
c
/**************************************功能介绍***********************************
Date : 2023年10月1日 11:54:18
Author : Yang.
Project : 密码锁
Require : 用verliog实现密码锁,且具有以下功能:
1、六位密码,且用数码管显示。
2、用按键键入每一位密码,可以加减。
3、密码正确时,led灯以300ms频率闪烁10s,且蜂鸣器播放音乐。
4、密码错误时,led灯以100ms频率闪烁10s,且蜂鸣器报警。
*********************************************************************************/
//---------<模块及端口声名>------------------------------------------------------
module seg_ctrl(
input clk ,
input rst_n ,
input [23:0] din ,//输入6位数码管显示数据,每位数码管占4位
input [5:0] point_n ,//输入小数点控制位
output reg [5:0] sel ,//输出位选
output reg [7:0] dig //输出段选
);
//---------<参数定义>---------------------------------------------------------
parameter TIME_1MS = 50_000;//1ms
//数码管显示字符编码
localparam NUM_0 = 7'b100_0000,//0
NUM_1 = 7'b111_1001,//1
NUM_2 = 7'b010_0100,//
NUM_3 = 7'b011_0000,//
NUM_4 = 7'b001_1001,//
NUM_5 = 7'b001_0010,//
NUM_6 = 7'b000_0010,//
NUM_7 = 7'b111_1000,//
NUM_8 = 7'b000_0000,//
NUM_9 = 7'b001_0000,//
A = 7'b000_1000,//
B = 7'b000_0011,//b
C = 7'b100_0110,//
OFF = 7'b111_1111,//全灭
CROSS = 7'b011_1111,//横杠
//D = 7'b010_0001,//d
//E = 7'b000_0110,//
F = 7'b000_1110;//
//---------<内部信号定义>-----------------------------------------------------
reg [15:0] cnt_1ms ;//1ms计数器(扫描间隔计数器)
wire add_cnt_1ms ;
wire end_cnt_1ms ;
reg [3:0] disp_data ;//每一位数码管显示的数值
reg point_n_r ;//每一位数码管显示的小数点
//****************************************************************
//--cnt_1ms
//****************************************************************
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_1ms <= 'd0;
end
else if(add_cnt_1ms)begin
if(end_cnt_1ms)begin
cnt_1ms <= 'd0;
end
else begin
cnt_1ms <= cnt_1ms + 1'b1;
end
end
end
assign add_cnt_1ms = 1'b1;//数码管一直亮
assign end_cnt_1ms = add_cnt_1ms && cnt_1ms == TIME_1MS - 1;
//****************************************************************
//--seg_sel
//****************************************************************
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sel <= 6'b111_110;//循环移位实现时,需要给位选赋初值
end
else if(end_cnt_1ms)begin
sel <= {sel[4:0],sel[5]};//循环左移
end
end
//****************************************************************
//--disp_data
//****************************************************************
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
disp_data <= 'd0;
point_n_r <= 1'b1;
end
else begin
case (sel)
6'b111_110 : begin disp_data <= din[3:0] ; point_n_r <= point_n[0]; end//第一位数码管显示的数值
6'b111_101 : begin disp_data <= din[7:4] ; point_n_r <= point_n[1]; end
6'b111_011 : begin disp_data <= din[11:8] ; point_n_r <= point_n[2]; end
6'b110_111 : begin disp_data <= din[15:12]; point_n_r <= point_n[3]; end
6'b101_111 : begin disp_data <= din[19:16]; point_n_r <= point_n[4]; end
6'b011_111 : begin disp_data <= din[23:20]; point_n_r <= point_n[5]; end
default: disp_data <= 'd0;
endcase
end
end
//****************************************************************
//--seg_dig
//****************************************************************
always @(*)begin
case (disp_data)
0 : dig = {point_n_r,NUM_0};
1 : dig = {point_n_r,NUM_1};
2 : dig = {point_n_r,NUM_2};
3 : dig = {point_n_r,NUM_3};
4 : dig = {point_n_r,NUM_4};
5 : dig = {point_n_r,NUM_5};
6 : dig = {point_n_r,NUM_6};
7 : dig = {point_n_r,NUM_7};
8 : dig = {point_n_r,NUM_8};
9 : dig = {point_n_r,NUM_9};
10 : dig = {point_n_r,A };
11 : dig = {point_n_r,B };
12 : dig = {point_n_r,C };
13 : dig = {point_n_r,CROSS};
14 : dig = {point_n_r,OFF };
15 : dig = {point_n_r,F };
default: dig = 8'hff;
endcase
end
endmodule
7.uart_top模块
c
//****************************************Copyright (c)***********************************//
//原子哥在线教学平台:www.yuanzige.com
//技术支持:http://www.openedv.com/forum.php
//淘宝店铺:https://zhengdianyuanzi.tmall.com
//关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2023-2033
//All rights reserved
//----------------------------------------------------------------------------------------
// File name: uart_loopback
// Created by: 正点原子
// Created date: 2023年2月16日14:20:02
// Version: V1.0
// Descriptions: 串口回环实验
//
//----------------------------------------------------------------------------------------
//****************************************************************************************//
module uart_top(
input sys_clk , //外部50MHz时钟
input sys_rst_n, //系外部复位信号,低有效
//UART端口
input uart_rxd , //UART接收端口
output uart_txd , //UART发送端口
output wire uart_tx_en, //UART接收完成信号
output wire uart_rx_done, //UART接收完成信号
output wire uart_tx_done, //UART接收完成信号
output wire [7:0] uart_tx_data, //UART接收数据
output wire [7:0] uart_rx_data //UART接收数据
);
//parameter define
parameter CLK_FREQ = 50000000; //定义系统时钟频率
parameter UART_BPS = 576000 ; //定义串口波特率
//wire define
//wire uart_rx_done; //UART接收完成信号
//wire [7:0] uart_rx_data; //UART接收数据
//*****************************************************
//** main code
//*****************************************************
//串口接收模块
uart_rx #(
.CLK_FREQ (CLK_FREQ),
.UART_BPS (UART_BPS)
)
u_uart_rx(
.clk (sys_clk ),
.rst_n (sys_rst_n ),
.uart_rxd (uart_rxd ),
.uart_rx_done (uart_rx_done),
.uart_rx_data (uart_rx_data)
);
//串口发送模块
uart_tx #(
.CLK_FREQ (CLK_FREQ),
.UART_BPS (UART_BPS)
)
u_uart_tx(
.clk (sys_clk ),
.rst_n (sys_rst_n ),
.uart_tx_en (uart_tx_en),
.uart_tx_data (uart_tx_data),
.uart_tx_done (uart_tx_done),
.uart_txd (uart_txd ),
.uart_tx_busy ( )
);
endmodule
//uart_rx//
//uart_rx//
//uart_rx//
c
//****************************************Copyright (c)***********************************//
//原子哥在线教学平台:www.yuanzige.com
//技术支持:http://www.openedv.com/forum.php
//淘宝店铺:https://zhengdianyuanzi.tmall.com
//关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2023-2033
//All rights reserved
//----------------------------------------------------------------------------------------
// File name: uart_rx
// Created by: 正点原子
// Created date: 2023年2月16日14:20:02
// Version: V1.0
// Descriptions: UART串口接收模块
//
//----------------------------------------------------------------------------------------
//****************************************************************************************//
module uart_rx(
input clk , //系统时钟
input rst_n , //系统复位,低有效
input uart_rxd , //UART接收端口
output reg uart_rx_done, //UART接收完成信号
output reg [7:0] uart_rx_data //UART接收到的数据
);
//parameter define
parameter CLK_FREQ = 50000000; //系统时钟频率
parameter UART_BPS = 576000 ; //串口波特率
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //为得到指定波特率,对系统时钟计数BPS_CNT次
//reg define
reg uart_rxd_d0;
reg uart_rxd_d1;
reg uart_rxd_d2;
reg rx_flag ; //接收过程标志信号
reg [3:0 ] rx_cnt ; //接收数据计数器
reg [15:0] baud_cnt ; //波特率计数器
reg [7:0 ] rx_data_t ; //接收数据寄存器
//wire define
wire start_en;
//*****************************************************
//** main code
//*****************************************************
//捕获接收端口下降沿(起始位),得到一个时钟周期的脉冲信号
assign start_en = uart_rxd_d2 & (~uart_rxd_d1) & (~rx_flag);
//针对异步信号的同步处理
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
uart_rxd_d0 <= 1'b0;
uart_rxd_d1 <= 1'b0;
uart_rxd_d2 <= 1'b0;
end
else begin
uart_rxd_d0 <= uart_rxd;
uart_rxd_d1 <= uart_rxd_d0;
uart_rxd_d2 <= uart_rxd_d1;
end
end
//给接收标志赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rx_flag <= 1'b0;
else if(start_en) //检测到起始位
rx_flag <= 1'b1; //接收过程中,标志信号rx_flag拉高
//在停止位一半的时候,即接收过程结束,标志信号rx_flag拉低
else if((rx_cnt == 4'd9) && (baud_cnt == BAUD_CNT_MAX/2 - 1'b1))
rx_flag <= 1'b0;
else
rx_flag <= rx_flag;
end
//波特率的计数器赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
baud_cnt <= 16'd0;
else if(rx_flag) begin //处于接收过程时,波特率计数器(baud_cnt)进行循环计数
if(baud_cnt < BAUD_CNT_MAX - 1'b1)
baud_cnt <= baud_cnt + 16'b1;
else
baud_cnt <= 16'd0; //计数达到一个波特率周期后清零
end
else
baud_cnt <= 16'd0; //接收过程结束时计数器清零
end
//对接收数据计数器(rx_cnt)进行赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rx_cnt <= 4'd0;
else if(rx_flag) begin //处于接收过程时rx_cnt才进行计数
if(baud_cnt == BAUD_CNT_MAX - 1'b1) //当波特率计数器计数到一个波特率周期时
rx_cnt <= rx_cnt + 1'b1; //接收数据计数器加1
else
rx_cnt <= rx_cnt;
end
else
rx_cnt <= 4'd0; //接收过程结束时计数器清零
end
//根据rx_cnt来寄存rxd端口的数据
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rx_data_t <= 8'b0;
else if(rx_flag) begin //系统处于接收过程时
if(baud_cnt == BAUD_CNT_MAX/2 - 1'b1) begin //判断baud_cnt是否计数到数据位的中间
case(rx_cnt)
4'd1 : rx_data_t[0] <= uart_rxd_d2; //寄存数据的最低位
4'd2 : rx_data_t[1] <= uart_rxd_d2;
4'd3 : rx_data_t[2] <= uart_rxd_d2;
4'd4 : rx_data_t[3] <= uart_rxd_d2;
4'd5 : rx_data_t[4] <= uart_rxd_d2;
4'd6 : rx_data_t[5] <= uart_rxd_d2;
4'd7 : rx_data_t[6] <= uart_rxd_d2;
4'd8 : rx_data_t[7] <= uart_rxd_d2; //寄存数据的高低位
default : ;
endcase
end
else
rx_data_t <= rx_data_t;
end
else
rx_data_t <= 8'b0;
end
//给接收完成信号和接收到的数据赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
uart_rx_done <= 1'b0;
uart_rx_data <= 8'b0;
end
//当接收数据计数器计数到停止位,且baud_cnt计数到停止位的中间时
else if(rx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX/2 - 1'b1) begin
uart_rx_done <= 1'b1 ; //拉高接收完成信号
uart_rx_data <= rx_data_t; //并对UART接收到的数据进行赋值
end
else begin
uart_rx_done <= 1'b0;
uart_rx_data <= uart_rx_data;
end
end
endmodule
//uart_tx//
//uart_tx//
//uart_tx//
c
//****************************************Copyright (c)***********************************//
//原子哥在线教学平台:www.yuanzige.com
//技术支持:http://www.openedv.com/forum.php
//淘宝店铺:https://zhengdianyuanzi.tmall.com
//关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2023-2033
//All rights reserved
//----------------------------------------------------------------------------------------
// File name: uart_tx
// Created by: 正点原子
// Created date: 2023年2月16日14:20:02
// Version: V1.0
// Descriptions: UART串口发送模块
//
//----------------------------------------------------------------------------------------
//****************************************************************************************//
module uart_tx(
input clk , //系统时钟
input rst_n , //系统复位,低有效
input uart_tx_en , //UART的发送使能
input [7:0] uart_tx_data, //UART要发送的数据
output reg uart_txd , //UART发送端口
output reg [3:0] tx_cnt , //发送数据计数器
output reg [15:0] baud_cnt , //波特率计数器
output reg uart_tx_done,
output reg uart_tx_busy //发送忙状态信号
);
//parameter define
parameter CLK_FREQ = 50000000; //系统时钟频率
parameter UART_BPS = 576000 ; //串口波特率
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //为得到指定波特率,对系统时钟计数BPS_CNT次
//reg define
reg [7:0] tx_data_t; //发送数据寄存器
//波特率的计数器赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
uart_tx_done<=1'b0;
else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - 1) begin
uart_tx_done<=1'b1;
end
else
uart_tx_done<=1'b0; //发送过程结束时计数器清零
end
//*****************************************************
//** main code
//*****************************************************
//当uart_tx_en为高时,寄存输入的并行数据,并拉高BUSY信号
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
tx_data_t <= 8'b0;
uart_tx_busy <= 1'b0;
end
//发送使能时,寄存要发送的数据,并拉高BUSY信号
else if(uart_tx_en) begin
tx_data_t <= uart_tx_data;
uart_tx_busy <= 1'b1;
end
//当计数到停止位结束时,停止发送过程
else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - 1) begin
tx_data_t <= 8'b0; //清空发送数据寄存器
uart_tx_busy <= 1'b0; //并拉低BUSY信号
end
else begin
tx_data_t <= tx_data_t;
uart_tx_busy <= uart_tx_busy;
end
end
//波特率的计数器赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
baud_cnt <= 16'd0;
else if(uart_tx_en)
baud_cnt <= 16'd0;
//当处于发送过程时,波特率计数器(baud_cnt)进行循环计数
else if(uart_tx_busy) begin
if(baud_cnt < BAUD_CNT_MAX - 1'b1)
baud_cnt <= baud_cnt + 16'b1;
else
baud_cnt <= 16'd0; //计数达到一个波特率周期后清零
end
else
baud_cnt <= 16'd0; //发送过程结束时计数器清零
end
//tx_cnt进行赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
tx_cnt <= 4'd0;
else if(uart_tx_en)
tx_cnt <= 16'd0;
else if(uart_tx_busy) begin //处于发送过程时tx_cnt才进行计数
if(baud_cnt == BAUD_CNT_MAX - 1'b1) //当波特率计数器计数到一个波特率周期时
tx_cnt <= tx_cnt + 1'b1; //发送数据计数器加1
else
tx_cnt <= tx_cnt;
end
else
tx_cnt <= 4'd0; //发送过程结束时计数器清零
end
//根据tx_cnt来给uart发送端口赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
uart_txd <= 1'b1;
else if(uart_tx_busy) begin
case(tx_cnt)
4'd0 : uart_txd <= 1'b0 ; //起始位
4'd1 : uart_txd <= tx_data_t[0]; //数据位最低位
4'd2 : uart_txd <= tx_data_t[1];
4'd3 : uart_txd <= tx_data_t[2];
4'd4 : uart_txd <= tx_data_t[3];
4'd5 : uart_txd <= tx_data_t[4];
4'd6 : uart_txd <= tx_data_t[5];
4'd7 : uart_txd <= tx_data_t[6];
4'd8 : uart_txd <= tx_data_t[7]; //数据位最高位
4'd9 : uart_txd <= 1'b1 ; //停止位
default : uart_txd <= 1'b1;
endcase
end
else
uart_txd <= 1'b1; //空闲时发送端口为高电平
end
endmodule
8.key_debounce模块
仿真用不到,按键消抖模块
c
//
// //
// //
// Author: lhj //
// //
// ALINX(shanghai) Technology Co.,Ltd //
// heijin //
// WEB: http://www.alinx.cn/ //
// BBS: http://www.heijin.org/ //
// //
//
// //
// Copyright (c) 2017,ALINX(shanghai) Technology Co.,Ltd //
// All rights reserved //
// //
// This source file may be used and distributed without restriction provided //
// that this copyright statement is not removed from the file and that any //
// derivative work contains the original copyright notice and the associated //
// disclaimer. //
// //
//
//===============================================================================
// Revision History:
// Date By Revision Change Description
//-------------------------------------------------------------------------------
// 2018/01/03 lhj 1.0 Original
//*******************************************************************************/
module key_debounce
(
input sys_clk,
input rst_n,
input key,
output wire button_negedge //Key falling edge
);
wire [3:0] led;
ax_debounce ax_debounce_m0
(
.clk (sys_clk ),
.rst (~rst_n ),
.button_in (key ),
.button_posedge ( ),
.button_negedge (button_negedge),
.button_out ( )
);
wire[3:0] count;
counter count_m0
(
.clk (sys_clk ),
.rst_n (rst_n ),
.en (button_negedge),
.clr (1'b0 ),
.data (count )
);
assign led = ~count;
endmodule
9.TOP模块
c
//****************************************Copyright (c)***********************************//
//原子哥在线教学平台:www.yuanzige.com
//技术支持:http://www.openedv.com/forum.php
//淘宝店铺:https://zhengdianyuanzi.tmall.com
//关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2023-2033
//All rights reserved
//----------------------------------------------------------------------------------------
// File name: uart_loopback
// Created by: 正点原子
// Created date: 2023年2月16日14:20:02
// Version: V1.0
// Descriptions: 串口回环实验
//
//----------------------------------------------------------------------------------------
//****************************************************************************************//
module top(
input sys_clk , //外部50MHz时钟
input rst_n, //系外部复位信号,低有效
input WAK,
input key1,
input key2,
input key3,
input key4,
input key5,
input [3:0] r_pin,
output wire [4:0] led,
output wire [3:0] c_pin,
output wire [5:0] sel,
output wire [7:0] dig,
//UART端口
input uart_rxd , //UART接收端口
output uart_txd //UART发送端口
);
wire button1_negedge;
wire uart_tx_en;
wire uart_rx_done;
wire uart_tx_done;
wire [23:0] correct_password;
wire mima_flag;//密码正确标志
wire [23:0] mima; //密码
wire [23:0] din; //
wire [7:0] uart_tx_data;
wire [7:0] uart_rx_data;
wire [3:0] key_out;
wire hand_flag;
wire check_hand_flag;
wire led1;
wire led2;
wire led3;
wire led4;
wire led5;
wire led6;
assign led={led1,led2,led3,led4,led5};
four_four_key u_four_four_key(
.clk(sys_clk),//时钟
.rst(rst_n),//复位
.c_pin(c_pin),//行引脚
.r_pin(r_pin),//列引脚
.key_out(key_out)//按键编号输出
);
check_mima u_check_mima(
.clk(sys_clk), // 时钟信号
.rst_n(rst_n), // 异步复位信号,低有效
.key3(key3), // 启动密码输入的按键
.r_pin(r_pin), // 键盘输入(数字键的按下信号)
.key_out(key_out), // 键盘输出的具体数字
.correct_password(correct_password),
.mima(mima), // 24位密码存储寄存器
.mima_flag(mima_flag) // 密码验证标志
);
change_mima u_change_mima(
.clk(sys_clk), // 时钟信号
.rst_n(rst_n), // 异步复位信号,低有效
.key4(key4), // 启动密码输入的按键
.r_pin(r_pin), // 键盘输入(数字键的按下信号)
.key_out(key_out), // 键盘输出的具体数字
.led_change(led6),
.correct_password(correct_password)
);
check_hand u_check_hand(
.clk(sys_clk),
.rst_n(rst_n),
.hand_flag(hand_flag),
.check_hand_flag(check_hand_flag),
.led_hand_right(led4),
.led_hand_error(led5)
);
seg_ctrl u_seg_ctrl(
.clk(sys_clk) ,
.rst_n(rst_n) ,
.din(mima) ,//输入6位数码管显示数据,每位数码管占4位
.point_n(6'b111111) ,//输入小数点控制位
.sel(sel) ,//输出位选
.dig(dig) //输出段选
);
AS608_data u_AS608_data(
.clk(sys_clk),
.rst_n(rst_n),
.WAK(WAK),
.key1(key1),
.key2(key2),
.key3(key3),
.key4(key4),
.key5(key5),
.led_hand1(led1),
.led_hand2(led2),
.led_hand3(led3),
.hand_flag_r1(hand_flag),
.check_hand_flag(check_hand_flag),
.uart_tx_done(uart_tx_done),
.uart_rx_data(uart_rx_data),
.uart_rx_done(uart_rx_done),
.uart_tx_en(uart_tx_en),
.uart_tx_data(uart_tx_data)
);
key_debounce u_key_debounce
(
.sys_clk(sys_clk),
.rst_n(rst_n),
.key(key1),
.button_negedge(button1_negedge) //Key falling edgz
);
uart_top u_uart_top(
.sys_clk(sys_clk) , //外部50MHz时钟
.sys_rst_n(rst_n), //系外部复位信号,低有效
.uart_rx_done (uart_rx_done),
.uart_rx_data (uart_rx_data),
.uart_tx_en (uart_tx_en),
.uart_tx_data (uart_tx_data),
.uart_tx_done (uart_tx_done),
.uart_rxd(uart_rxd) , //UART接收端口
.uart_txd(uart_txd) //UART发送端口
);
endmodule
9.仿真tb文件
c
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/12/02 20:16:35
// Design Name:
// Module Name: tb_top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_top();
reg sys_clk;
reg rst_n;
reg WAK;
reg key1;
reg key2;
reg key3;
reg key4;
reg key5;
reg uart_rxd;
reg [3:0] r_pin;
wire [3:0] c_pin;
wire [5:0] sel;
wire [7:0] dig;
reg flag;
wire uart_txd;
parameter CLK_FREQ = 50000000; //定义系统时钟频率
parameter UART_BPS = 115200 ; //定义串口波特率
top u_top(
.sys_clk(sys_clk),
.rst_n(rst_n),
.WAK(WAK),
.key1(key1),
.key2(key2),
.key3(key3),
.key4(key4),
.key5(key5),
.c_pin(c_pin),
.r_pin(r_pin),
.sel(sel),//输出位选
.dig(dig),
.uart_rxd(uart_rxd) , //UART接收端口
.uart_txd(uart_txd) //UART发送端口
);
always #10 sys_clk=~sys_clk;
initial begin
sys_clk=0;
rst_n=0;
WAK=1;
key1=0;
key2=0;
key3=0;
key4=0;
key5=0;
flag=0;
r_pin=4'b0000;
uart_rxd=1;
#100
rst_n=1;
#100
key1=1;
#120
key1=0;
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
///22222222222222222222222222222222222222222222222222222222222222222ak
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
///22222222222222222222222222222222222222222222222222222222222222222ak
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
///22222222222222222222222222222222222222222222222222222222222222222ak
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
///22222222222222222222222222222222222222222222222222222222222222222ak
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
///22222222222222222222222222222222222222222222222222222222222222222ak
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
key1=1;
#20
key1=0;
///22222222222222222222222222222222222222222222222222222222222222222ak
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#100
key2=1;
#20
key2=0;
///22222222222222222222222222222222222222222222222222222222222222222ak
#250000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
///22222222222222222222222222222222222222222222222222222222222222222ak
#300000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=0;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1736
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1000
uart_rxd=0;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
#1720
uart_rxd=1;
key3=1;///mima
#20
key3=0;
#100
r_pin=4'b0100; //1
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//2
#20
r_pin=4'b0000;
#100
r_pin=4'b0001;//3
#20
r_pin=4'b0000;
#500000
r_pin=4'b1000;//4
#20
r_pin=4'b0000;
#100
r_pin=4'b0100;//5
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//6
#20
r_pin=4'b0000;
#1000
key3=1;///mima
#20
key3=0;
#100
r_pin=4'b0100; //1
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//2
#20
r_pin=4'b0000;
#100
r_pin=4'b0001;//3
#20
r_pin=4'b0000;
#500000
r_pin=4'b1000;//4
#20
r_pin=4'b0000;
#100
r_pin=4'b0100;//5
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//6
#20
r_pin=4'b0000;
#1000
key3=1;///mima
#20
key3=0;
#100
r_pin=4'b0100; //1
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//2
#20
r_pin=4'b0000;
#100
r_pin=4'b0001;//3
#20
r_pin=4'b0000;
#500000
r_pin=4'b1000;//4
#20
r_pin=4'b0000;
#100
r_pin=4'b0100;//5
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//6
#20
r_pin=4'b0000;
#1000
key3=1;///mima
#20
key3=0;
#1000
r_pin=4'b1000;//4
#20
r_pin=4'b0000;
#100
r_pin=4'b0100;//5
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//6
#20
r_pin=4'b0000;
#1000
r_pin=4'b1000;//4
#20
r_pin=4'b0000;
#100
r_pin=4'b0100;//5
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//6
#20
r_pin=4'b0000;
#1000
key4=1;
#20
key4=0;
#1000
#100
r_pin=4'b0100; //1
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//2
#20
r_pin=4'b0000;
#100
r_pin=4'b0001;//3
#20
r_pin=4'b0000;
#500000
r_pin=4'b1000;//4
#20
r_pin=4'b0000;
#100
r_pin=4'b0100;//5
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//6
#20
r_pin=4'b0000;
#1000
r_pin=4'b1000;//4
#20
r_pin=4'b0000;
#100
r_pin=4'b0100;//5
#20
r_pin=4'b0000;
#100
r_pin=4'b0010;//6
#20
r_pin=4'b0000;
end
//1736
endmodule
这里接受的数据,没有按照手册来,只是将第10个数据设置为00,来表示通讯正确。
总结
其实就是围绕UART和状态机展开的逻辑编写,部分常见代码直接参考了正点原子、野火、等等案例,部分简单功能使用了chatgpt进行描述生成。实现难度并不大,就是涉及的模块较多,不过好好利用仿真结果能够差不多。代码有很多不足之处,有问题欢迎批评指正。