基于FPGA的交通灯

交通灯是单片机和FPGA都会做的简单项目。本次交通灯做得比较简单,只是模仿一个十字路口的交通灯。

总共有三个模块组成,RTL视图如下:


顶层模块,控制模块,数码管显示模块。代码如下:

顶层模块:

module JTD (CLK,RST_N,LED,SEG_DATA,SEG_EN);

input CLK,RST_N;			//时钟和复位
output [5:0] LED;			//对应的灯分别是X方向红、黄、绿,Y方向红、黄、绿
output [6:0] SEG_DATA;	//数码管段选
output [1:0] SEG_EN;		//数码管位选

wire [3:0] DATA1,DATA0;

segled seg 
(
	.CLK			(CLK),
	.RST_N		(RST_N),
	.DATA_1		(DATA1),
	.DATA_0		(DATA0),
	.SEG_DATA	(SEG_DATA),
	.SEG_EN		(SEG_EN)
);

controler ctr
(
	.CLK			(CLK),
	.RST_N		(RST_N),
	.LED			(LED),
	.data1		(DATA1),
	.data0		(DATA0)
);


endmodule
控制模块:

module controler (CLK,RST_N,LED,data1,data0);

input CLK,RST_N;									//时钟和复位
output reg [5:0] LED;							
output reg [3:0]  data1,data0;				//输出倒计时的十位和个位

parameter TIME_1S 	  = 26'd50_000_000,	//1s晶振所振荡的次数
			 TIME_1S_HALF = 26'd25_000_000;	//0.5s晶振所振荡的次数

reg [25:0] cnt,cnt_n;							//用于计数
reg [3:0]  data1_n,data0_n;					//十位和个位下一个状态的寄存器
reg cnt_1s_half,cnt_1s_half_n;				//0.5s信号

parameter IDLE    = 5'b00001,					//启动与复位后的状态
			 X_PASS  = 5'b00010,					//X方向通行的状态
			 X_FLASH = 5'b00100,					//X方向黄灯闪烁的状态
			 Y_PASS	= 5'b01000,					//Y方向通行的状态
			 Y_FLASH = 5'b10000;					//Y方向黄灯闪烁的状态

reg [4:0] fsm_cs,fsm_ns;						//状态寄存器与下一个状态寄存器

//三段式状态机
always @ (posedge CLK or negedge RST_N)		//给状态寄存器赋值的时序电路
 if (!RST_N)
	fsm_cs <= IDLE;
 else
	fsm_cs <= fsm_ns;

always @ (*)											//给下一个状态赋值的组合电路
case (fsm_cs)
	IDLE		: if ((data0 == 4'd0) && (cnt == TIME_1S) && (data1 == 4'd0))
					fsm_ns = X_PASS;
				  else
					fsm_ns = fsm_cs;
	X_PASS	: if ((data0 == 4'd4) && (cnt == TIME_1S) && (data1 == 4'd0))
					fsm_ns = X_FLASH;
				  else
					fsm_ns = fsm_cs;
   X_FLASH  : if ((data0 == 4'd0) && (cnt ==  TIME_1S) && (data1 == 4'd0))
					fsm_ns = Y_PASS;
				  else
					fsm_ns = fsm_cs;
	Y_PASS	: if ((data0 == 4'd4) && (cnt == TIME_1S) && (data1 == 4'd0))
					fsm_ns = Y_FLASH;
				  else
					fsm_ns = fsm_cs;
   Y_FLASH  : if ((data0 == 4'd0) && (cnt ==  TIME_1S) && (data1 == 4'd0))
					fsm_ns = X_PASS;
				  else
					fsm_ns = fsm_cs;	
	default  : fsm_ns = IDLE;				
 endcase

always @ (*)												//给输出赋值的组合电路
 case (fsm_cs)
	IDLE		: LED = ~6'b100100;
	X_PASS	: LED = ~6'b001100;
   X_FLASH  : LED = ~{1'b0,cnt_1s_half,4'b0100};
	Y_PASS	: LED = ~6'b100001;
   Y_FLASH  : LED = ~{4'b1000,cnt_1s_half,1'b0};
	default  : LED = ~6'b100100;				
 endcase
 
//计数器,产生1HZ的时钟
always @ (posedge CLK or negedge RST_N)
	if (!RST_N)
		cnt <= 26'd0;
	else
		cnt <= cnt_n;

always @ (*)
   if (cnt == TIME_1S)
		cnt_n = 26'd0;
	else 
		cnt_n = cnt + 1'b1;
		
//产生2HZ信号		
always @ (posedge CLK or negedge RST_N)
	if (!RST_N)
		cnt_1s_half <= 1'b0;
	else
		cnt_1s_half <= cnt_1s_half_n;
		
always @ (*)
	if (cnt == TIME_1S_HALF)
		cnt_1s_half_n = cnt_1s_half  + 1'd1; 
	else
		cnt_1s_half_n = cnt_1s_half;
		
//个位计数
always @ (posedge CLK or negedge RST_N)
	if (!RST_N)
		data0 <= 4'd3;
	else
		data0 <= data0_n;

always @ (*)
	if (cnt == TIME_1S)
		begin
			if (data0 == 4'd0)
				begin
					if (data1 == 4'd0)
						data0_n = 4'd0;
					else
						data0_n = 4'd9;
				end
			else
				data0_n = data0 - 4'd1;
		end
	else
		data0_n = data0;
		
//十位计数
always @ (posedge CLK or negedge RST_N)
	if (!RST_N)
		data1 <= 4'b0;
	else
		data1 <= data1_n;
		
always @ (*)
	if ((cnt == TIME_1S) && (data0 == 4'd0))
		begin
			if (data1 == 4'd0)
				data1_n = 4'd2;
			else
				data1_n = data1 - 4'd1;
		end
	else
		data1_n = data1;
		
endmodule
数码管显示代码:

module segled (CLK,RST_N,DATA_1,DATA_0,SEG_DATA,SEG_EN);

input  CLK,RST_N;
input  [3:0] DATA_1,DATA_0;
output reg [6:0] SEG_DATA;
output [1:0] SEG_EN;

parameter SET_TIME_1MS = 16'd50_000;

reg [15:0] cnt,cnt_n;
reg [1:0] SEG_EN_N; 
reg cnt_seg,cnt_seg_n;

always @ (posedge CLK or negedge RST_N)
 begin
	if (!RST_N)
		cnt <= 16'd0;
	else
		cnt <= cnt_n;
 end
 
always @ (*)
begin
	if (cnt == SET_TIME_1MS)
		cnt_n = 16'd0;
	else
		cnt_n = cnt + 1'b1;
end


always @ (posedge CLK or negedge RST_N)
 if (!RST_N)
	cnt_seg <= 1'b0;
else
	cnt_seg <= cnt_seg_n;
	
	
always @ (*)
if (cnt == SET_TIME_1MS)
	cnt_seg_n = ~cnt_seg;
else
	cnt_seg_n = cnt_seg;
	
assign SEG_EN = cnt_seg ? 2'b10 : 2'b01;

wire [3:0] led = cnt_seg ? DATA_1 : DATA_0;

always @ (*)
begin
  case(led )
		0  :  SEG_DATA = 7'b0111111;   		//显示数字 "0"
		1  :  SEG_DATA = 7'b0000110;  		//显示数字 "1"
		2  :  SEG_DATA = 7'b1011011;   		//显示数字 "2"
		3  :  SEG_DATA = 7'b1001111;   		//显示数字 "3"
		4  :  SEG_DATA = 7'b1100110;  		//显示数字 "4"
		5  :  SEG_DATA = 7'b1101101;   		//显示数字 "5"
		6  :  SEG_DATA = 7'b1111101;   		//显示数字 "6"
		7  :  SEG_DATA = 7'b0000111;   		//显示数字 "7"
		8  :  SEG_DATA = 7'b1111111;   		//显示数字 "8"
		9  :  SEG_DATA = 7'b1101111;  		//显示数字 "9"
		default : SEG_DATA = 7'b0000000; 	//显示数字 "0"
  endcase
end

endmodule




  • 15
    点赞
  • 170
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
设计任务 (一)有一条主干道和一条支干道的汇合点形成十字交叉路口,主干道为东西向,支干道为南北向。为确保车辆安全,迅速地通行,在交叉道口的每个入口处设置了红,绿,黄3色信号灯。 (二)要求: (1)主干道绿灯亮时,支干道红灯亮,反之亦然,两者交替允许通行,主干道每次放行55s,支干道每次放行25s。每次由绿灯变为红灯的过程中,黄灯亮5s作为过渡。 (2)能实现正常的倒计时显示功能。 (3)能实现总体清零功能:计数器由初始状态开始计数,对应状态的指示灯亮。 (4)能实现特殊状态的功能显示:进入特殊状态时,东西、南北路口均显示红灯状态。 Verilog HDL作为一种规范的硬件描述语言,被广泛应用于电路的设计中。利用Verilog的设计描述可被不同的工具(包括验证仿真、时序分析、测试分析以及综合)所支持,可用不同器件来实现。而可编程器件的广泛应用,为数字系统的设计带来了极大的灵活性。由于可编程器件可以通过软件编程对硬件的结构和工作方式进行重构,使得硬件的设计可以如同软件设计那样快捷方便。 本文用Verilog HDL设计了一个交通灯控制系统,主干道交通灯按绿-黄-红变化,支干道交通灯按红-绿-黄变化。设计采用了自顶向下的设计方法,首先根据功能将电路分为div(包括div1和div2)、counter、controller、Fenwei(包括Fenwei1和Fenwei2)、demx模块,然后针对每个模块进行开发。利用QuartusII6.0中的仿真工具对每个模块进行仿真,保证功能正确。在此基础上,将所有模块连接起来,形成完整的设计,并用QuartusII6.0中的仿真工具再次仿真。仿真结果表明功能正确,符合设计要求。最后利用QuartusII6.0将程序下载到Altera FPGA芯片EP1C3T144C8中,实际结果表明电路工作正常,满足了设计要求。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值