step fpga上实现呼吸灯和交通灯

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_33946416/article/details/96465014

呼吸灯

呼吸灯:我们将通过脉宽调制技术来实现“呼吸灯”,实现LED的亮度由最暗逐渐增加到最亮,再逐渐变暗的过程。 脉冲宽度调制。它是利用微控制器的数字输出调制实现,是对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等众多领域。
硬件设计
在这里插入图片描述
在这里插入图片描述
实现原理:如上图所示,脉冲信号的周期为T,高电平脉冲宽度为t,占空比为t/T。为了实现PWM脉宽调制,我们需要保持周期T不变,调整高电平脉宽t的时间,从而改变占空比。

当t = 0时,占空比为0%,因为我们的LED硬件为低电平点亮,所以为最亮的状态。
当t = T时,占空比为100%,LED灯为最暗(熄灭)的状态。
结合呼吸灯的原理,整个呼吸的周期为最亮→最暗→最亮的时间,即t的值的变化:0→T→0逐渐变化,这个时间应该为2s。
在这里插入图片描述
呼吸灯设计要求呼吸的周期为2s,也就是说LED灯从最亮的状态开始,第一秒时间内逐渐变暗,第二秒的时间内再逐渐变亮,依次进行。
本设计中需要两个计数器cnt1和cnt2,cnt1随系统时钟同步计数(系统时钟上升沿时cnt1自加1)范围为0-T,cnt2随cnt1的周期同步计数(cnt1等于T时,cnt2自加1)范围也是0-T,这样每次cnt1在0-T的计数时,cnt2为一个固定值,相邻cnt1计数周期对应的cnt2的值逐渐增大,我们将cnt1计数0~T的时间作为脉冲周期,cnt2的值作为脉冲宽度,则占空比 = cnt2/T,占空比从0%到100%的时间 = cnt2*cnt1 = T^2 = 1s = 12M个系统时钟,T = 2400,我们定义CNT_NUM = 2400作为两个计数器的计数最大值。
在这里插入图片描述
2.verilog程序设计

module breath_led(clk,rst,led);
 
	input clk;             //系统时钟输入
	input rst;             //复位输出
	output led;            //led输出
 
	reg [24:0] cnt1;       //计数器1
	reg [24:0] cnt2;       //计数器2
	reg flag;              //呼吸灯变亮和变暗的标志位
 
	parameter   CNT_NUM = 2400;	//计数器的最大值 period = (2400^2)*2 = 24000000 = 2s
	//产生计数器cnt1
	always@(posedge clk or negedge rst) begin 
		if(!rst) begin
			cnt1<=13'd0;
			end 
        else if(cnt1>=CNT_NUM-1) 
				cnt1<=1'b0;
		     else 
                cnt1<=cnt1+1'b1; 
		end
 
	//产生计数器cnt2
	always@(posedge clk or negedge rst) begin 
		if(!rst) begin
			cnt2<=13'd0;
			flag<=1'b0;
			end 
        else if(cnt1==CNT_NUM-1) begin //当计数器1计满时计数器2开始计数加一或减一
			if(!flag) begin            //当标志位为0时计数器2递增计数,表示呼吸灯效果由暗变亮
				if(cnt2>=CNT_NUM-1)    //计数器2计满时,表示亮度已最大,标志位变高,之后计数器2开始递减
					flag<=1'b1;
				else
					cnt2<=cnt2+1'b1;
				end
			else begin
				if(cnt2<=0)      //当标志位为高时计数器2递减计数
					flag<=1'b0;		   //计数器2级到0,表示亮度已最小,标志位变低,之后计数器2开始递增
				else 	
					cnt2<=cnt2-1'b1;
				end		
 
			end
		else 
			cnt2<=cnt2;                //计数器1在计数过程中计数器2保持不变
		end
 
	//比较计数器1和计数器2的值产生自动调整占空比输出的信号,输出到led产生呼吸灯效果
	assign	led = (cnt1<cnt2)?1'b0:1'b1;
 
endmodule

交通灯

1.有限状态机
FSM:一种由寄存器组和组合逻辑构成硬件时序电路,堪称FPGA硬件设计的灵魂。
在同一时钟跳变沿由当前状态(现态)转移到下一状态(次态)
究竟转向哪一状态不但取决于各个输入值,还取决于当前状态。
在时钟跳变沿时刻进行复杂组合逻辑控制
包含时序、组合逻辑电路
非常有用模型,可以模拟大部分事物。如按键命令、自动门控制、通信时序等

1)状态总数state是有限的
2)任何一个时刻,只能处于一个状态
3)在条件满足时,由一个状态转变到另一个状态

分类:1)moore型:输出逻辑只由当前状态决定
下一个状态 = F(当前状态,输入信号);
输出信号 = G(当前状态);
在这里插入图片描述
2)mealy型:输出逻辑不但与当前状态有关还与当前输入值有关
下一个状态 = F(当前状态,输入信号);
输出信号 = G(当前状态,输入信号);
在这里插入图片描述
有限状态机要素
状态:当前状态、次态
输入:触发状态转移的输入条件
输出:输入所触发的动作

有限状态机的样式
一段式
整个状态机在一个always模块中,模块中既包含状态转移也含有组合逻辑输入输出。
二段式
状态机使用两个always描述,一个采用同步时序实现状态转移,一个采用组合逻辑判断转移条件和逻辑输出。需要定义两个状态——现态和次态
三段式
状态机使用三个always描述,一个采用同步时序实现状态转移,一个采用组合逻辑判断转移条件,一个实现状态同步输出
2.交通灯的设计
设计流程:
在这里插入图片描述
上图为十字路口交通示意图分之路与主路,要求如下: * 交通灯主路上绿灯持续15s的时间,黄灯3s的时间,红灯10s的时间; * 交通灯支路上绿灯持续7s的时间, 黄灯持续3秒的时间,红灯18秒的时间;
在这里插入图片描述
根据上述要求,状态机设计框架分析如下: * S1:主路绿灯点亮,支路红灯点亮,持续15s的时间; * S2:主路黄灯点亮,支路红灯点亮,持续3s的时间; * S3:主路红灯点亮,支路绿灯点亮,持续10s的时间; * S4:主路红灯点亮,支路黄灯点亮,持续3s的时间;
在这里插入图片描述
程序设计
时钟分频:

module divide
(
	//INPUT
	clk			,
	rst_n			,
	//OUTPUT
	clkout			
);
	//*******************
	//DEFINE PARAMETER
	//*******************
	parameter			WIDTH	=	3;
	parameter			N		=	5;
 
	//*******************
	//DEFINE INPUT
	//*******************
	input 	clk,rst_n;     
 
    //*******************
	//DEFINE OUTPUT
	//*******************
	output	clkout;
 
	//********************
	//OUTPUT ATTRIBUTE
	//********************
	//REGS
	reg 	[WIDTH-1:0]		cnt_p,cnt_n;
	reg						clk_p,clk_n;
 
	assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p;
 
	//Sequential logic style
	always @ (posedge clk)
		begin
			if(!rst_n)
				cnt_p<=0;
			else if (cnt_p==(N-1))
				cnt_p<=0;
			else cnt_p<=cnt_p+1;
		end
 
	always @ (negedge clk)
		begin
			if(!rst_n)
				cnt_n<=0;
			else if (cnt_n==(N-1))
				cnt_n<=0;
			else cnt_n<=cnt_n+1;
		end
 
	always @ (posedge clk)
		begin
			if(!rst_n)
				clk_p<=0;
			else if (cnt_p<(N>>1))  
				clk_p<=0;
			else 
				clk_p<=1;
		end
 
	always @ (negedge clk)
		begin
			if(!rst_n)
				clk_n<=0;
			else if (cnt_n<(N>>1))  
				clk_n<=0;
			else 
				clk_n<=1;
		end
endmodule     

交通灯通过利用有限状态机的三段式模型的程序设计:

module traffic
(
	clk		,    //时钟
	rst_n		,    //复位
	out		     //三色led代表交通灯
);
 
	input 	clk,rst_n;     
	output	reg[5:0]	out;
 
	parameter      	S1 = 4'b00,    //状态机状态编码
			S2 = 4'b01,
			S3 = 4'b10,
			S4 = 4'b11;
 
	parameter	time_s1 = 4'd15, //计时参数
			time_s2 = 4'd3,
			time_s3 = 4'd10,
			time_s4 = 4'd3;
	//交通灯的控制
	parameter	led_s1 = 6'b101011, // LED2 绿色 LED1 红色
			led_s2 = 6'b110011, // LED2 蓝色 LED1 红色
			led_s3 = 6'b011101, // LED2 红色 LED1 绿色
			led_s4 = 6'b011110; // LED2 红色 LED1 蓝色
 
	reg 	[3:0] 	timecont;
	reg 	[1:0] 	cur_state,next_state;  //现态、次态
 
	wire			clk1h;  //1Hz时钟
 
	//产生1秒的时钟周期
	divide #(.WIDTH(32),.N(12000000)) CLK1H (
					.clk(clk),
					.rst_n(rst_n),
					.clkout(clk1h));
	//第一段 同步逻辑 描述次态到现态的转移
	always @ (posedge clk1h or negedge rst_n)
	begin
		if(!rst_n) 
			cur_state <= S1;
        else 
			cur_state <= next_state;
	end
	//第二段 组合逻辑描述状态转移的判断
	always @ (cur_state or rst_n or timecont)
	begin
		if(!rst_n) begin
		        next_state = S1;
			end
		else begin
			case(cur_state)
				S1:begin
					if(timecont==1) 
						next_state = S2;
					else 
						next_state = S1;
				end
 
                S2:begin
					if(timecont==1) 
						next_state = S3;
					else 
						next_state = S2;
				end
 
                S3:begin
					if(timecont==1) 
						next_state = S4;
					else 
						next_state = S3;
				end
 
                S4:begin
					if(timecont==1) 
						next_state = S1;
					else 
						next_state = S4;
				end
 
				default: next_state = S1;
			endcase
		end
	end
	//第三段  同步逻辑 描述次态的输出动作
	always @ (posedge clk1h or negedge rst_n)
	begin
		if(!rst_n==1) begin
			out <= led_s1;
			timecont <= time_s1;
			end 
		else begin
			case(next_state)
				S1:begin
					out <= led_s1;
					if(timecont == 1) 
						timecont <= time_s1;
					else 
						timecont <= timecont - 1;
				end
 
				S2:begin
					out <= led_s2;
					if(timecont == 1) 
						timecont <= time_s2;
					else 
						timecont <= timecont - 1;
				end
 
				S3:begin
					out <= led_s3;
					if(timecont == 1) 
						timecont <= time_s3;
					else 
						timecont <= timecont - 1;
				end
 
				S4:begin
					out <= led_s4;
					if(timecont == 1) 
						timecont <= time_s4;
					else 
						timecont <= timecont - 1;
				end
 
				default:begin
					out <= led_s1;
					end
			endcase
		end
	end
endmodule

猜你喜欢

转载自blog.csdn.net/qq_33946416/article/details/96465014