EDA设计(verilog)—— 七段管+字符串位移2速度控制

题目描述:设计移动速度可控的 HELLO 自动循环显示,当KEY1 按下后,循环速度为每秒移动 1 个七段管的位置,按下 KEY0 后,速度减慢,4 秒移动一个七段管的位置。用 FSM 设计实现。(系统外部时钟50 MHz。)

题目分析

对于七段管显示字符串的移动,上篇博客已经说过,这里就不做赘述。说一下新的地方,这次的要求是使用FSM(有限状态机)设计实现。对于题目里的状态表示可以有两个思考维度,

  1. 状态用来表示速度的快慢,速度的快慢用两个按钮表示时,可以设置三种基本状态,快速,慢速,以及输入错误,通过三种状态的改变去实现不同的文字移动速度。
  2. 状态用来表示hello的在七段管中的位置,这样,状态数目就和七段管的数量一样了,再通过这个状态来控制显示。

我认为这两种想法都是对的。这篇文章使用的是第一种理解方式。

综合代码

module hello_show(
	// 基本控制
	input clk50, // clk50 为输入50Mhz系统外部时钟
	input reset, // reset 为复位信号
	input key1,  // 控制移动速度 1m/s
	input key0,  // 控制移动速度 0.25m/s
	
	// 输入控制
	input ifinput,  // 是否正在输入, 定义为低位时表示正在输入
	input[2:0] inp, // input_position 输入的管子位置 2^3 = 8 从0-7 一共表示8个管子 
	input[6:0] inv, // input_value 输入的字符型
	
	// 输出控制
	output reg[55:0] out, // 1-8 一共8个七段管的输出位置(56位)
	output reg err,      // 错误标志位
	
	// 状态表示
	output reg[1:0] state
);

wire clk1;      // 接收内部时钟产生的1Hz信号

divclk1hz clock1(
	.reset(ifinput),  // 如果用户进行了输入,那么我们就重新开始计数
	.clk50(clk50),    // 传入的基本信号,用于做分频
	.clk1(clk1),       // 产生的1Hz信号
	.state(state)
);

// 控制状态转移
always @(key1 or key0) begin
	if (key1 ^ key0) begin  // 当两个按键有且只有一个被按下
		state <= key1;   // 用其中一个去表示状态就可以 
	end
	else begin
		state <= 2'b11;  // 否则的话进入输入错误模式
	end
end


always @(posedge clk1 or negedge ifinput) begin
	if (!ifinput) begin  // 如果是在输入状态下就进行寄存的复制
		case(inp)    // 根据用户要求改变的位置进行赋值。
			 0: out[6:0]   <= inv;
			 1: out[13:7]  <= inv;
			 2: out[20:14] <= inv;
			 3: out[27:21] <= inv;
			 4: out[34:28] <= inv;
			 5: out[41:35] <= inv;
			 6: out[48:42] <= inv;
			 7: out[55:49] <= inv;
		 endcase
		 
	end else begin
		out <= {out[6:0], out[55:7]};// 进行向右移动 
		err <= 0;
	end 
end

endmodule



/** 分频模块,每数到25M改变一个让一个输出寄存器clk1里的值发生反转 */
module divclk1hz(reset,clk50,clk1,state);
input clk50,reset; //clk50 为输入50Mhz 信号,reset 为复位信号
input[1:0] state;
output reg clk1;         // 新产生的1hz 信号
integer i=0;             //50Mhz 频率下,周期计数器
reg[1:0] prestate;


always@(negedge reset or posedge clk50) begin
	prestate <= state;
	if(!reset) begin
		i = 0;
		clk1 = 0;
	end else if(!prestate==state) begin
		i = 0;
		clk1 = 0;
	end else if((state==0) && (i>=40)) begin  // 这里的40只是便于测试,2S的时间要用 100M来表示
		i=0; clk1=~clk1;
	end else if((state ==1) && (i>= 10)) begin// 这里的10只是便于测试,0.5S的时间要用 25M来表示
		i=0; clk1=~clk1;
	end else if(state!=2'b11) begin
		i = i + 1;
	end
end
endmodule

测试代码

`timescale 10 ns/ 1 ns

module hello_show_vlg_tst();
reg clk50;
reg ifinput;
reg [2:0] inp;
reg [6:0] inv;
reg key0;
reg key1;
reg reset;                                    
wire err;
wire [55:0]  out;
wire [1:0] state;                 
hello_show i1 (
	.clk50(clk50),
	.err(err),
	.ifinput(ifinput),
	.inp(inp),
	.inv(inv),
	.key0(key0),
	.key1(key1),
	.out(out),
	.reset(reset),
	.state(state)
);


/** 用于测试时钟 **/
//reg[1:0] state;  
//wire clk1;
//divclk1hz clock1(
//	.reset(ifinput),  // 如果用户进行了输入,那么我们就重新开始计数
//	.clk50(clk50),    // 传入的基本信号,用于做分频
//	.clk1(clk1),       // 产生的1Hz信号
//	.state(state)
//);


initial begin
	// 使用快速模式, 初始化时钟
	key0 = 0; key1 = 1; clk50 = 0; 
//	state = 1;
	// 给每一个七段管子赋值,这里为了让大家看的清楚,将8个管子的值赋值为了"88 88888","hello__"需要跟改为
	/**
		1001000
		0110000
		1110001
		1110001
		1100010
		1110111
		1110111
		1110111
	*/
	#00; ifinput = 1; inp = 0; inv=7'b0000000;
	#10 ifinput = 0;
	#10; ifinput = 1; inp = 1; inv=7'b0000000;
	#10 ifinput = 0;
	#10; ifinput = 1; inp = 2; inv=7'b1111111;
	#10 ifinput = 0;
	#10; ifinput = 1; inp = 3; inv=7'b0000000;
	#10 ifinput = 0;
	#10; ifinput = 1; inp = 4; inv=7'b0000000;
	#10 ifinput = 0;
	#10; ifinput = 1; inp = 5; inv=7'b0000000;
	#10 ifinput = 0;
	#10; ifinput = 1; inp = 6; inv=7'b0000000;
	#10 ifinput = 0;
	#10; ifinput = 1; inp = 7; inv=7'b0000000;
	#10 ifinput = 0; #1 ifinput = 1;  // 赋值过程结束
	
	// 经过900 个单位时间的等待,观察输出的右移过程
	#899;
	// 进入慢速模式
	key0 = 1; key1 = 0; #1;
	// 进入错误模式
	#899 key0 = 1; key1 = 1; #1;
	// 返回快速模式
	#899 key0 = 0; key1 = 1; #1;
	// 再经过600 个单位时间的等待,暂停运行
	#600 $stop;
end
always begin
	#1 clk50 =~ clk50;
end                                        
endmodule

4、效果展示

在这里插入图片描述
从图中可以看到随着时间的变化,高电平在寄存器上的位置发生了改变,(表示这对于七段管的里的文字正在发生转移)。当状态从01(高速状态) 变为00(低速状态),可以看到寄存器里的值变化时间发生了明显延长,当状态从00 变化到11(输入错误状态)时,寄存器上的值不发生改变,最后,当状态再次变为01(高速状态),寄存器里的值又开始发生转移。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值