FPGA-数码管

DE2-115 开发板
Cyclone IV EP4CE115F29器件
在这里插入图片描述

一、任务要求

  1. 闪烁的数码管
    在HEX0上连续循环地显示数字0~9,每秒刷新一次显示。使用计数器产生1 s的时间间隔,这个计数器的时钟由DE2-115平台上的50 MHz时钟提供。注意:这个设计中只允许使用DE2-115平台上的50 MHz时钟,而不允许使用其他时钟,并保证所有的触发器都直接使用这个50 MHz时钟。

  2. 用移位寄存器与FSM实现“HELLO”的循环显示
    使用移位寄存器并结合FSM实现DE2-115平台上的“HELLO”循环显示。在HEX7~HEX0上循环显示“HELLO”,使所有字母从右向左移动,每秒移动一次,

  3. 移动速度可控的“HELLO”的自动循环显示
    用KEY0作为低电平有效同步清除输入
    当KEY1按下时,移动速度增加一倍;
    当KEY2按下时,移动速度减小一半。KEY2和KEY1是经过去抖处理的,能够产生一个精确的脉冲,但脉冲的长度是任意的。

二、问题分析

DE2-115 配有八个七段数码管。它们被分成两组,每组四个,用来作为数字 显示用。正如图 所示,七段数码管的每个引脚(共阳模式)均连接到 Cyclone IV E FPGA。FPGA 输出低电压的时候,对应的字码段点亮,反之则熄灭。每个数 码管的字段都从 0 到 6 依次编号
在这里插入图片描述

所以将8个7位寄存器按流水线的形式排列

output reg [56:0] hex

三、代码实现

在这里插入图片描述

1. 任务一

seg_led_09模块

/*
	闪烁的数码管 
	在HEX0上连续循环地显示数字0~9,
	每秒刷新一次显示。
*/
module seg_led_09(
	input wire clk,
	input wire rst_n,
	input wire sec_1,
	
	output reg [55:0] hex  //对于任务一,其实完全不用56位宽,在HEX0上连续循环地显示数字0~9 
						  //  7位就可,只是因为我的任务都是同一个项目完成,                                      
                          // 任务二,三都会用到所有数码管,所以就用56位宽
);

reg [3:0] value;

//每次通知信号sec_05到达时,数码管计数加1
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		value<=4'h0;
	end
	else if(sec_1)begin
		if(value<4'h9)
			value<=value+1'h1;
		else
			value<=4'h0;
	end
	else
		value<=value;
end
//根据数码管显示的数值,控制段选信号
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		hex<=56'b0;
	else begin
		case(value)    
			  4'h0:    hex <= {
    
    {49{1'b1}},7'b100_0000};
	        4'h1:    hex <= {
    
    {49{1'b1}},7'b111_1001};
	        4'h2:    hex <= {
    
    {49{1'b1}},7'b010_0100};
	        4'h3:    hex <= {
    
    {49{1'b1}},7'b011_0000};
	        4'h4:    hex <= {
    
    {49{1'b1}},7'b001_1001};
	        4'h5:    hex <= {
    
    {49{1'b1}},7'b001_0010};
	        4'h6:    hex <= {
    
    {49{1'b1}},7'b000_0010};
	        4'h7:    hex <= {
    
    {49{1'b1}},7'b111_1000};
	        4'h8:    hex <= {
    
    {49{1'b1}},7'b000_0000};
	        4'h9:    hex <= {
    
    {49{1'b1}},7'b001_0000};
	      	default : hex <= {
    
    {
    
    49{
    
    1'b1}},7'b100_0000};
		endcase
	end
end		
endmodule

time_count模块

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


parameter MAX_NUM=26'd49_999_999;//记最大数,时间1s

reg [25:0] cnt;//计数寄存器
//1s计时
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt<=26'd0;
	end
	else if(cnt<MAX_NUM)begin
		cnt<=cnt+1'd1;
	end
	else
	   cnt<=26'd0;

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


endmodule

digital_tube_top模块

module digital_tube_top(
	input wire clk,
	input wire rst_n,
	input wire [1:0] key,
	output	wire	[56:0]	hex


);

wire sec_1;
wire [1:0] flag;
wire [1:0] key_value;
//每隔1s产生一个时钟周期的脉冲信号
time_count inst_time_count(
	.clk		(clk)  ,  //50MHz时钟信号
	.rst_n	(rst_n),  //复位信号
	.sec_1	(sec_1)//一个时钟周期的脉冲信号
);

//每当脉冲信号到达时,使数码管显示的数值加1
seg_led_09 inst_seg_led_09(
	.clk		(clk),
	.rst_n	(rst_n),
	.sec_1	(sec_1),

	.hex		(hex)

);

endmodule

效果展示
请添加图片描述

2. 任务二

在这里插入图片描述

/*
	循环显示的“HELLO”  
	设计一个电路实现在HEX7~HEX0上循环显示“HELLO”,
	使所有字母从右向左移动,每秒移动一次,
*/

module seg_led_r_l(
	input wire clk,
	input wire rst_n,
	input wire sec_1,
	
	output reg [55:0] hex

);

//控制数码管位选信号(注:低电平有效),选中所有的数码管
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		hex<=56'b1111111_1111111_1111111_0001001_0000110_1000111_1000111_1000000;
	end
	else begin
		if(sec_1)
		 hex<={
    
    hex[48:0],hex[55:49]};
		 else 
		 hex<=hex;
	end

end


		
endmodule

digital_tube_top

module digital_tube_top(
	input wire clk,
	input wire rst_n,
	input wire [1:0] key,
	output	wire	[56:0]	hex


);

wire sec_1;
wire [1:0] flag;
wire [1:0] key_value;
//每隔1s产生一个时钟周期的脉冲信号
time_count inst_time_count(
	.clk		(clk)  ,  //50MHz时钟信号
	.rst_n	(rst_n),  //复位信号
	.sec_1	(sec_1)//一个时钟周期的脉冲信号
);

seg_led_r_l inst_seg_led_r_l(
.clk      (clk  ),
.rst_n    (rst_n),
.sec_1	(sec_1),
           
.hex      (hex  )

);

endmodule


效果展示
请添加图片描述

3. 任务三

在这里插入图片描述
seg_led_FSM模块

module seg_led_FSM(
	input wire clk,
	input wire rst_n,
	input wire [1:0] key,
	
	output reg [55:0] hex
  
);


parameter RATE1=99_999_999;//2s
parameter RATE2=49_999_999;//1s
parameter RATE3=12_499_999;//0.25s


reg [26:0] cnt;//计数寄存器
reg flag1;//key0是否按下标志
reg flag2;//key1是否按下标志
reg [26:0] c_state,n_state;
reg [1:0] key_r;

always@(posedge clk,negedge rst_n)begin
	if(!rst_n)begin
		flag1<=1'b0;
		flag2<=1'b0;
	end
	else begin
		case(key)
			2'b00:begin
						flag1<=1'b0;
						flag2<=1'b0;
					end
			2'b10:begin
						flag1<=1'b1;
						flag2<=1'b0;
					end
			2'b01:begin
						flag1<=1'b0;
						flag2<=1'b1;
					end
			2'b11:begin
						flag1<=1'b0;
						flag2<=1'b0;
					end
			default:begin
						flag1<=1'b0;
						flag2<=1'b0;
					  end
		endcase
	end
						
end

always@(posedge clk,negedge rst_n)begin
	if(!rst_n)
		c_state<=RATE2;
	else
		c_state<=n_state;

end

always@(posedge clk,negedge rst_n)begin
	if(!rst_n)
		n_state<=RATE2;
	else 
		case(c_state)
			RATE1:begin
						if(flag1)
							n_state<=RATE2;
						else if(flag2)
							n_state<=RATE1;
						else
							n_state<=n_state;
					end
			
			RATE2:begin
						if(flag1)
							n_state<=RATE3;
						else if(flag2)
							n_state<=RATE1;
						else
							n_state<=n_state;
					end
			
			RATE3:begin
						if(flag1)
							n_state<=RATE3;
						else if(flag2)
							n_state<=RATE2;
						else
							n_state<=n_state;
					end
			
			default:n_state<=n_state;
		endcase
end



//计时
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt<=27'd0;
	end
	else if(cnt<c_state)begin
		cnt<=cnt+1'd1;
	end
	else
	   cnt<=27'd0;

end
//控制数码管位选信号(注:低电平有效),选中所有的数码管
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		hex<=56'b1111111_1111111_1111111_0001001_0000110_1000111_1000111_1000000;
	end
	else begin
		if(cnt==c_state)
			hex<={
    
    hex[48:0],hex[55:49]};
		else 
		 hex<=hex;
	end

end
endmodule

按键消抖模块

module key_debounce(
	input 	wire	clk,
	input 	wire 	rst_n,
	input 	wire 	key,
	
	output 	reg 	flag,// 0抖动, 1抖动结束
	output 	reg	key_value//key抖动结束后的值
);

parameter MAX_NUM = 20'd1_000_000;

reg [19:0] delay_cnt;//1_000_000

reg key_reg;//key上一次的值

always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		key_reg <= 1;
		delay_cnt <= 0;
	end
	
	else begin
		key_reg <= key;
		//当key为1 key 为0 表示按下抖动,开始计时
		if(key_reg  != key  ) begin 
		   delay_cnt <= MAX_NUM ;
		end
		else begin
		    if(delay_cnt > 0)
				delay_cnt <= delay_cnt -1;
			else
				delay_cnt <= 0;
		end
	end
end


//当计时完成,获取key的值
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		flag <= 0;
		key_value <= 1;
	end

	else begin
		
		// 计时完成 处于稳定状态,进行赋值
		if(delay_cnt == 1) begin
			flag <= 1;
			key_value <= key;
		end
		else begin
			flag <= 0;
			key_value <= key_value;
		end
	end
end

endmodule

digital_tube_top模块

module digital_tube_top(
	input wire clk,
	input wire rst_n,
	input wire [1:0] key,
	output	wire	[56:0]	hex


);

wire sec_1;
wire [1:0] flag;
wire [1:0] key_value;

key_debounce inst_key_debounce1(
.clk      (clk      ),     //1s震荡50_000_000次
.rst_n    (rst_n    ),
.key      (key[0]      ),
           
.flag     (flag[0]     ),      //判断抖动是否消除的标志信号,0为抖动,1为抖动消除
.key_value(key_value[0])  
);
key_debounce inst_key_debounce2(
.clk      (clk      ),     //1s震荡50_000_000次
.rst_n    (rst_n    ),
.key      (key[1]      ),
           
.flag     (flag[1]     ),      //判断抖动是否消除的标志信号,0为抖动,1为抖动消除
.key_value(key_value[1])  
);

seg_led_FSM inst_seg_led_FSM(
.clk    (clk),
.rst_n  (rst_n),
.key    ({
    
    flag[1]&&key_value[1],flag[0]&&key_value[0]}),

.hex    (hex)
  
);

endmodule

效果展示
请添加图片描述

猜你喜欢

转载自blog.csdn.net/Mouer__/article/details/124717319