① 首先在相应的文件夹下建立一个名为state_show(可自行命名)的文件,里面分别创建prj(存放工程的文件)、src(存放Verilog代码源文件)、sim(存放仿真文件)、tcl(引脚配置文件),除此之外还可以建立ip(存放知识产权的文件)等…
②打开Quartus ||(我的版本是18.1),新建工程
file——New——New Quartus Prime Preject——OK
然后next,到如下图页面:
③两个next后,根据自己的开发版型号进行选择,笔主这里是:
File->New->Verilog HDL File
module time_count(
input clk, //50M时钟
input rst_n, //复位信号
output reg sec_15//15s
);
parameter MAX_NUM = 30'd749_999_999;//最大数15s,750_000_000-1次
reg [29:0] cnt_15;//计数寄存器
//15s计时器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_15 <= 30'd0;
end
else if(cnt_15 == MAX_NUM)begin
cnt_15 <= 30'd0;
end
else begin
cnt_15 <= cnt_15 + 1'd1;
end
end
//15s脉冲信号
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sec_15 <= 1'b0;
end
else if(cnt_15 == MAX_NUM)begin
sec_15 <= 1'b1;
end
else begin
sec_15 <= 1'b0;
end
end
endmodule
module state_change(
input clk ,
input rst_n ,
input wire sec_15
);
reg [2:0] cstate; //现态
reg [2:0] nstate; //次态
//状态划分
parameter S0 = 0;//初始化
parameter S1 = 1;//启动准备状态
parameter S2 = 2;//启动测试
parameter S3 = 3;//停止测试
parameter S4 = 4;//查询测试结果
parameter S5 = 5;//显示测试结果
//第一段:现态跟随次态
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cstate <= S0;//复位键被按下,当前状态设置为初始化
else
cstate <= nstate; //下一次状态赋值给当前状态
end
//第二段:组合逻辑,阻塞赋值
always@(*)begin
if(!rst_n)
begin
nstate = S0;
end
else
case(cstate)
S0: begin
if(sec_15 == 1'b1)
nstate = S1;
else
nstate = nstate;
end
S1: begin
if(sec_15 == 1'b1)
nstate = S2;
else
nstate = nstate;
end
S2: begin
if(sec_15 == 1'b1)
nstate = S3;
else
nstate = nstate;
end
S3: begin
if(sec_15 == 1'b1)
nstate = S4;
else
nstate = nstate;
end
S4: begin
if(sec_15 == 1'b1)
nstate = S5;
else
nstate = nstate;
end
S5: begin
if(sec_15 == 1'b1)
nstate = S0;
else
nstate = nstate;
end
default: nstate = S0;
endcase
end
endmodule
module state_top(
input clk,
input rst_n
);
wire sec_15;
//实例化计时器模块
time_count inst_time_count(
.clk (clk ),
.rst_n (rst_n ),
.sec_15 (sec_15)
);
//实例化状态切换模块
state_change inst_state_change(
.clk (clk ),
.rst_n (rst_n ),
.sec_15 (sec_15)
);
endmodule
module key_debounce(
input clk,
input rst_n,
input key,
output key_value, //按键稳定信号
output flag //抖动结束标识(0表示未结束,1表示结束)
);
parameter TIME_20MS = 20'd1_000_000; //20ms
reg [19:0] cnt_20ms;
reg key_value_r;
reg flag_r;
reg key_reg; //保存前一次取的key值
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_20ms <= 20'd0;
key_reg <= 1'b1;
end
else begin
key_reg <= key;
if(key_reg == 1'b1 && key == 1'b0)
cnt_20ms <= TIME_20MS;
else if(cnt_20ms <= 20'd0)
cnt_20ms <= 20'd0;
else
cnt_20ms <= cnt_20ms -20'd1;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
flag_r <= 1'b0;
else if(cnt_20ms == 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'b1;
else if(cnt_20ms == 20'd1)
key_value_r <= ~key;
else
key_value_r <= key_value_r;
end
assign key_value = key_value_r;
endmodule
module state(
input clk,
input rst_n,
input [1:0] key,
output wire [3:0] led
);
parameter MAX_TIME = 26'd49_999_999;//1s
parameter TIME_200MS = 24'd9_999_999; //200ms
reg [2:0] cstate; //现态
reg [2:0] nstate; //次态
parameter S0 = 0;//初始状态
parameter S1 = 1;//1状态
parameter S2 = 2;//10状态
parameter S3 = 3;//100状态
parameter S4 = 4;//1001状态
parameter S5 = 5;//10010状态
reg [3:0] led_r;
reg [25:0] cnt_1s;
reg [23:0] cnt_200ms;
//1s计数器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt_1s <= 26'd0;
else if(cnt_1s == MAX_TIME)
cnt_1s <= 26'd0;
else
cnt_1s <= cnt_1s + 26'd1;
end
//200ms计数器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt_200ms <= 24'd0;
else if(cnt_200ms == TIME_200MS)
cnt_200ms <= 24'd0;
else
cnt_200ms <= cnt_200ms + 24'd1;
end
//第一段
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cstate <= S0;
else
cstate <= nstate;
end
//状态切换模块
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
begin
nstate <= S0;
end
else
case(cstate)
S0: begin
if(key[1] )
nstate <= S1;
else if(key[0])
nstate <= S0;
else
nstate <= nstate;
end
S1: begin
if(key[0] )
nstate <= S2;
else if(key[1])
nstate <= S0;
else
nstate <= nstate;
end
S2: begin
if(key[0] )
nstate <= S3;
else if(key[1])
nstate <= S0;
else
nstate <= nstate;
end
S3: begin
if(key[1] )
nstate <= S4;
else if(key[0] )
nstate <= S0;
else
nstate <= nstate;
end
S4: begin
if(key[0] )
nstate <= S5;
else if(key[1] )
nstate <= S0;
else
nstate <= nstate;
end
S5: begin
if(cnt_1s == MAX_TIME)
nstate <= S0;
else
nstate <= S5;
end
default: nstate <= S0;
endcase
end
//第三段:跟随状态输出
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
led_r <=4'b0000;
else
case(cstate)
S5:begin
if(cnt_200ms == TIME_200MS)
led_r <= ~led_r;
else
led_r <= led_r;
end
default: led_r <= 4'b0000;
endcase
end
assign led = led_r;
endmodule
3、顶层模块
module state_top(
input wire clk,
input wire rst_n,
input wire [1:0] key,
output wire [3:0] led
);
wire [1:0] flag;
wire [1:0] key_value;
//实例化按键KEY0
key_debounce inst_key_debounce(
.clk (clk ),
.rst_n (rst_n ),
.key (key[0] ),
.flag (flag[0] ),
.key_value(key_value[0])
);
//实例化按键KEY1
key_debounce inst_key_debounce1(
.clk (clk ),
.rst_n (rst_n ),
.key (key[1] ),
.flag (flag[1] ),
.key_value(key_value[1])
);
//实例化状态切换模块
state inst_state(
.clk (clk ),
.rst_n(rst_n ),
.key ({key_value[1]&&flag[1],key_value[0]&&flag[0]}),
.led (led)
);
endmodule