基于FPGA的交通灯
程序员文章站
2022-06-20 12:18:19
...
交通灯是单片机和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
上一篇: 怎么就吵起来了呢
推荐阅读
-
同一页面多个商品倒计时JS 基于面向对象的javascript
-
基于Android中dp和px之间进行转换的实现代码
-
基于Android设计模式之--SDK源码之策略模式的详解
-
基于Android中Webview使用自定义的javascript进行回调的问题详解
-
基于将Android工程做成jar包和资源文件的解决方法
-
基于Android应用中如何反馈Crash报告的详解
-
基于android中的各种颜色在drawable.xml中的值详解
-
基于Manifest.xml中不要出现重复的uses permission的说明
-
基于Android开发支持表情的实现详解
-
基于Java回顾之集合的总结概述