IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【FPGA实验】基于DE2-115平台的数码管实验2 -> 正文阅读

[嵌入式]【FPGA实验】基于DE2-115平台的数码管实验2

一.试验任务

1.用移位寄存器与FSM实现“HELLO”的循环显示

本练习使用移位寄存器并结合FSM实现DE2-115平台上 的“HELLO”循环显示。在HEX7~HEX0上循环显示
“HELLO”,根据手动时钟输入脉冲的控制,每接收到一 个脉冲,显示左移一位,当“HELLO”移出左边后,从右 边重新开始显示。
将8个7位寄存器按流水线的形式排列,即第一个寄存器 的输出作为第二个寄存器的输入,第二个寄存器的输出作为
第三个寄存器的输入,依此类推。每个寄存器的输出同时驱 动七段数码管的显示。请设计一个状态机对寄存器流水线进 行以下控制: (1)
在前8个时钟,FSM将字符“H,E,L,L,O, , , ”分别插入8个7位寄存器。 (2)
第(1)步完成后,将寄存器流水线配置成循环模式, 即最后一个寄存器的输出作为第一个寄存器的输入,使字符 可以无限循环显示。
建立一个新的Quartus Ⅱ工程,完成以上的任务。用 DE2-115平台上的KEY0作为FSM及移位寄存器的手动时钟 输入,用SW0作为低电平有效同步清除输入,并按照代码 6.7所示的架构实现所要求的电路。工程编译完成后,将电 路下载到FPGA中测试其功能。

2.用FSM实现“HELLO”的自动循环显示

对上一个练习的内容加以改动,字符的移动以1 s为间 隔自动进行,在HEX7~HEX0上循环显示“HELLO”,
“HELLO”从左边移出后,再从右边重新开始显示。建立 一个新的Quartus Ⅱ工程,完成此任务,用DE2-115平台上的 50
MHz时钟(CLOCK_50)作为FSM及移位寄存器的时钟输入, 并确保所有的触发器都采用CLOCK_50作为时钟,用KEY0
作为低电平有效同步清除输入,并参照代码6.7所示的架构 实现所要求的电路。工程编译完成后,将电路下载到FPGA 中进行功能测试。

3.移动速度可控的“HELLO”的自动循环显示

对上一个练习的内容加以改动,使“HELLO”移动的 速度可以控制:当KEY1按下时,移动速度增加一倍;当 KEY2按下时,移动速度减小一半。
KEY2和KEY1是经过去抖处理的,能够产生一个精确 的脉冲,但脉冲的长度是任意的。建议另外增加一个FSM以
监测按键的状态,这个FSM的输出可以作为调整移动时间间 隔的一个变量。KEY2和KEY1是异步输入的,因此在FSM
中使用时应先与系统时钟同步。 电路复位后,字符每秒移动一次。当连续按KEY1键时, 字符最快以每秒4次的速度移动;当连续按KEY2键时,字
符最慢以每秒一次的速度移动。 建立一个新的Quartus Ⅱ工程,完成以上任务,并在 DE2-115开发板上测试其功能。

二.用移位寄存器与FSM实现“HELLO”的循环显示

使用三段式写状态机

①设计按键消抖模块

这里使用按键时需要消抖,否则不稳定状态会导致按下一次产生多次按下效果。
key_debounce.v

module key_debounce(
	input  wire  clk,
	input  wire  rst_n,
	input  wire  key,
	
	output reg   flag,               //判断抖动是否消除的标志信号,0为抖动,1为抖动结束
	output reg   key_value           //消抖后稳定的按键值给到蜂鸣器模块和LED模块
);

//定义20ms延迟计数器,0.2s,1_000_000次
reg [19:0] delay_cnt;

//寄存依次key的值用来判断按键是否消抖成功
reg key_reg;

//按下按键20ms延时计数器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		begin
			key_reg <= 1'b1;                        //复位信号,设置按键无效
			delay_cnt <= 1'b0;                      //计数器设置为0
		end
	else
		begin
			key_reg <= key; 
			if(key_reg ^ key)            //当这一次key值和上一次key值不一样,证明正在抖动
				delay_cnt <= 20'd1000;          //延迟时间20ms(1_000_000) 仿真用20000ns(1000)
			else if(delay_cnt > 0)
				delay_cnt <= delay_cnt - 1;          //没有抖动,开始20ms倒计时
			else
				delay_cnt <= 1'b0;                  
		end
end


//根据延时计数器获取按键状态以及按键值
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		begin
		   flag <= 1'b0;                               //复位信号,设置信号标志为抖动
			key_value <= 1'b1;                          //设置抽样值为1
		end
	else
		begin
			if(delay_cnt == 20'd1)                      //倒计时1_000_000到1
				begin
					flag <= 1'b1;
					key_value <= key;                     //稳定20ms后将key值给到key_value
				end
			else	
				begin
					flag <= 1'b0;
					key_value <= key_value;               //20ms内先不取样
				end
		end
end

endmodule

②设计数码管显示模块

fsm_hello.v

module fsm_hello(
	input wire clk,//时钟
	input wire rst_n,//复位
	input wire key,//手动脉冲信号
	
	output wire [6:0] seg0,//7位数码管段选信号
	output wire [6:0] seg1,
	output wire [6:0] seg2,
	output wire [6:0] seg3,
	output wire [6:0] seg4,
	output wire [6:0] seg5,
	output wire [6:0] seg6,
	output wire [6:0] seg7
);

reg [3:0] cstate;//现态
reg [3:0] nstate;//次态

//状态划分
localparam st_HELLO = 0;
localparam st_ELLO0 = 1;
localparam st_LLO00 = 2;
localparam st_LO000 = 3;
localparam st_O0000 = 4;
localparam st_00000 = 5;
localparam st_0000H = 6;
localparam st_000HE = 7;
localparam st_00HEL = 8;
localparam st_0HELL = 9;

reg [6:0] seg_r0;
reg [6:0] seg_r1;
reg [6:0] seg_r2;
reg [6:0] seg_r3;
reg [6:0] seg_r4;
reg [6:0] seg_r5;
reg [6:0] seg_r6;
reg [6:0] seg_r7;

reg [3:0] cnt;//记录8个时钟
reg flag;//计时标志
wire key_posedge;//key上升沿
reg key1,key2;//两拍

//key上升沿检测
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		key1 <= 1'b0;
		key2 <= 1'b0;
	end
	else begin
		key1 <= key;//key1得到上一个时钟的key
		key2 <= key1;//key2得到上一个时钟key1,也就是上上个时钟的key
	end
end

assign key_posedge = key1 && ~key2;

//8个时钟计数器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt <= 4'd0;
	end
	else if(flag == 1'b1)begin
		if(cnt == 4'd8)begin
			cnt <= 1'd0;
		end
		else begin
			cnt <= cnt + 1'd1;
	   end
	end
	else begin
		cnt <=4'd0;
	end
end

//第一段:现态跟随次态,时序逻辑,非阻塞赋值
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cstate <= st_HELLO;
	end
	else begin
		cstate <= nstate;
	end
end

//第二段:组合逻辑,阻塞赋值
always@(*)begin
	if(!rst_n)begin
		nstate = st_HELLO;
	end
	else begin
		case(cstate)
			st_HELLO:begin
				if(key_posedge == 1'b1)begin
					nstate = st_ELLO0;
				end
				else begin
					nstate = nstate;
				end
			end
			st_ELLO0:begin
				if(key_posedge == 1'b1)begin
					nstate = st_LLO00;
				end
				else begin
					nstate = nstate;
				end
			end
			st_LLO00:begin
				if(key_posedge == 1'b1)begin
					nstate = st_LO000;
				end
				else begin
					nstate = nstate;
				end
			end
			st_LO000:begin
				if(key_posedge == 1'b1)begin
					nstate = st_O0000;
				end
				else begin
					nstate = nstate;
				end
			end
			st_O0000:begin
				if(key_posedge == 1'b1)begin
					nstate = st_00000;
				end
				else begin
					nstate = nstate;
				end
			end
			st_00000:begin
				if(key_posedge == 1'b1)begin
					nstate = st_0000H;
				end
				else begin
					nstate = nstate;
				end
			end
			st_0000H:begin
				if(key_posedge == 1'b1)begin
					nstate = st_000HE;
				end
				else begin
					nstate = nstate;
				end
			end
			st_000HE:begin
				if(key_posedge == 1'b1)begin
					nstate = st_00HEL;
				end
				else begin
					nstate = nstate;
				end
			end
			st_00HEL:begin
				if(key_posedge == 1'b1)begin
					nstate = st_0HELL;
				end
				else begin
					nstate = nstate;
				end
			end
			st_0HELL:begin
				if(key_posedge == 1'b1)begin
					nstate = st_HELLO;
				end
				else begin
					nstate = nstate;
				end
			end
			default:;
		endcase
	end
end

//三段式:跟随状态输出
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		flag <= 1'b1;
		seg_r0 <= 7'b111_1111;
		seg_r1 <= 7'b111_1111;
		seg_r2 <= 7'b111_1111;
		seg_r3 <= 7'b111_1111;
		seg_r4 <= 7'b111_1111;
		seg_r5 <= 7'b111_1111;
		seg_r6 <= 7'b111_1111;
		seg_r7 <= 7'b111_1111;
	end
	else if(flag)begin
		case(cnt)
			4'd0:seg_r0 <= 7'b100_0000;
			4'd1:seg_r1 <= 7'b100_0111;
			4'd2:seg_r2 <= 7'b100_0111;
			4'd3:seg_r3 <= 7'b000_0110;
			4'd4:seg_r4 <= 7'b000_1001;
			4'd5:seg_r5 <= 7'b111_1111;
			4'd6:seg_r6 <= 7'b111_1111;
			4'd7:seg_r7 <= 7'b111_1111;
			4'd8:flag   <= 1'b0       ;
			default:;
		endcase
	end
	else begin
		case(cstate)
			st_HELLO:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_ELLO0:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_LLO00:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_LO000:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_O0000:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_00000:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_0000H:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_000HE:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_00HEL:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_0HELL:begin 
				if(key_posedge)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			default:;
		endcase
	end
end

assign {seg7,seg6,seg5,seg4,seg3,seg2,seg1,seg0} = {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};

endmodule


③设计顶层模块

fsm_hello_top.v

module fsm_hello_top(
	input  wire  		clk,
	input  wire  		rst_n,
	input  wire    	key,
	
	output wire [6:0] seg0,//7位数码管段选信号
	output wire [6:0] seg1,
	output wire [6:0] seg2,
	output wire [6:0] seg3,
	output wire [6:0] seg4,
	output wire [6:0] seg5,
	output wire [6:0] seg6,
	output wire [6:0] seg7
);

wire key_value;
wire flag;


//例化按键key消抖模块
key_debounce inst_key_debounce(
.clk       (clk      ),
.rst_n     (rst_n    ),
.key       (key      ),
            
.flag      (flag     ),              
.key_value (key_value)          
);

//例化HELLO状态机模块
fsm_hello inst_fsm_hello(
.clk  (clk),//时钟
.rst_n(rst_n),//复位
.key  (~key_value && flag),//手动脉冲信号
	
.seg0 (seg0),//7位数码管段选信号
.seg1 (seg1),
.seg2 (seg2),
.seg3 (seg3),
.seg4 (seg4),
.seg5 (seg5),
.seg6 (seg6),
.seg7 (seg7)
);

endmodule

④设计仿真文件

fsm_hello_top_tb.v

`timescale 1ns/1ns                  //时间单位和时间精度,两者最多一样大,精度不能大于单位

module fsm_hello_top_tb();

parameter DELAY = 50000;

reg        clk_50M;                //wire型改为reg类型,可以起不同的名字
reg        rst_n;  
reg        key; 

wire [6:0] seg0;                             
wire [6:0] seg1;	   
wire [6:0] seg2;		
wire [6:0] seg3;		
wire [6:0] seg4;		
wire [6:0] seg5;		
wire [6:0] seg6;		
wire [6:0] seg7;


//激励信号
always #10 clk_50M = ~clk_50M;     //每过10ns,时钟取反,总是执行

//信号初始化
initial begin
	clk_50M = 1'b0;
	rst_n = 1'b0;
	#10;                            //复位信号延迟10纳秒变为无效
	rst_n = 1'b1;
	#200;
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第1次按下
	#DELAY
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第2次按下
	#DELAY
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第3次按下
	#DELAY
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第4次按下
	#DELAY
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第5次按下
	#DELAY
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第6次按下
	#DELAY
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第7次按下
	#DELAY
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第8次按下
	#DELAY
	key = 1'b1;
	#DELAY
	
	key = 1'b0;//第9次按下
	#DELAY
	key = 1'b1;
	#DELAY
	                        //延迟后停止
	$stop;
end

fsm_hello_top inst_fsm_hello_top(
.clk     (clk_50M),
.rst_n	(rst_n),
.key  	(key),

.seg0 	(seg0),//7位数码管段选信号
.seg1 	(seg1),
.seg2 	(seg2),
.seg3 	(seg3),
.seg4 	(seg4),
.seg5 	(seg5),
.seg6 	(seg6),
.seg7 	(seg7)
);

endmodule

⑤查看RTL门级电路

在这里插入图片描述

⑥仿真波形

在这里插入图片描述
可以看见付复位号后,所有数码管寄存器初始化值为111_1111。在前面8个时钟周期,分别为每个寄存器赋值
在这里插入图片描述
此后0~7号寄存器分别赋值给7,0,1,2,3,4,5,6号寄存器,实现数码管的移动显示
在这里插入图片描述
可以看见key每按下一次,HELLO就移动一次

三.用FSM实现“HELLO”的自动循环显示

①设计计数器模块

同实验1
time_count.v

module time_count(
	input wire clk,   //时钟,50MHZ                        
	input wire rst_n, //复位信号,下降沿有效,negative
	
	output wire sec_1//1s输出一个脉冲信号             
);


parameter MAX_NUM = 26'd49_999;//记最大数1s,50_000_000次 仿真使用1ms
reg [25:0] cnt_1;//计数寄存器
reg sec_1_r;


//1s计时器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_1 <= 26'd0;
	end
	else if(cnt_1 == MAX_NUM)begin
		cnt_1 <= 26'd0;	
	end
	else begin
		cnt_1 <= cnt_1 + 1'd1;
	end
end


//1s脉冲信号
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		sec_1_r <= 1'b0;
	end
	else if(cnt_1 == MAX_NUM)begin
		sec_1_r <= 1'b1;
	end
	else begin
		sec_1_r <= 1'b0;
	end
end

assign sec_1 = sec_1_r;//当右边改变,立马赋值给左边 assign和always并行

endmodule

②设计数码管显示模块

fsm_hello.v

module fsm_hello(
	input wire clk,//时钟
	input wire rst_n,//复位
	input wire sec_1,//1s脉冲信号
	
	output wire [6:0] seg0,//7位数码管段选信号
	output wire [6:0] seg1,
	output wire [6:0] seg2,
	output wire [6:0] seg3,
	output wire [6:0] seg4,
	output wire [6:0] seg5,
	output wire [6:0] seg6,
	output wire [6:0] seg7
);

reg [3:0] cstate;//现态
reg [3:0] nstate;//次态

//状态划分
localparam st_HELLO = 0;
localparam st_ELLO0 = 1;
localparam st_LLO00 = 2;
localparam st_LO000 = 3;
localparam st_O0000 = 4;
localparam st_00000 = 5;
localparam st_0000H = 6;
localparam st_000HE = 7;
localparam st_00HEL = 8;
localparam st_0HELL = 9;

reg [6:0] seg_r0;
reg [6:0] seg_r1;
reg [6:0] seg_r2;
reg [6:0] seg_r3;
reg [6:0] seg_r4;
reg [6:0] seg_r5;
reg [6:0] seg_r6;
reg [6:0] seg_r7;

reg [3:0] cnt;
reg flag;

//8个时钟计数器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt <= 4'd0;
	end
	else if(flag == 1'b1)begin
		if(cnt == 4'd8)begin
			cnt <= 1'd0;
		end
		else begin
			cnt <= cnt + 1'd1;
	   end
	end
	else begin
		cnt <=4'd0;
	end
end

//第一段:现态跟随次态,时序逻辑,非阻塞赋值
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cstate <= st_HELLO;
	end
	else begin
		cstate <= nstate;
	end
end

//第二段:组合逻辑,阻塞赋值
always@(*)begin
	if(!rst_n)begin
		nstate = st_HELLO;
	end
	else begin
		case(cstate)
			st_HELLO:begin
				if(sec_1 == 1'b1)begin
					nstate = st_ELLO0;
				end
				else begin
					nstate = nstate;
				end
			end
			st_ELLO0:begin
				if(sec_1 == 1'b1)begin
					nstate = st_LLO00;
				end
				else begin
					nstate = nstate;
				end
			end
			st_LLO00:begin
				if(sec_1 == 1'b1)begin
					nstate = st_LO000;
				end
				else begin
					nstate = nstate;
				end
			end
			st_LO000:begin
				if(sec_1 == 1'b1)begin
					nstate = st_O0000;
				end
				else begin
					nstate = nstate;
				end
			end
			st_O0000:begin
				if(sec_1 == 1'b1)begin
					nstate = st_00000;
				end
				else begin
					nstate = nstate;
				end
			end
			st_00000:begin
				if(sec_1 == 1'b1)begin
					nstate = st_0000H;
				end
				else begin
					nstate = nstate;
				end
			end
			st_0000H:begin
				if(sec_1 == 1'b1)begin
					nstate = st_000HE;
				end
				else begin
					nstate = nstate;
				end
			end
			st_000HE:begin
				if(sec_1 == 1'b1)begin
					nstate = st_00HEL;
				end
				else begin
					nstate = nstate;
				end
			end
			st_00HEL:begin
				if(sec_1 == 1'b1)begin
					nstate = st_0HELL;
				end
				else begin
					nstate = nstate;
				end
			end
			st_0HELL:begin
				if(sec_1 == 1'b1)begin
					nstate = st_HELLO;
				end
				else begin
					nstate = nstate;
				end
			end
			default:;
		endcase
	end
end

//三段式:跟随状态输出
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		flag <= 1'b1;
		seg_r0 <= 7'b111_1111;
		seg_r1 <= 7'b111_1111;
		seg_r2 <= 7'b111_1111;
		seg_r3 <= 7'b111_1111;
		seg_r4 <= 7'b111_1111;
		seg_r5 <= 7'b111_1111;
		seg_r6 <= 7'b111_1111;
		seg_r7 <= 7'b111_1111;
	end
	else if(flag)begin
		case(cnt)
			4'd0:seg_r0 <= 7'b100_0000;
			4'd1:seg_r1 <= 7'b100_0111;
			4'd2:seg_r2 <= 7'b100_0111;
			4'd3:seg_r3 <= 7'b000_0110;
			4'd4:seg_r4 <= 7'b000_1001;
			4'd5:seg_r5 <= 7'b111_1111;
			4'd6:seg_r6 <= 7'b111_1111;
			4'd7:seg_r7 <= 7'b111_1111;
			4'd8:flag   <= 1'b0       ;
			default:;
		endcase
	end
	else begin
		case(cstate)
			st_HELLO:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_ELLO0:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_LLO00:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_LO000:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_O0000:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_00000:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_0000H:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_000HE:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_00HEL:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			st_0HELL:begin 
				if(sec_1)begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
				end
				else begin
					{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
				end
			end
			default:;
		endcase
	end
end

assign {seg7,seg6,seg5,seg4,seg3,seg2,seg1,seg0} = {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};

endmodule

③设计顶层模块

fsm_hello_top.v

module fsm_hello_top(
	input  wire  		clk,
	input  wire  		rst_n,
	
	output wire [6:0] seg0,//7位数码管段选信号
	output wire [6:0] seg1,
	output wire [6:0] seg2,
	output wire [6:0] seg3,
	output wire [6:0] seg4,
	output wire [6:0] seg5,
	output wire [6:0] seg6,
	output wire [6:0] seg7
);
wire sec_1;


time_count inst_time_count(
.clk  (clk),   //时钟,50MHZ                        
.rst_n(rst_n), //复位信号,下降沿有效,negative

.sec_1 (sec_1)//1s输出一个脉冲信号             
);

//例化HELLO状态机模块
fsm_hello inst_fsm_hello(
.clk    (clk),//时钟
.rst_n  (rst_n),//复位
.sec_1  (sec_1),//手动脉冲信号
	
.seg0   (seg0),//7位数码管段选信号
.seg1   (seg1),
.seg2   (seg2),
.seg3   (seg3),
.seg4   (seg4),
.seg5   (seg5),
.seg6   (seg6),
.seg7   (seg7)
);

endmodule

④编写仿真文件

fsm_hello_top_tb.v

`timescale 1ns/1ns                  //时间单位和时间精度,两者最多一样大,精度不能大于单位

module fsm_hello_top_tb();

parameter DELAY = 1000000;//1ms

reg        clk_50M;                //wire型改为reg类型,可以起不同的名字
reg        rst_n;  

wire [6:0] seg0;                             
wire [6:0] seg1;	   
wire [6:0] seg2;		
wire [6:0] seg3;		
wire [6:0] seg4;		
wire [6:0] seg5;		
wire [6:0] seg6;		
wire [6:0] seg7;


//激励信号
always #10 clk_50M = ~clk_50M;     //每过10ns,时钟取反,总是执行

//信号初始化
initial begin
	clk_50M = 1'b0;
	rst_n = 1'b0;
	#10;                            //复位信号延迟10纳秒变为无效
	rst_n = 1'b1;
	#(DELAY * 10);
	                        //延迟后停止
	$stop;
end
                               

fsm_hello_top inst_fsm_hello_top(
.clk     (clk_50M),
.rst_n	(rst_n),

.seg0 	(seg0),//7位数码管段选信号
.seg1 	(seg1),
.seg2 	(seg2),
.seg3 	(seg3),
.seg4 	(seg4),
.seg5 	(seg5),
.seg6 	(seg6),
.seg7 	(seg7)
);



endmodule

⑤查看RTL门级电路

在这里插入图片描述

⑥仿真波形

在这里插入图片描述
可以看到每隔1_000_000nsHELLO移动一次。

四.移动速度可控的“HELLO”的自动循环显示

①设计计数器模块

这里要使用三种速度实现数码管切换,计数器模块输出0.5,1,2s脉冲信号
time_count.v

module time_count(
	input  wire clk      ,//时钟,50MHZ                        
	input  wire rst_n    ,//复位信号,下降沿有效,negative
	
	output wire sec_05   ,//0.5s输出一个脉冲信号
	output wire sec_1    ,//1s输出一个脉冲信号
	output wire sec_2     //2s输出一个脉冲信号 
);


parameter MAX_NUM   = 26'd24_999;//记最大数0.5s,25_000_000次 仿真使用0.5ms
parameter MAX_NUM1  = 2         ;

reg [25:0] cnt_05  ;//0.5s计数寄存器
reg [1:0]  cnt_1   ;//1s计数寄存器
reg [1:0]  cnt_2   ;//2s计数寄存器
reg        sec_05_r;
reg        sec_1_r ;
reg        sec_2_r ;


//0.5s计时器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_05 <= 26'd0;
	end
	else if(cnt_05 == MAX_NUM)begin
		cnt_05 <= 26'd0;	
	end
	else begin
		cnt_05 <= cnt_05 + 1'd1;
	end
end

//1s计时器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_1 <= 2'd0;
	end
	else if(cnt_1 < MAX_NUM1)begin
		if(cnt_05 == MAX_NUM)begin
			cnt_1 <= cnt_1 + 1'd1;
		end
		else begin
			cnt_1 <= cnt_1;
		end
	end
	else begin
		cnt_1 <= 2'd0;
	end
end

//2s计时器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_2 <= 2'd0;
	end
	else if(cnt_2 < MAX_NUM1)begin
		if(cnt_1 == MAX_NUM1)begin
			cnt_2 <= cnt_2 + 1'd1;
		end
		else begin
			cnt_2 <= cnt_2;
		end
	end
	else begin
		cnt_2 <= 2'd0;
	end
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 begin
		sec_05_r <= 1'b0;
	end
end


//1s脉冲信号
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		sec_1_r <= 1'b0;
	end
	else if(cnt_1 == MAX_NUM1)begin
		sec_1_r <= 1'b1;
	end
	else begin
		sec_1_r <= 1'b0;
	end
end

//1s脉冲信号
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		sec_2_r <= 1'b0;
	end
	else if(cnt_2 == MAX_NUM1)begin
		sec_2_r <= 1'b1;
	end
	else begin
		sec_2_r <= 1'b0;
	end
end

assign sec_05 = sec_05_r;//当右边改变,立马赋值给左边 assign和always并行
assign sec_1  = sec_1_r ;
assign sec_2  = sec_2_r ;

endmodule 

②设计按键消抖模块

key_debounce.v

module key_debounce(
	input  wire  clk,
	input  wire  rst_n,
	input  wire  key,
	
	output reg   flag,               //判断抖动是否消除的标志信号,0为抖动,1为抖动结束
	output reg   key_value           //消抖后稳定的按键值给到蜂鸣器模块和LED模块
);

//定义20ms延迟计数器,0.2s,1_000_000次
reg [19:0] delay_cnt;

//寄存依次key的值用来判断按键是否消抖成功
reg key_reg;

//按下按键20ms延时计数器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		begin
			key_reg <= 1'b1;                        //复位信号,设置按键无效
			delay_cnt <= 1'b0;                      //计数器设置为0
		end
	else
		begin
			key_reg <= key; 
			if(key_reg ^ key)            //当这一次key值和上一次key值不一样,证明正在抖动
				delay_cnt <= 20'd1000;          //延迟时间20ms(1_000_000) 仿真用20000ns(1000)
			else if(delay_cnt > 0)
				delay_cnt <= delay_cnt - 1;          //没有抖动,开始20ms倒计时
			else
				delay_cnt <= 1'b0;                  
		end
end


//根据延时计数器获取按键状态以及按键值
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		begin
		   flag <= 1'b0;                               //复位信号,设置信号标志为抖动
			key_value <= 1'b1;                          //设置抽样值为1
		end
	else
		begin
			if(delay_cnt == 20'd1)                      //倒计时1_000_000到1
				begin
					flag <= 1'b1;
					key_value <= key;                     //稳定20ms后将key值给到key_value
				end
			else	
				begin
					flag <= 1'b0;
					key_value <= key_value;               //20ms内先不取样
				end
		end
end

endmodule

③设计数码管显示模块

fsm_key_speed_hello.v

module fsm_key_speed_hello(
	input wire       clk   ,//时钟
	input wire       rst_n ,//复位
	input wire       sec_05,//0.5s脉冲信号
	input wire       sec_1 ,//1s脉冲信号
	input wire       sec_2 ,//2s脉冲信号
	input wire [1:0] key   ,//按键
	
	output wire [6:0] seg0,//7位数码管段选信号
	output wire [6:0] seg1,
	output wire [6:0] seg2,
	output wire [6:0] seg3,
	output wire [6:0] seg4,
	output wire [6:0] seg5,
	output wire [6:0] seg6,
	output wire [6:0] seg7
);

reg [3:0] cstate;//现态
reg [3:0] nstate;//次态

//状态划分
localparam st_HELLO = 0;
localparam st_ELLO0 = 1;
localparam st_LLO00 = 2;
localparam st_LO000 = 3;
localparam st_O0000 = 4;
localparam st_00000 = 5;
localparam st_0000H = 6;
localparam st_000HE = 7;
localparam st_00HEL = 8;
localparam st_0HELL = 9;

reg [6:0] seg_r0;
reg [6:0] seg_r1;
reg [6:0] seg_r2;
reg [6:0] seg_r3;
reg [6:0] seg_r4;
reg [6:0] seg_r5;
reg [6:0] seg_r6;
reg [6:0] seg_r7;

reg [3:0] cnt   ;
reg       flag  ;
reg [1:0] speed ;//HELLO移动速度3种

//8个时钟计数器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt <= 4'd0;
	end
	else if(flag == 1'b1)begin
		if(cnt == 4'd8)begin
			cnt <= 1'd0;
		end
		else begin
			cnt <= cnt + 1'd1;
	   end
	end
	else begin
		cnt <=4'd0;
	end
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		speed <= 2'd0;
	end
	else if(key[0])begin
		speed <= 2'd1;
	end
	else if(key[1])begin
		speed <= 2'd2;
	end
	else begin
		speed <= speed;
	end
end

//第一段:现态跟随次态,时序逻辑,非阻塞赋值
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cstate <= st_HELLO;
	end
	else begin
		cstate <= nstate;
	end
end

//第二段:组合逻辑,阻塞赋值
always@(*)begin
	if(!rst_n)begin
		nstate = st_HELLO;
	end
	else begin
		case(speed)
			2'd0:begin
				case(cstate)
					st_HELLO:begin
						if(sec_1 == 1'b1)begin
							nstate = st_ELLO0;
						end
						else begin
							nstate = nstate;
						end
					end
					st_ELLO0:begin
						if(sec_1 == 1'b1)begin
							nstate = st_LLO00;
						end
						else begin
							nstate = nstate;
						end
					end
					st_LLO00:begin
						if(sec_1 == 1'b1)begin
							nstate = st_LO000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_LO000:begin
						if(sec_1 == 1'b1)begin
							nstate = st_O0000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_O0000:begin
						if(sec_1 == 1'b1)begin
							nstate = st_00000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_00000:begin
						if(sec_1 == 1'b1)begin
							nstate = st_0000H;
						end
						else begin
							nstate = nstate;
						end
					end
					st_0000H:begin
						if(sec_1 == 1'b1)begin
							nstate = st_000HE;
						end
						else begin
							nstate = nstate;
						end
					end
					st_000HE:begin
						if(sec_1 == 1'b1)begin
							nstate = st_00HEL;
						end
						else begin
							nstate = nstate;
						end
					end
					st_00HEL:begin
						if(sec_1 == 1'b1)begin
							nstate = st_0HELL;
						end
						else begin
							nstate = nstate;
						end
					end
					st_0HELL:begin
						if(sec_1 == 1'b1)begin
							nstate = st_HELLO;
						end
						else begin
							nstate = nstate;
						end
					end
					default:nstate = st_HELLO;
				endcase
			end
			2'd1:begin
				case(cstate)
					st_HELLO:begin
						if(sec_05 == 1'b1)begin
							nstate = st_ELLO0;
						end
						else begin
							nstate = nstate;
						end
					end
					st_ELLO0:begin
						if(sec_05 == 1'b1)begin
							nstate = st_LLO00;
						end
						else begin
							nstate = nstate;
						end
					end
					st_LLO00:begin
						if(sec_05 == 1'b1)begin
							nstate = st_LO000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_LO000:begin
						if(sec_05 == 1'b1)begin
							nstate = st_O0000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_O0000:begin
						if(sec_05 == 1'b1)begin
							nstate = st_00000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_00000:begin
						if(sec_05 == 1'b1)begin
							nstate = st_0000H;
						end
						else begin
							nstate = nstate;
						end
					end
					st_0000H:begin
						if(sec_05 == 1'b1)begin
							nstate = st_000HE;
						end
						else begin
							nstate = nstate;
						end
					end
					st_000HE:begin
						if(sec_05 == 1'b1)begin
							nstate = st_00HEL;
						end
						else begin
							nstate = nstate;
						end
					end
					st_00HEL:begin
						if(sec_05 == 1'b1)begin
							nstate = st_0HELL;
						end
						else begin
							nstate = nstate;
						end
					end
					st_0HELL:begin
						if(sec_05 == 1'b1)begin
							nstate = st_HELLO;
						end
						else begin
							nstate = nstate;
						end
					end
					default:nstate = st_HELLO;
				endcase
			end
			2'd2:begin
				case(cstate)
					st_HELLO:begin
						if(sec_2 == 1'b1)begin
							nstate = st_ELLO0;
						end
						else begin
							nstate = nstate;
						end
					end
					st_ELLO0:begin
						if(sec_2 == 1'b1)begin
							nstate = st_LLO00;
						end
						else begin
							nstate = nstate;
						end
					end
					st_LLO00:begin
						if(sec_2 == 1'b1)begin
							nstate = st_LO000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_LO000:begin
						if(sec_2 == 1'b1)begin
							nstate = st_O0000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_O0000:begin
						if(sec_2 == 1'b1)begin
							nstate = st_00000;
						end
						else begin
							nstate = nstate;
						end
					end
					st_00000:begin
						if(sec_2 == 1'b1)begin
							nstate = st_0000H;
						end
						else begin
							nstate = nstate;
						end
					end
					st_0000H:begin
						if(sec_2 == 1'b1)begin
							nstate = st_000HE;
						end
						else begin
							nstate = nstate;
						end
					end
					st_000HE:begin
						if(sec_2 == 1'b1)begin
							nstate = st_00HEL;
						end
						else begin
							nstate = nstate;
						end
					end
					st_00HEL:begin
						if(sec_2 == 1'b1)begin
							nstate = st_0HELL;
						end
						else begin
							nstate = nstate;
						end
					end
					st_0HELL:begin
						if(sec_2 == 1'b1)begin
							nstate = st_HELLO;
						end
						else begin
							nstate = nstate;
						end
					end
					default:nstate = st_HELLO;
				endcase
			end
			default:;
		endcase
	end
end

//三段式:跟随状态输出
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		flag <= 1'b1;
		seg_r0 <= 7'b111_1111;
		seg_r1 <= 7'b111_1111;
		seg_r2 <= 7'b111_1111;
		seg_r3 <= 7'b111_1111;
		seg_r4 <= 7'b111_1111;
		seg_r5 <= 7'b111_1111;
		seg_r6 <= 7'b111_1111;
		seg_r7 <= 7'b111_1111;
	end
	else if(flag)begin
		case(cnt)
			4'd0:seg_r0 <= 7'b100_0000;
			4'd1:seg_r1 <= 7'b100_0111;
			4'd2:seg_r2 <= 7'b100_0111;
			4'd3:seg_r3 <= 7'b000_0110;
			4'd4:seg_r4 <= 7'b000_1001;
			4'd5:seg_r5 <= 7'b111_1111;
			4'd6:seg_r6 <= 7'b111_1111;
			4'd7:seg_r7 <= 7'b111_1111;
			4'd8:flag   <= 1'b0       ;
			default:;
		endcase
	end
	else begin
		case(speed)
			2'd0:begin
				case(cstate)
					st_HELLO:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_ELLO0:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_LLO00:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_LO000:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_O0000:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_00000:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_0000H:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_000HE:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_00HEL:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_0HELL:begin 
						if(sec_1)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					default:;
				endcase
			end
			2'd1:begin
				case(cstate)
					st_HELLO:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_ELLO0:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_LLO00:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_LO000:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_O0000:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_00000:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_0000H:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_000HE:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_00HEL:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_0HELL:begin 
						if(sec_05)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					default:;
				endcase
			end
			2'd2:begin
				case(cstate)
					st_HELLO:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_ELLO0:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_LLO00:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_LO000:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_O0000:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_00000:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_0000H:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_000HE:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_00HEL:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					st_0HELL:begin 
						if(sec_2)begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0,seg_r7};
						end
						else begin
							{seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0} <= {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};
						end
					end
					default:;
				endcase
			end
			default:;
		endcase
	end
end

assign {seg7,seg6,seg5,seg4,seg3,seg2,seg1,seg0} = {seg_r7,seg_r6,seg_r5,seg_r4,seg_r3,seg_r2,seg_r1,seg_r0};

endmodule

④设计顶层模块

fsm_key_speed_hello_top.v

module fsm_key_speed_hello_top(
	input  wire  		clk  ,
	input  wire  		rst_n,
	input  wire [1:0] key  ,
	
	output wire [6:0] seg0 ,//7位数码管段选信号
	output wire [6:0] seg1 ,
	output wire [6:0] seg2 ,
	output wire [6:0] seg3 ,
	output wire [6:0] seg4 ,
	output wire [6:0] seg5 ,
	output wire [6:0] seg6 ,
	output wire [6:0] seg7 
);
wire       sec_05   ;
wire       sec_1    ;
wire       sec_2    ;
wire [1:0] flag     ;
wire [1:0] key_value;

key_debounce inst_key_debounce(
.clk         (clk    ),
.rst_n       (rst_n  ),
.key         (key[0] ),

.flag        (flag[0]),               //判断抖动是否消除的标志信号,0为抖动,1为抖动结束
.key_value   (key_value[0])           //消抖后稳定的按键值给到蜂鸣器模块和LED模块
);

key_debounce inst_key_debounce1(
.clk         (clk    ),
.rst_n       (rst_n  ),
.key         (key[1] ),

.flag        (flag[1]),               //判断抖动是否消除的标志信号,0为抖动,1为抖动结束
.key_value   (key_value[1])           //消抖后稳定的按键值给到蜂鸣器模块和LED模块
);

time_count inst_time_count(
.clk  (clk)    ,   //时钟,50MHZ                        
.rst_n(rst_n)  , //复位信号,下降沿有效,negative

.sec_05(sec_05),//0.5s输出一个脉冲信号
.sec_1 (sec_1) ,//1s输出一个脉冲信号
.sec_2 (sec_2)   //2s输出一个脉冲信号             
);

//例化HELLO状态机模块
fsm_key_speed_hello inst_fsm_key_speed_hello(
.clk    (clk   ),//时钟
.rst_n  (rst_n ),//复位
.sec_05 (sec_05),
.sec_1  (sec_1 ),
.sec_2  (sec_2 ),
.key    ({~key_value[1]&&flag[1],~key_value[0]&&flag[0]}),
	
.seg0   (seg0  ),//7位数码管段选信号
.seg1   (seg1  ),
.seg2   (seg2  ),
.seg3   (seg3  ),
.seg4   (seg4  ),
.seg5   (seg5  ),
.seg6   (seg6  ),
.seg7   (seg7  )
);

endmodule

⑤查看RTL门级电路

在这里插入图片描述

⑥编写仿真模块

fsm_key_speed_hello_top_tb.v

`timescale 1ns/1ns                  //时间单位和时间精度,两者最多一样大,精度不能大于单位

module fsm_key_speed_hello_top_tb();

parameter DELAY = 1000000;//1ms

reg        clk_50M;                //wire型改为reg类型,可以起不同的名字
reg        rst_n;  
reg  [1:0] key;

wire [6:0] seg0;                             
wire [6:0] seg1;	   
wire [6:0] seg2;		
wire [6:0] seg3;		
wire [6:0] seg4;		
wire [6:0] seg5;		
wire [6:0] seg6;		
wire [6:0] seg7;


//激励信号
always #10 clk_50M = ~clk_50M;     //每过10ns,时钟取反,总是执行

//信号初始化
initial begin
	clk_50M = 1'b0 ;
	rst_n   = 1'b0 ;
	#10            ;                //复位信号延迟10纳秒变为无效
	rst_n   = 1'b1 ;
	key     = 2'b11;					  //以速度1ms移动
	#(DELAY * 4)   ;                //以速度1ms延迟4ms
	key     = 2'b10;					  //按下KEY0键,以速度0.5ms移动
	#(DELAY * 4)   ;                //以速度0.5ms延迟4ms
	key     = 2'b11;					  //弹起KEY0键,以速度1ms移动
	#(DELAY * 4)   ;                //以速度1ms延迟4ms
	key     = 2'b01;                //按下KEY1键,以速度2ms移动
	#(DELAY * 4)   ;                //以速度2ms延迟4ms
	                                //延迟后停止
	$stop;
end
                               

fsm_key_speed_hello_top inst_fsm_key_speed_hello_top(
.clk     (clk_50M),
.rst_n	(rst_n),
.key     (key  ),

.seg0 	(seg0),//7位数码管段选信号
.seg1 	(seg1),
.seg2 	(seg2),
.seg3 	(seg3),
.seg4 	(seg4),
.seg5 	(seg5),
.seg6 	(seg6),
.seg7 	(seg7)
);



endmodule

⑦仿真波形

在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-14 10:06:25  更:2022-05-14 10:06:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:32:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码