汽车尾灯自动控制系统fpga

module carlight(sw,clk,rst_n,led);
	 input [3:0] sw;//拨码开关控制
	 input clk;//50MHz时钟
	 input rst_n;//sw8为1时正常工作
	 output reg [5:0] led;//两个三色led
	 
	 
	 wire clk_1Hz;
	 //分频得到频率为1khz的时钟
	divide #(.WIDTH(32),.N(25000000))u2(         
		.clk(clk),
		.rst_n(rst_n),                  
		.clkout(clk_1Hz)
		);
		
	parameter[3:0]
	START=4'b0000,//初始状态
	S1=4'b0001,//前行
	S2=4'b0011,//左转
	S3=4'b0101,//右转
	S4=4'b1001,//临时停车或故障
	S5=4'b1111;//倒车
	
	reg [3:0]
	current_state,
	next_state;
	
	initial
	begin
	current_state<=4'b0000;
	next_state<=4'b0000;
	end
		
	

	
		
		//第一个always块,描述在时钟驱动下次态迁移到现态。
	always @ (posedge clk_1Hz or negedge rst_n)  //异步复位
		if (!rst_n)
			current_state<= START;
		else
			current_state<= next_state; //注意,使用非阻塞赋值
 
		//第二个always块,描述状态的转移关系
	always @ (current_state or sw)   //电平触发,将现态作为敏感信号
		begin
			case (current_state)
				START: case(sw)
							S1: next_state = S1;  
							S2: next_state = S2;  
							S3: next_state = S3;
							S4: next_state = S4;
							S5: next_state = S5;
							default: next_state = START;
						endcase
				S1: next_state = START ;  //阻塞赋值
				S2: next_state = START;  //阻塞赋值
				S3: next_state = START;
				S4: next_state = START;
				S5: next_state = START;
				default: next_state = START; //对多余状态的处理
			endcase
		end
 
		//第三个always块,描述每个状态对应的输出
	always @ (current_state)
		begin
			led=6'b111111;
			case (current_state)
				START: led = 6'b111111; //对输出进行赋值
				S1: led = 6'b111111;
				S2: led = 6'b011111;
				S3: led = 6'b111011;
				S4: led = 6'b011011;
				S5: led = 6'b110011;
				default: led = 6'b111111;// 避免综合出锁存器。
			endcase
		end
		
endmodule 
module divide ( clk,rst_n,clkout);
	input clk,rst_n; //输入信号,其中 clk 连接到 FPGA 的 M1 脚,频率为 50MHz
	output clkout; //输出信号,可以连接到 LED 观察分频的时钟
	//parameter 是 verilog 里常数语句
	parameter WIDTH = 3; //计数器的位数,计数的最大值为 2**WIDTH-1
	parameter N = 5; //分频系数,请确保 N < 2**WIDTH-1,否则计数会溢出
	reg [WIDTH-1:0] cnt_p,cnt_n; //cnt_p 为上升沿触发时的计数器,cnt_n 为下降沿触发时的计数器
	reg clk_p,clk_n; //clk_p 为上升沿触发时分频时钟,clk_n 为下降沿触发时分频时钟
	//上升沿触发时计数器的控制
	always @ (posedge clk or negedge rst_n ) //posedge 和 negedge 是 verilog 表示信号上升沿和下降沿
	//当 clk 上升沿来临或者 rst_n 变低的时候执行一次 always 里的语句
	begin
		if(!rst_n)
			cnt_p<=0;
		else if (cnt_p==(N-1))
			cnt_p<=0;
		else cnt_p<=cnt_p+1; //计数器一直计数,当计数到 N-1 的时候清零,这是一个模 N 的计数器
	end
	//上升沿触发的分频时钟输出,如果 N 为奇数得到的时钟占空比不是 50%;如果 N 为偶数得到的时钟占空比为 50%
	always @ (posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			clk_p<=0;
		else if (cnt_p<(N>>1))//N>>1 表示右移一位,相当于除以 2 去掉余数
			clk_p<=0;
		else
			clk_p<=1; //得到的分频时钟正周期比负周期多一个 clk 时钟
	end
	//下降沿触发时计数器的控制
	always @ (negedge clk or negedge rst_n)
	begin
		if(!rst_n)
			cnt_n<=0;
		else if (cnt_n==(N-1))
			cnt_n<=0;
		else cnt_n<=cnt_n+1;
	end
	//下降沿触发的分频时钟输出,和 clk_p 相差半个时钟
	always @ (negedge clk)
	begin
		if(!rst_n)
			clk_n<=0;
		else if (cnt_n<(N>>1))
			clk_n<=0;
		else
			clk_n<=1; //得到的分频时钟正周期比负周期多一个 clk 时钟
	end
	assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p; //条件判断表达式
	//当 N=1 时,直接输出 clk
	//当 N 为偶数也就是 N 的最低位为 0,N(0)=0,输出 clk_p
	//当 N 为奇数也就是 N 最低位为 1,N(0)=1,输出 clk_p&clk_n。正周期多所以是相与
endmodule

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值