一、任务一
1、根据以下描述功能用verilog编写一段代码,并用状态机来实现该功能。
(1)状态机:实现一个测试过程,该过程包括启动准备状态、启动测试、停止测试、查询测试结果、显示测试结果、测试结束返回初始化6个状态;用时间来控制该过程,90秒内完成该过程;
(2)描述状态跳转时间;
(3)编码实现。
1.1需求分析
实现六个状态,并且用时间来控制这个过程,说简单一点,就是根据时间切换六个状态下面我们用状态机实现HELLO在数码管上滚动显示来代表这六个状态。
1.2实现
计数器模块:
module time_count(
input wire clk,//时钟,50MHZ
input wire rst_n,//复位信号,下降沿有效
output wire sec_05//0.5脉冲信号
);
parameter MAX_NUM=25'd24_999_999;//计最大数,0.5s,24_999_999
reg [24:0] cnt_05;//计数寄存器
reg sec_05_r;
//0.5s计数器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_05 <= 25'b0;
end
else if(cnt_05 == MAX_NUM)begin
cnt_05 <= 25'b0;
end
else
cnt_05 <= cnt_05 +1'b1;
end
//0.5s脉冲
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sec_05_r <= 1'b0;
end
else if(cnt_05 == MAX_NUM)begin
sec_05_r <= 1'b1;
end
else
sec_05_r <= 1'b0;
end
assign sec_05 = sec_05_r;
endmodule
数码管模块及状态机实现:
//数码管led
module test_3_digital_HELLO(
input wire clk,//时钟,50MHZ
input wire rst_n,//复位信号,下降沿有效
input wire sec_05,
output wire [6:0] HEX0,//8个数码管
output wire [6:0] HEX1,
output wire [6:0] HEX2,
output wire [6:0] HEX3,
output wire [6:0] HEX4,
output wire [6:0] HEX5,
output wire [6:0] HEX6,
output wire [6:0] HEX7
);
parameter H = 7'b1001_000;
parameter E = 7'b0110_000;
parameter L = 7'b1110_001;
parameter O = 7'b0000_001;
parameter X = 7'b1111_111;
reg [6:0] HEX0_r;
reg [6:0] HEX1_r;
reg [6:0] HEX2_r;
reg [6:0] HEX3_r;
reg [6:0] HEX4_r;
reg [6:0] HEX5_r;
reg [6:0] HEX6_r;
reg [6:0] HEX7_r;
reg [2:0] value;//
//0-4计数功能 共五位
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
value <= 3'h0;
end
else if(sec_05)begin
if(value < 3'h7)begin //可以修改4'h4
value <= value + 1'h1;
end
else begin
value <= 3'h0;
end
end
else begin
value <= value;
end
end
//数码管译码功能,组合逻辑
always@(*)begin
case(value)
3'b000: begin
HEX7_r = H ;
HEX6_r = E ;
HEX5_r = L ;
HEX4_r = L ;
HEX3_r = O ;
HEX2_r = X ;
HEX1_r = X ;
HEX0_r = X ;
end
3'b001: begin
HEX7_r = X ;
HEX6_r = H ;
HEX5_r = E ;
HEX4_r = L ;
HEX3_r = L ;
HEX2_r = O ;
HEX1_r = X ;
HEX0_r = X ;
end
3'b010:begin
HEX7_r = X ;
HEX6_r = X ;
HEX5_r = H ;
HEX4_r = E ;
HEX3_r = L ;
HEX2_r = L ;
HEX1_r = O ;
HEX0_r = X ;
end
3'b011:begin
HEX7_r = X ;
HEX6_r = X ;
HEX5_r = X ;
HEX4_r = H ;
HEX3_r = E ;
HEX2_r = L ;
HEX1_r = L ;
HEX0_r = O ;
end
3'b100: begin
HEX7_r = O ;
HEX6_r = X ;
HEX5_r = X ;
HEX4_r = X ;
HEX3_r = H ;
HEX2_r = E ;
HEX1_r = L ;
HEX0_r = L ;
end
3'b101: begin
HEX7_r = L ;
HEX6_r = O ;
HEX5_r = X ;
HEX4_r = X ;
HEX3_r = X ;
HEX2_r = H ;
HEX1_r = E ;
HEX0_r = L ;
end
3'b110: begin
HEX7_r = L ;
HEX6_r = L ;
HEX5_r = O ;
HEX4_r = X ;
HEX3_r = X ;
HEX2_r = X ;
HEX1_r = H ;
HEX0_r = E ;
end
3'b111: begin
HEX7_r = E ;
HEX6_r = L ;
HEX5_r = L ;
HEX4_r = O ;
HEX3_r = X ;
HEX2_r = X ;
HEX1_r = X ;
HEX0_r = H ;
end
default: begin
HEX7_r = X ;
HEX6_r = X ;
HEX5_r = X ;
HEX4_r = H ;
HEX3_r = E ;
HEX2_r = L ;
HEX1_r = L ;
HEX0_r = O ;
end
endcase
end
assign HEX0 = HEX0_r;
assign HEX1 = HEX1_r;
assign HEX2 = HEX2_r;
assign HEX3 = HEX3_r;
assign HEX4 = HEX4_r;
assign HEX5 = HEX5_r;
assign HEX6 = HEX6_r;
assign HEX7 = HEX7_r;
endmodule
顶层文件:
module digital_char(
input wire clk,//时钟,50MHZ
input wire rst_n,//复位信号,下降沿有效
output wire [6:0] HEX0,//5个数码管
output wire [6:0] HEX1,
output wire [6:0] HEX2,
output wire [6:0] HEX3,
output wire [6:0] HEX4,
output wire [6:0] HEX5,
output wire [6:0] HEX6,
output wire [6:0] HEX7
);
wire sec_05;
time_count inst_time_count(
.clk (clk ),//时钟,50MHZ
.rst_n (rst_n ),//复位信号,下降沿有效
.sec_05 (sec_05)//0.5脉冲信号
);
test_3_digital_HELLO inst_test_3_digital_HELLO(
.clk (clk ),//时钟,50MHZ
.rst_n (rst_n ),//复位信号,下降沿有效
.sec_05 (sec_05),//0.5s脉冲信号
.HEX0 (HEX0 ),//一个数码管
.HEX1 (HEX1 ),
.HEX2 (HEX2 ),
.HEX3 (HEX3 ),
.HEX4 (HEX4 ),
.HEX5 (HEX5 ),
.HEX6 (HEX6 ),
.HEX7 (HEX7 )
);
endmodule
二、任务二
2.1需求分析
需要检测10010的数据串,只有当10010依次输入时,才能通过检测,而实现这个功能,可以通过按键来模拟0和1的值,并且使用6个状态,只有当输入的值正确之后,才能进入下一个状态,不然就会回到出事状态
2.2实现
按键消抖模块:
module key_debounce( //按键消抖模块
input wire clk,
input wire rst_n,
input wire key,
output wire key_value, //按键稳定信号
output wire flag //按键稳定标志
);
parameter delay_time = 1_000_000;
reg [22:0] delay_cnt;
reg key_reg;
reg flag_r;
reg key_value_r;
//0.2ms计时器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
key_reg <= 1'b0;
else begin
key_reg <= key;
if(key_reg == 1'b1 && key == 1'b0)begin
delay_cnt <= delay_time;
end
else if (delay_cnt == 20'd0)
delay_cnt <= 20'd0;
else if (key_reg == 1'b0 && key == 1'b0)
delay_cnt <= delay_cnt -1'd1;
end
end
//控制flag
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
flag_r <= 1'b0;
else if (delay_cnt == 20'd1)
flag_r <= 1'b1;
else
flag_r <= 1'b0;
end
assign flag = flag_r;
//得到输出值
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
key_value_r <= 1'b0;
else if (delay_cnt == 20'd1)
key_value_r <= ~key ;
else
key_value_r <= key_value_r;
end
assign key_value =key_value_r;
endmodule
密码模块:
/* 密码:10010 */
module password(
input wire clk,
input wire rst_n,
input wire [1:0] key,
output wire [3:0] led
);
//转态空间
parameter IDLE = 3'd0;
parameter S1 = 3'd1;//按对一个
parameter S2 = 3'd2;//按对两个
parameter S3 = 3'd3;//按对三个
parameter S4 = 3'd4;//按对四个
parameter S5 = 3'd5;//按对五个
parameter MAX_NUM=26'd49_999_999;
reg [2:0] cstate;
reg [3:0] led_r;
reg [25:0] cnt;
//1s计时器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 26'd0;
else if (cnt == MAX_NUM)
cnt <= 26'd0;
else
cnt <= cnt + 1'd1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cstate <= IDLE;
end
else begin
case(cstate)
IDLE:begin
if(key[1])begin
cstate <= S1;
end
else if(key[0])
cstate <= IDLE;
else
cstate <= cstate;
end
S1:begin
if(key[0])begin
cstate <= S2;
end
else if(key[1])
cstate <= IDLE;
else
cstate <= cstate;
end
S2:begin
if(key[0])begin
cstate <= S3;
end
else if(key[1])
cstate <= IDLE;
else
cstate <= cstate;
end
S3:begin
if(key[1])begin
cstate <= S4;
end
else if(key[0])
cstate <= IDLE;
else
cstate <= cstate;
end
S4:begin
if(key[0])begin
cstate <= S5;
end
else if(key[1])
cstate <= IDLE;
else
cstate <= cstate;
end
default:cstate <= cstate;
endcase
end
end
//状态输出
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
led_r <= 4'b0;
else begin
case(cstate)
IDLE: led_r <= 4'b0001;
S1: led_r <= 4'b0010;
S2: led_r <= 4'b0100;
S3: led_r <= 4'b1000;
S4: led_r <= 4'b1110;
S5: led_r <= 4'b1111;
default led_r <= led_r;
endcase
end
end
assign led =led_r;
endmodule
顶层文件:
module state_judge_top(
input wire clk,
input wire rst_n,
input wire [1:0] key,
output wire [3:0] led
);
wire [1:0] key_value;
wire [1:0] flag;
key_debounce i0_key_debounce(
.clk (clk),
.rst_n (rst_n),
.key (key[0]),
.key_value (key_value[0]), //按键稳定信号
.flag (flag[0])//按键稳定标志
);
key_debounce i1_key_debounce(
.clk (clk),
.rst_n (rst_n),
.key (key[1]),
.key_value (key_value[1]), //按键稳定信号
.flag (flag[1])//按键稳定标志
);
password i_password(
.clk (clk),
.rst_n (rst_n),
.key ({key_value[1]&&flag[1],key_value[0]&&flag[0]}),
.led (led)
);
endmodule
三、总结
在序列串较短的时候,用状态切换不仅思路清晰,而且比较简单。