【FPGA】状态机简单实现

本文档介绍了如何使用Verilog语言分别实现一个数码管滚动显示'HELLO'的测试过程和一个按键输入检测10010密码的模块。在数码管模块中,利用状态机控制在90秒内完成六个状态的切换,显示'HELLO'滚动。而在密码检测模块中,通过状态机和按键消抖模块,确保只有输入正确的10010序列时才能进入下一个状态。这两个实例展示了状态机在简短序列处理中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、任务一

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

三、总结

在序列串较短的时候,用状态切换不仅思路清晰,而且比较简单。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值