今天比较痛苦,主要是下午的加法器一直没实现。而且调试半天没成功,有很大部分时间也浪费在了,忘了原来flash里面他们烧有程序了,然后相当于一直调试,白调了。还有就是我总感觉,可能是数码管显示那里,我没弄完全透,那部分出了些问题,因为感觉加法计算这一块,没啥逻辑问题,就算有,感觉还没到后面,就前面显示都有问题。 总之弄半天了,也挺难受的。
还是先总结今天写的吧。
学习内容:
按键输入密码锁,还有固化文件的设置(将文件写到flash中去)
下午就是实现加法器。
产生疑惑:
参数等正常传入,为啥,数码管不能正常显示给定数字,数码管的显示和数字表示的进制方式,位宽有关吗,即3’d2, 3'b10, 4'd2 这三种数字传入后,显示的数字是一样的吗?答案是不影响
感觉数码管那一块还是没掌握特别好。
其他的感觉今天讲的很少,下面就贴些代码吧。
密码锁:
module password(
input clk,
input rst_n,
input [3:0] key,
output reg [3:0] led
);
//状态空间
parameter IDLE = 3'd0;
parameter S1 = 3'd1;
parameter S2 = 3'd2;
parameter S3 = 3'd3;
parameter S4 = 3'd4;
parameter CNT_MAX = 26'd49_999_999;
parameter TIME = 24'd9_999_999;
reg [23:0]cnt_200ms;
reg [25:0] cnt;
reg [2:0] cstate;//当前状态
wire add_cnt;
wire end_cnt;
wire add_cnt_200ms;
wire end_cnt_200ms;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if (end_cnt) begin
cnt <= 0;
end
else begin
cnt <= cnt +1'd1;
end
end
end
assign add_cnt = (cstate == S4);
assign end_cnt = add_cnt && cnt == CNT_MAX;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_200ms <= 0;
end
else if(add_cnt_200ms)begin
if (end_cnt_200ms) begin
cnt_200ms <= 0;
end
else begin
cnt_200ms <= cnt_200ms +1'd1;
end
end
else begin
end
end
assign add_cnt_200ms = (cstate == S4);
assign end_cnt_200ms = add_cnt_200ms && cnt_200ms == TIME;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cstate <= IDLE;
end
else begin
case (cstate)
IDLE: begin
if(key[0])begin//1
cstate <= S1;
end
else if (key[1]|key[2]|key[3]) begin
cstate = IDLE;
end
else
cstate <= IDLE;
end
S1: begin
if(key[3])begin//4
cstate <= S2;
end
else if (key[1]|key[2]|key[0]) begin
cstate = IDLE;
end
else
cstate <= S1;
end
S2: begin
if(key[1])begin//2
cstate <= S3;
end
else if (key[0]|key[2]|key[3]) begin
cstate = IDLE;
end
else
cstate <= S2;
end
S3: begin
if(key[2])begin//3
cstate <= S4;
end
else if (key[0]|key[1]|key[3]) begin
cstate = IDLE;
end
else
cstate <= S3;
end
S4: begin
if (end_cnt) begin
cstate <= IDLE;
end
else
cstate <= S4;
end
default: ;
endcase
end
end
reg [0:0]flag;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
led <= 0;
flag <= 1'b1;
end
else begin
case (cstate)
IDLE: led <= 4'b0000;
S1 : led <= 4'b0001;
S2 : led <= 4'b0011;
S3 : begin
led <= 4'b0111;
flag <= 1'b1;
end
S4 : begin
if (flag) begin
led <= 4'b1111;
flag <= 1'b0;
end
else if(end_cnt_200ms)
begin
led <= ~led;
end
else begin
led <= led;
end
end
default: ;
endcase
end
end
endmodule
顶层文件
module top_key_lock(
input clk,
input rst_n,
input [3:0]key,
output [3:0]led
);
wire [3:0] key_reg;
password u_password(
.clk(clk),
.rst_n(rst_n),
.key(key_reg),
.led(led)
);
key_keep u0_key_keep(
.clk(clk),
.rst_n(rst_n),
.key_in(key[0]),
.key_down(key_reg[0])
);
key_keep u1_key_keep(
.clk(clk),
.rst_n(rst_n),
.key_in(key[1]),
.key_down(key_reg[1])
);
key_keep u2_key_keep(
.clk(clk),
.rst_n(rst_n),
.key_in(key[2]),
.key_down(key_reg[2])
);
key_keep u3_key_keep(
.clk(clk),
.rst_n(rst_n),
.key_in(key[3]),
.key_down(key_reg[3])
);
endmodule
按键消抖
module key_keep(//消抖模块
input clk,
input rst_n,
input key_in,//未消抖的按键
output reg key_down//消抖后的按键值
);
/****************************************************************
main
按键消抖用状态机方法实现
***************************************************************/
//定义按键按下的四个 状态
localparam IDLE = 4'b0001;
localparam FILTER_DOWN = 4'b0010;//按键按下过程
localparam HOLD_DOWN = 4'b0100 ;
localparam FILTER_UP = 4'b1000; //按键松开过程
parameter TIME_DELAY = 20'd100_0000;
wire add_delay_cnt;//开始计时的标志
wire end_delay_cnt;//结束及时的标志
reg [19:0] cnt;
reg [3:0] state_c;//现态
reg [3:0] state_n;//次态
reg key_in_r0;
reg key_in_r1;
wire n_edge;//按键按下
wire p_edge;//按键松开
wire idle2filter_down_start;
wire filter_down2hold_down_start;
wire filter_down2idle_start;
wire hold_down2filter_up_start;
wire filter_up2idle_start;
//接收按键信号
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
key_in_r0 <= 1'b1;
key_in_r1 <= 1'b1;
end
else begin
key_in_r0 <= key_in;
key_in_r1 <= key_in_r0;
end
end
assign n_edge = ~key_in_r0 & key_in_r1;
assign p_edge = ~key_in_r1 & key_in_r0;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state_c <= IDLE;
end
else begin
state_c <= state_n;
end
end
always @(*)begin
if(!rst_n)begin
state_n = IDLE;
end
else begin
case (state_c)
IDLE:begin
if(idle2filter_down_start)
state_n <=FILTER_DOWN;
else
state_n <=state_c;
end
FILTER_DOWN:begin
if(filter_down2hold_down_start)begin
state_n <= HOLD_DOWN;
end
else if (filter_down2idle_start) begin
state_n <=IDLE;
end
else
state_n <= state_c;
end
HOLD_DOWN: begin
if (hold_down2filter_up_start) begin
state_n <= FILTER_UP;
end
else
state_n <= state_c;
end
FILTER_UP: begin
if (filter_up2idle_start)begin
state_n <= IDLE;
end
else
state_n <= state_c;
end
default: ;
endcase
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
key_down <= 0;
end
else if(hold_down2filter_up_start)begin
key_down <= ~key_in_r1;//如果不取反,按键按下就输出0,取反,按键按下就输出1
end
else begin
key_down <= 1'b0;
end
end
assign idle2filter_down_start = (state_c == IDLE)&&(n_edge);
assign filter_down2idle_start = (state_c == FILTER_DOWN)&&(add_delay_cnt && p_edge);
assign filter_down2hold_down_start = (state_c == FILTER_DOWN)&&(end_delay_cnt && !p_edge);
assign hold_down2filter_up_start = (state_c == HOLD_DOWN)&&(p_edge);
assign filter_up2idle_start = (state_c == FILTER_UP)&&(end_delay_cnt);
/*计数条件与结束条件*/
assign add_delay_cnt = (state_c==FILTER_DOWN) || (state_c==FILTER_UP);
assign end_delay_cnt = add_delay_cnt && (cnt == TIME_DELAY-1);
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 20'd0;
end
else if(add_delay_cnt)begin
if (end_delay_cnt) begin
cnt <= 20'd0;
end
else begin
cnt <= cnt +1'b1;
end
end
else begin
cnt <= cnt;
end
end
endmodule