基于FPGA的智能电子密码指纹锁
- 一、功能描述
- 硬件资源需求
- 二、整体框架
- 知识准备
- AS608指纹模块
- 4*4数字键盘模块
- 三、Verilog代码实现以及仿真验证
- 1.AS608_data模块
- 2.check_hand模块
- 3.four_four_key模块
- 4.check_mima模块
- 5.change_mima模块
- 6.seg_ctrl模块
- 7.uart_top模块
- 8.key_debounce模块
- 9.TOP模块
- 9.仿真tb文件
- 总结
一、功能描述
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模块
实现思想:状态机
一路顺利就是这么个流程,不顺利的话就回到上个可以重新开始的流程。
`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 03unsuccessreg [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 16btyereg [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) beginif(!rst_n)beginhand_flag_r1<=1'b0;hand_flag_r<=1'b0;end else beginhand_flag_r1<=hand_flag;hand_flag_r<=hand_flag_r1;endend//各个状态return_dataalways @(posedge clk or negedge rst_n) beginif(!rst_n) beginuart_tx_data <= 8'd0;endelse if((state==GET_HAND1 || state==GET_HAND2) && tx_count<6'd12 ) beginuart_tx_data <= cmd_state[95 - tx_count *8 -:8];endelse if((state==FIND_HAND) && tx_count<6'd17 ) beginuart_tx_data <= cmd_find[135 - tx_count *8 -:8];endelse if((state==COMPARE_FEATURE) && tx_count<6'd12 ) beginuart_tx_data <= cmd_compare[95 - tx_count *8 -:8];endelse if((state==SAVE_FEATURE) && tx_count<6'd12 ) beginuart_tx_data <= cmd_save[95 - tx_count *8 -:8];endelse if((state==SEND_FEATURE) && tx_count<6'd15 ) beginuart_tx_data <= cmd_send[119 - tx_count *8 -:8];endelse if((state==MAKE_FEATURE1) && tx_count<6'd13 ) beginuart_tx_data <= cmd_make1[103 - tx_count *8 -:8];endelse if((state==MAKE_FEATURE2) && tx_count<6'd13 ) beginuart_tx_data <= cmd_make2[103 - tx_count *8 -:8];endelse beginuart_tx_data <= uart_tx_data;end
end//各个状态return_flagalways @(posedge clk or negedge rst_n) beginif(!rst_n) beginfind_flag <= 1'b0;endelse if(key2==1'b1)beginfind_flag <= ~find_flag;endelse beginfind_flag <= find_flag;endend//各个状态return_flagalways @(posedge clk or negedge rst_n) beginif(!rst_n) beginreturn_flag <= 1'b0;endelse if((state==WAK_HAND1 ||state==WAK_HAND2) && return_data==8'h00&& rx_count==11 && uart_rx_done==1'b1) beginreturn_flag <= 1'b1;endelse 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) beginreturn_flag <= 1'b1;endelse if((state==WAK_FIND) && return_data==8'h00 && rx_count==15 && uart_rx_done==1'b1) beginreturn_flag <= 1'b1;endelse beginreturn_flag <= 1'b0;end
end//各个状态return_dataalways @(posedge clk or negedge rst_n) beginif(!rst_n) beginreturn_data <= 8'b0;endelse if((state==WAK_HAND1 ||state==WAK_HAND2) && rx_count==10 ) beginreturn_data <= uart_rx_data;endelse if((state==WAK_FEATURE1 ||state==WAK_FEATURE2 || state== WAK_COMPARE || state==WAK_SAVE || state==WAK_FIND) && rx_count==10 ) beginreturn_data <= uart_rx_data;endelse beginreturn_data <= return_data;end
end//各个状态data_tx_enalways @(posedge clk or negedge rst_n) beginif(!rst_n) beginuart_tx_en_temp <= 1'b0;uart_tx_en <= uart_tx_en_temp;endelse if((state==GET_HAND1 || state==GET_HAND2 || state==COMPARE_FEATURE || state==SAVE_FEATURE) && tx_en_count==1) beginuart_tx_en_temp <= 1'b1;uart_tx_en <= uart_tx_en_temp;endelse if((state==MAKE_FEATURE1 || state==MAKE_FEATURE2 || state==SEND_FEATURE || state==FIND_HAND ) && tx_en_count==1) beginuart_tx_en_temp <= 1'b1;uart_tx_en <= uart_tx_en_temp;endelse if((state==GET_HAND1 || state==GET_HAND2 || state==COMPARE_FEATURE || state==SAVE_FEATURE) && tx_count<6'd11 && uart_tx_done==1)beginuart_tx_en_temp <= 1'b1;uart_tx_en <= uart_tx_en_temp;endelse if((state==MAKE_FEATURE1 || state==MAKE_FEATURE2) && tx_count<6'd12 && uart_tx_done==1)beginuart_tx_en_temp <= 1'b1;uart_tx_en <= uart_tx_en_temp;endelse if((state==SEND_FEATURE) && tx_count<6'd14 && uart_tx_done==1)beginuart_tx_en_temp <= 1'b1;uart_tx_en <= uart_tx_en_temp;endelse if((state==FIND_HAND) && tx_count<6'd16 && uart_tx_done==1)beginuart_tx_en_temp <= 1'b1;uart_tx_en <= uart_tx_en_temp;endelse beginuart_tx_en_temp <= 1'b0;uart_tx_en <= uart_tx_en_temp;end
end//各个状态rx_countalways @(posedge clk or negedge rst_n) beginif(!rst_n) beginrx_count <= 6'd0;endelse if((state==WAK_HAND1 ||state==WAK_HAND2 || state==WAK_FEATURE1 ||state==WAK_FEATURE2 || state== WAK_COMPARE || state==WAK_SAVE || state==WAK_SEND) ) beginif(uart_rx_done==1'd1)rx_count <= rx_count+1'b1;else if(rx_count==6'd12) beginrx_count <= 6'b0;endelse beginrx_count <= rx_count;endendelse if((state==WAK_FIND) ) beginif(uart_rx_done==1'd1)rx_count <= rx_count+1'b1;else if(rx_count==6'd16) beginrx_count <= 6'b0;endelse beginrx_count <= rx_count;endend
end//各个状态tx_countalways @(posedge clk or negedge rst_n) beginif(!rst_n) begintx_count <= 6'd0;endelse if((state==GET_HAND1 || state==GET_HAND2 || state==COMPARE_FEATURE || state==SAVE_FEATURE) ) beginif(uart_tx_done==1'd1)tx_count <= tx_count+1'b1;else if(tx_count==6'd12) begintx_count <= 6'b0;endelse begintx_count <= tx_count;endendelse if((state==MAKE_FEATURE1 || state==MAKE_FEATURE2) ) beginif(uart_tx_done==1'd1)tx_count <= tx_count+1'b1;else if(tx_count==6'd13) begintx_count <= 6'b0;endelse begintx_count <= tx_count;endendelse if((state==SEND_FEATURE) ) beginif(uart_tx_done==1'd1)tx_count <= tx_count+1'b1;else if(tx_count==6'd15) begintx_count <= 6'b0;endelse begintx_count <= tx_count;endendelse if((state==FIND_HAND) ) beginif(uart_tx_done==1'd1)tx_count <= tx_count+1'b1;else if(tx_count==6'd17) begintx_count <= 6'b0;endelse begintx_count <= tx_count;endend
end//tx_en timealways @(posedge clk or negedge rst_n) beginif(!rst_n) begintx_en_count <= 2'b0;endelse 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) begintx_en_count <=tx_en_count+ 2'd1;endelse 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) begintx_en_count <= 2'd3;endelse 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))begintx_en_count <= 2'd0;endelse begintx_en_count <= tx_en_count;end
end//state go always @(posedge clk or negedge rst_n) beginif(!rst_n) beginstate <= 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;endelse begincase(state)IDLE:beginblink_counter <= 0;hand_flag<=1'b0;check_hand_flag<=1'b0;if(key1==1'b1 && WAK==1'b1)beginstate <= GET_HAND1;endelse beginstate <= IDLE;endendGET_HAND1:beginif(tx_count==6'd12)beginstate <= WAK_HAND1;endelse beginstate <= GET_HAND1;endendWAK_HAND1:beginif(rx_count==6'd12 && return_flag==1'b1)beginstate <= MAKE_FEATURE1;endelse if(rx_count==6'd12 && return_flag==1'b0)beginstate <= IDLE;endelse beginstate <= WAK_HAND1;endendHAND1_LED: beginif (blink_counter < 2) beginif (blink_timer == 16'd0) beginled_hand1 = ~led_hand1; // 每秒反转一次 ledblink_counter = blink_counter + 1;endend else beginstate = MAKE_FEATURE1; // 完成 10 次闪烁后返回 IDLE 状态endendMAKE_FEATURE1:beginif(tx_count==6'd13)beginstate <= WAK_FEATURE1;endelse beginstate <= MAKE_FEATURE1;endendWAK_FEATURE1:beginif(find_flag==1'b0) beginif(rx_count==6'd12 && return_flag==1'b1)beginstate <= GET_HAND2;endelse if(rx_count==6'd12 && return_flag==1'b0)beginstate <= IDLE;endelse beginstate <= WAK_FEATURE1;endendelse beginif(rx_count==6'd12 && return_flag==1'b1)beginstate <= FIND_HAND;endelse if(rx_count==6'd12 && return_flag==1'b0)beginstate <= IDLE;endelse beginstate <= WAK_FEATURE1;endendendGET_HAND2:beginblink_counter <= 0;if(tx_count==6'd12)beginstate <= WAK_HAND2;endelse beginstate <= GET_HAND2;endendWAK_HAND2:beginif(rx_count==6'd12 && return_flag==1'b1)beginstate <= MAKE_FEATURE2;endelse if(rx_count==6'd12 && return_flag==1'b0)beginstate <= GET_HAND2;endelse beginstate <= WAK_HAND2;endendHAND2_LED: beginif (blink_counter < 2) beginif (blink_timer == 16'd0) beginled_hand2 = ~led_hand2; // 每秒反转一次 ledblink_counter = blink_counter + 1;endend else beginstate = MAKE_FEATURE2; // 完成 10 次闪烁后返回 IDLE 状态endendMAKE_FEATURE2:beginif(tx_count==6'd13)beginstate <= WAK_FEATURE2;endelse beginstate <= MAKE_FEATURE2;endendWAK_FEATURE2:beginif(rx_count==6'd12 && return_flag==1'b1)beginstate <= COMPARE_FEATURE;endelse if(rx_count==6'd12 && return_flag==1'b0)beginstate <= IDLE;endelse beginstate <= WAK_FEATURE2;endendCOMPARE_FEATURE:beginif(tx_count==6'd12)beginstate <= WAK_COMPARE;endelse beginstate <= COMPARE_FEATURE;endendWAK_COMPARE:beginif(rx_count==6'd12 && return_flag==1'b1)beginstate <= SAVE_FEATURE;endelse if(rx_count==6'd12 && return_flag==1'b0)beginstate <= IDLE;endelse beginstate <= WAK_COMPARE;endendSAVE_FEATURE:beginif(tx_count==6'd12)beginstate <= WAK_SAVE;endelse beginstate <= SAVE_FEATURE;endendWAK_SAVE:beginif(rx_count==6'd12 && return_flag==1'b1)beginstate <= SEND_FEATURE;endelse if(rx_count==6'd12 && return_flag==1'b0)beginstate <= IDLE;endelse beginstate <= WAK_SAVE;endendSEND_FEATURE:beginif(tx_count==6'd15)beginstate <= WAK_SEND;endelse beginstate <= SEND_FEATURE;endendWAK_SEND:beginif(rx_count==6'd12 && return_flag==1'b1)beginstate <= IDLE;endelse if(rx_count==6'd12 && return_flag==1'b0)beginstate <= IDLE;endelse beginstate <= WAK_SEND;endendSAVE_LED: beginif (blink_counter < 2) beginif (blink_timer == 16'd0) beginled_hand3 = ~led_hand3; // 每秒反转一次 ledblink_counter = blink_counter + 1;endend else beginstate = IDLE; // 完成 10 次闪烁后返回 IDLE 状态endendFIND_HAND:beginif(tx_count==6'd17)beginstate <= WAK_FIND;endelse beginstate <= FIND_HAND;endendWAK_FIND:beginif(rx_count==6'd16 && return_flag==1'b1)beginstate <= IDLE;check_hand_flag<=1'b1;hand_flag<=1'b1;endelse if(rx_count==6'd16 && return_flag==1'b0)beginstate <= IDLE;check_hand_flag<=1'b1;hand_flag<=1'b0;endelse beginstate <= WAK_FIND;endenddefault:state <= IDLE;endcaseend
end
// 计时器,用于实现 1 秒钟的闪烁周期
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginblink_timer <= 0;end else beginif (state == HAND2_LED ||state == HAND1_LED ||state == SAVE_LED) beginif (blink_timer == 16'd49999) // 假设时钟频率是 50MHz,每 1 秒blink_timer <= 0;elseblink_timer <= blink_timer + 1;end else beginblink_timer <= 0;endend
endendmodule
2.check_hand模块
通过check_hand_flag控制进入检验CHECK状态,通过hand_flag确定指纹验证是否正确。正确就led_hand_right闪,错误就led_hand_error。这两个标志是通过AS608模块传出来的。
代码如下(示例):
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) beginif (!rst_n) beginblink_timer <= 0;end else beginif (state == BLINK) beginif (blink_timer == 16'd49999) // 假设时钟频率是 50MHz,每 1 秒blink_timer <= 0;elseblink_timer <= blink_timer + 1;end else beginblink_timer <= 0;endend
end// 错误状态计时器(10秒)
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginerror_timer <= 0;end else if (state == ERROR) beginif (error_timer == 16'd49999) // 假设时钟频率是 50MHz,10秒error_timer <= 0; // 超过 10 秒后,计时器重置elseerror_timer <= error_timer + 1;end else beginerror_timer <= 0; // 不是错误状态时,计时器清零end
end// 状态转移与输出逻辑
always @(posedge clk or negedge rst_n) beginif(!rst_n)beginstate <=IDLE;led_hand_right <= 0;led_hand_error <=0;endelse begincase(state)IDLE: beginif (check_hand_flag) beginstate <=CHECK; // 如果检测标志位为1,进入检测状态endelse beginstate <=IDLE;endendCHECK: beginif (hand_flag) beginstate <= BLINK; // 如果手势正确,进入闪烁状态end else beginstate <= ERROR; // 如果手势错误,进入错误状态endendBLINK: beginif (blink_counter < 10) beginif (blink_timer == 16'd0) beginled_hand_right = ~led_hand_right; // 每秒反转一次 ledblink_counter = blink_counter + 1;endend else beginstate = IDLE; // 完成 10 次闪烁后返回 IDLE 状态endendERROR: beginif (blink_counter < 10) beginif (error_timer == 16'd0) beginled_hand_error <= ~led_hand_error; // 错误时,led_hand_error 10次blink_counter <= blink_counter + 1;endend else beginstate <= IDLE; // 完成 10 次闪烁后返回 IDLE 状态endendendcaseend
end// 控制闪烁次数
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginblink_counter <= 0;end else if (state == IDLE) beginblink_counter <= 0; // 重置闪烁计数器end
endendmodule
3.four_four_key模块
矩阵按键模块,通过给予不同行高电平,然后检测列状态,得出按键的状态。
`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;//检测R1localparam CHECK_R2=3'b001;//检测R2localparam CHECK_R3=3'b011;//检测R3localparam CHECK_R4=3'b010;//检测R4always @(posedge clk or negedge rst)beginif(!rst) beginstate_r <= 3'b0;endelse beginstate_r <= state;endendassign clear_flag= (state_r==state)?1:0;always @(posedge clk or negedge rst)beginif(!rst) beginkey_out_r <= 4'b0;endelse beginkey_out_r <= key_out;endend//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//此处设计每次拉高一行时间为1msif(!rst)begindiv_cnt <= 16'd0;cnt_full <= 1'b0;endelseif(div_cnt==16'd49999)begindiv_cnt <= 16'd0;cnt_full <= 1'b1;endelse begindiv_cnt <= div_cnt + 1'b1;cnt_full <= 1'b0;endend//状态组合判断always@(posedge cnt_full or negedge rst)beginif(!rst)beginstate <= CHECK_R1;endelse begincase(state)CHECK_R1:if(cnt_full)beginstate <= CHECK_R2;endelse beginstate <= CHECK_R1;endCHECK_R2:if(cnt_full)beginstate <= CHECK_R3;endelse beginstate <= CHECK_R2;endCHECK_R3:if(cnt_full)beginstate <= CHECK_R4;endelse beginstate <= CHECK_R3;endCHECK_R4:if(cnt_full)beginstate <= CHECK_R1;endelse beginstate <= CHECK_R4;enddefault: beginstate <= state;endendcaseendend//状态机输出逻辑always@(posedge clk or negedge rst)beginif(!rst)beginc_pin <= 4'b0000;key_out <= 4'd0;endelse begincase(state)CHECK_R1:beginc_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;endcaseendCHECK_R2:beginc_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;endcaseendCHECK_R3:beginc_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;endcaseendCHECK_R4:beginc_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;endcaseend default:beginc_pin <= 4'b0000;key_out <= 4'd0;endendcaseendend
endmodule
4.check_mima模块
key3控制进入输入密码状态,检测到6次按下后自动检测密码是否正确。正确就回到IDLE,并输出一个mima_flag 一个clk的高电平。可以根据这个标志进行操作。错误就累加,累加到一定次进入WARNING,报警状态。
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) beginif (!rst_n) beginblink_timer <= 0;end else beginif (state == WARNING) beginif (blink_timer == 16'd20) // 假设时钟频率是 50MHz,每 1 秒blink_timer <= 0;elseblink_timer <= blink_timer + 1;end else beginblink_timer <= 0;endendend// 状态机逻辑always @(posedge clk or negedge rst_n) beginif (~rst_n)state <= IDLE; // 异步复位时,状态机回到IDLE状态elsestate <= next_state; // 按时钟更新状态end// 下一个状态的逻辑always @(posedge clk) begincase(state)IDLE: beginif (key3) // 按下key3启动密码输入next_state <= STORE;elsenext_state <= IDLE;endSTORE: beginif (digit_count == 6) // 密码输入6位后,进入校验状态next_state <= CHECK;elsenext_state <= STORE;endCHECK: beginif((mima_error_count==2) && (mima != correct_password))beginnext_state <= WARNING; // 校验完成后回到IDLE状态end else beginnext_state <= IDLE;endendWARNING: beginif (blink_counter == 10) beginnext_state <= IDLE;endelse beginnext_state <= WARNING;endenddefault: next_state <= IDLE;endcaseend// 密码输入存储逻辑always @(posedge clk or negedge rst_n) beginif (~rst_n) beginmima_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 begincase(state)IDLE: beginmima_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;endSTORE: beginif (r_pin != 4'b0000 && digit_count < 6) begindigit_count <= digit_count + 1;endcase(digit_count)6:beginmima_6<=key_out;end1:beginmima_1<=key_out;end2:beginmima_2<=key_out;end3:beginmima_3<=key_out;end4:beginmima_4<=key_out;end5:beginmima_5<=key_out;enddefault:beginmima_1<=4'd0;mima_2<=4'd0;mima_3<=4'd0;mima_4<=4'd0;mima_5<=4'd0;mima_6<=4'd0;endendcaseendCHECK: beginmima_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)beginmima_error_count<=mima_error_count+1;mima_flag <= 0; // 密码验证失败,保持mima_flag为低endendWARNING: beginmima_error_count<=0;if (blink_counter < 10) beginif (blink_timer == 16'd0) beginled_warning = ~led_warning; // 每秒反转一次 ledblink_counter = blink_counter + 1;endend enddefault: beginmima_flag <= 0; // 在其他状态下,密码标志保持低endendcaseendendassign mima={mima_1,mima_2,mima_3,mima_4,mima_5,mima_6};endmodule
5.change_mima模块
类似check_mima模块
`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) beginif (!rst_n) beginblink_timer <= 0;end else beginif (state == CHANGE_OK) beginif (blink_timer == 16'd100) // 假设时钟频率是 50MHz,每 1 秒blink_timer <= 0;elseblink_timer <= blink_timer + 1;end else beginblink_timer <= 0;endend
end// 状态机逻辑always @(posedge clk or negedge rst_n) beginif (~rst_n)state <= IDLE; // 异步复位时,状态机回到IDLE状态elsestate <= next_state; // 按时钟更新状态end// 下一个状态的逻辑always @(posedge clk) begincase(state)IDLE: beginif (key4) // 按下key3启动密码输入next_state = STORE;elsenext_state = IDLE;endSTORE: beginif (digit_count == 6) // 密码输入6位后,进入校验状态next_state <= CHANGE_OK;elsenext_state <= STORE;endCHANGE_OK: beginif(blink_counter == 10)next_state <= IDLE; // 校验完成后回到IDLE状态else beginnext_state <= CHANGE_OK; endenddefault: next_state <= IDLE;endcaseend// 密码输入存储逻辑always @(posedge clk or negedge rst_n) beginif (~rst_n) beginmima_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 begincase(state)IDLE: beginmima_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; // 清空输入的位数endSTORE: beginif (r_pin != 4'b0000 && digit_count < 6) begindigit_count <= digit_count + 1;endcase(digit_count)6:beginmima_6<=key_out;end1:beginmima_1<=key_out;end2:beginmima_2<=key_out;end3:beginmima_3<=key_out;end4:beginmima_4<=key_out;end5:beginmima_5<=key_out;enddefault:beginmima_1<=mima_1;mima_2<=mima_2;mima_3<=mima_3;mima_4<=mima_4;mima_5<=mima_5;mima_6<=mima_6;endendcaseendCHANGE_OK: beginif (blink_counter < 10) beginif (blink_timer == 16'd0) beginled_change<= ~led_change; // 每秒反转一次 ledblink_counter <= blink_counter + 1;endend else beginblink_counter <= blink_counter;endenddefault: beginstate<=IDLE;endendcaseendendendmodule
6.seg_ctrl模块
数码管显示模块
/**************************************功能介绍***********************************
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,//0NUM_1 = 7'b111_1001,//1NUM_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,//bC = 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)begincnt_1ms <= 'd0;end else if(add_cnt_1ms)begin if(end_cnt_1ms)begin cnt_1ms <= 'd0;endelse begin cnt_1ms <= cnt_1ms + 1'b1;end endend 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)beginsel <= 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)begindisp_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]; end6'b111_011 : begin disp_data <= din[11:8] ; point_n_r <= point_n[2]; end6'b110_111 : begin disp_data <= din[15:12]; point_n_r <= point_n[3]; end6'b101_111 : begin disp_data <= din[19:16]; point_n_r <= point_n[4]; end6'b011_111 : begin disp_data <= din[23:20]; point_n_r <= point_n[5]; enddefault: disp_data <= 'd0;endcaseend 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;endcaseendendmodule
7.uart_top模块
//****************************************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//
//****************************************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) beginif(!rst_n) beginuart_rxd_d0 <= 1'b0;uart_rxd_d1 <= 1'b0;uart_rxd_d2 <= 1'b0;endelse beginuart_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) beginif(!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;elserx_flag <= rx_flag;
end //波特率的计数器赋值
always @(posedge clk or negedge rst_n) beginif(!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 elsebaud_cnt <= 16'd0; //接收过程结束时计数器清零
end//对接收数据计数器(rx_cnt)进行赋值
always @(posedge clk or negedge rst_n) beginif(!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; //接收数据计数器加1elserx_cnt <= rx_cnt;endelserx_cnt <= 4'd0; //接收过程结束时计数器清零
end //根据rx_cnt来寄存rxd端口的数据
always @(posedge clk or negedge rst_n) beginif(!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 endelserx_data_t <= rx_data_t;endelserx_data_t <= 8'b0;
end //给接收完成信号和接收到的数据赋值
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginuart_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) beginuart_rx_done <= 1'b1 ; //拉高接收完成信号uart_rx_data <= rx_data_t; //并对UART接收到的数据进行赋值end else beginuart_rx_done <= 1'b0;uart_rx_data <= uart_rx_data;end
endendmodule
//uart_tx//
//uart_tx//
//uart_tx//
//****************************************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) beginif(!rst_n) uart_tx_done<=1'b0;else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - 1) beginuart_tx_done<=1'b1;end elseuart_tx_done<=1'b0; //发送过程结束时计数器清零
end//*****************************************************
//** main code
//*****************************************************//当uart_tx_en为高时,寄存输入的并行数据,并拉高BUSY信号
always @(posedge clk or negedge rst_n) beginif(!rst_n) begintx_data_t <= 8'b0;uart_tx_busy <= 1'b0;end//发送使能时,寄存要发送的数据,并拉高BUSY信号else if(uart_tx_en) begintx_data_t <= uart_tx_data;uart_tx_busy <= 1'b1;end//当计数到停止位结束时,停止发送过程else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - 1) begintx_data_t <= 8'b0; //清空发送数据寄存器uart_tx_busy <= 1'b0; //并拉低BUSY信号endelse begintx_data_t <= tx_data_t;uart_tx_busy <= uart_tx_busy;end
end//波特率的计数器赋值
always @(posedge clk or negedge rst_n) beginif(!rst_n) baud_cnt <= 16'd0;else if(uart_tx_en) baud_cnt <= 16'd0; //当处于发送过程时,波特率计数器(baud_cnt)进行循环计数else if(uart_tx_busy) beginif(baud_cnt < BAUD_CNT_MAX - 1'b1)baud_cnt <= baud_cnt + 16'b1;else baud_cnt <= 16'd0; //计数达到一个波特率周期后清零end elsebaud_cnt <= 16'd0; //发送过程结束时计数器清零
end//tx_cnt进行赋值
always @(posedge clk or negedge rst_n) beginif(!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; //发送数据计数器加1elsetx_cnt <= tx_cnt;endelsetx_cnt <= 4'd0; //发送过程结束时计数器清零
end//根据tx_cnt来给uart发送端口赋值
always @(posedge clk or negedge rst_n) beginif(!rst_n) uart_txd <= 1'b1;else if(uart_tx_busy) begincase(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;endcaseendelseuart_txd <= 1'b1; //空闲时发送端口为高电平
endendmodule
8.key_debounce模块
仿真用不到,按键消抖模块
//
// //
// //
// 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模块
//****************************************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文件
`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 beginsys_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;#100rst_n=1;#100key1=1;#120key1=0;#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;///22222222222222222222222222222222222222222222222222222222222222222ak#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;///22222222222222222222222222222222222222222222222222222222222222222ak#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;///22222222222222222222222222222222222222222222222222222222222222222ak#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;///22222222222222222222222222222222222222222222222222222222222222222ak#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;///22222222222222222222222222222222222222222222222222222222222222222ak#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000key1=1;#20key1=0;///22222222222222222222222222222222222222222222222222222222222222222ak#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#100key2=1;#20key2=0;///22222222222222222222222222222222222222222222222222222222222222222ak#250000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;///22222222222222222222222222222222222222222222222222222222222222222ak#300000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=0;#1720uart_rxd=1;#1000uart_rxd=0;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1736uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1000uart_rxd=0;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;#1720uart_rxd=1;key3=1;///mima#20key3=0;#100r_pin=4'b0100; //1#20r_pin=4'b0000;#100r_pin=4'b0010;//2#20r_pin=4'b0000;#100r_pin=4'b0001;//3#20r_pin=4'b0000;#500000r_pin=4'b1000;//4#20r_pin=4'b0000;#100r_pin=4'b0100;//5#20r_pin=4'b0000;#100r_pin=4'b0010;//6#20r_pin=4'b0000;#1000key3=1;///mima#20key3=0;#100r_pin=4'b0100; //1#20r_pin=4'b0000;#100r_pin=4'b0010;//2#20r_pin=4'b0000;#100r_pin=4'b0001;//3#20r_pin=4'b0000;#500000r_pin=4'b1000;//4#20r_pin=4'b0000;#100r_pin=4'b0100;//5#20r_pin=4'b0000;#100r_pin=4'b0010;//6#20r_pin=4'b0000;#1000key3=1;///mima#20key3=0;#100r_pin=4'b0100; //1#20r_pin=4'b0000;#100r_pin=4'b0010;//2#20r_pin=4'b0000;#100r_pin=4'b0001;//3#20r_pin=4'b0000;#500000r_pin=4'b1000;//4#20r_pin=4'b0000;#100r_pin=4'b0100;//5#20r_pin=4'b0000;#100r_pin=4'b0010;//6#20r_pin=4'b0000;#1000key3=1;///mima#20key3=0;#1000r_pin=4'b1000;//4#20r_pin=4'b0000;#100r_pin=4'b0100;//5#20r_pin=4'b0000;#100r_pin=4'b0010;//6#20r_pin=4'b0000;#1000r_pin=4'b1000;//4#20r_pin=4'b0000;#100r_pin=4'b0100;//5#20r_pin=4'b0000;#100r_pin=4'b0010;//6#20r_pin=4'b0000;#1000key4=1;#20key4=0;#1000#100r_pin=4'b0100; //1#20r_pin=4'b0000;#100r_pin=4'b0010;//2#20r_pin=4'b0000;#100r_pin=4'b0001;//3#20r_pin=4'b0000;#500000r_pin=4'b1000;//4#20r_pin=4'b0000;#100r_pin=4'b0100;//5#20r_pin=4'b0000;#100r_pin=4'b0010;//6#20r_pin=4'b0000;#1000r_pin=4'b1000;//4#20r_pin=4'b0000;#100r_pin=4'b0100;//5#20r_pin=4'b0000;#100r_pin=4'b0010;//6#20r_pin=4'b0000;end
//1736endmodule
这里接受的数据,没有按照手册来,只是将第10个数据设置为00,来表示通讯正确。
总结
其实就是围绕UART和状态机展开的逻辑编写,部分常见代码直接参考了正点原子、野火、等等案例,部分简单功能使用了chatgpt进行描述生成。实现难度并不大,就是涉及的模块较多,不过好好利用仿真结果能够差不多。代码有很多不足之处,有问题欢迎批评指正。