交通信号灯代码_交通灯代码

交通信号灯代码_交通灯代码一、Overview(1)Demand(2)Theory二、InterfaceDescription三、EW_FSM四、DesignandFunctionalVerification(1)RTL(2)TestBench五、Result(1)复位(2)倒计时(3)最终结果………

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用


完整程序(点击下载
虚拟机:VMware -14.0.0.24051
环 境:ubuntu 18.04.1
脚 本:makefile(点击直达
工 具:vcs 和 verdi



一、Overview

(1)Demand

  设计一个交通信号灯控制器,东西和南北方向各有四盏灯,分别为左拐灯绿灯黄灯和红灯。东西方向信号灯的时间为红灯55s,绿灯40s,黄灯5s,左拐灯15s;南北方向信号灯的时间为红灯65s,绿灯30s,黄灯5s,左拐灯15s.

(2)Theory

在这里插入图片描述


二、Interface Description

Signal Name Width Direction Description
clk 1 input System clk signal, 1Hz
rst_n 1 input System reset signal
light_ew_ZRYG 4 output 东西方向的左转、红、黄、绿灯
light_ns_ZRYG 4 output 南北方向的左转、红、黄、绿灯
time_ew_cnt 6 output 东西方向的倒计时
time_ns_cnt 7 output 南北方向的倒计时

三、EW_FSM

在这里插入图片描述

交通信号灯非常适合使用状态机实现,这个模块采用一个状态机,东西方向状态机一共有6个状态,其中南北方向和东西方向时间上是一个互补的状态。(为什么不使用两个状态机,因为它们时间上是互补的状态,只要其中一个方向的状态和倒计时已知,就可以控制另外一个方向的灯,在资源上,节省一个方向的状态机资源。


四、Design and Functional Verification

(1)RTL

//-- modified by xlinxdu, 2022/05/08
module traffic_lights 
#(
//-- time
parameter G_TIME_EW = 6'd40,
parameter Y_TIME_EW = 6'd5 ,
parameter R_TIME_EW = 6'd55,
parameter Z_TIME_EW = 6'd15,
parameter G_TIME_NS = 7'd30,
parameter Y_TIME_NS = 7'd5 ,
parameter R_TIME_NS = 7'd65,
parameter Z_TIME_NS = 7'd15
)(
input            clk_i        ,
input            rst_n_i      ,
//-- ew: east and west direction
//-- ns: north-south direction
//-- light,[3:0] green\yellow\red\left turn light
output reg [3:0] light_ew_ZRYG,
output reg [3:0] light_ns_ZRYG,
//-- counter
output reg [5:0] time_ew_cnt  ,
output reg [6:0] time_ns_cnt
);
//FSM signal
parameter G_LIGHT_EW  = 6'b00_0001;
parameter Y_LIGHT_EW1 = 6'b00_0010;
parameter R_LIGHT_EW  = 6'b00_0100;
parameter Y_LIGHT_EW2 = 6'b00_1000;
parameter Z_LIGHT_EW  = 6'b01_0000;
parameter Y_LIGHT_EW3 = 6'b10_0000;
reg [5:0] cur_state_ew;
reg [5:0] nxt_state_ew;
reg       ew_cnt_en   ;
reg       ns_cnt_en   ;
/*-----------------------------------------------\
------------------- ew counter  ----------------
\-----------------------------------------------*/
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
ew_cnt_en   <= 1'b1     ;
time_ew_cnt <= 0;
end
else if (ew_cnt_en && (nxt_state_ew == R_LIGHT_EW)) begin
time_ew_cnt <= R_TIME_EW;
ew_cnt_en   <= 1'b0     ;
end
else if (ew_cnt_en && (nxt_state_ew == Y_LIGHT_EW1 )) begin
time_ew_cnt <= Y_TIME_EW;
ew_cnt_en   <= 1'b0     ;
end
else if (ew_cnt_en && (nxt_state_ew ==  Y_LIGHT_EW2 )) begin
time_ew_cnt <= Y_TIME_EW;
ew_cnt_en   <= 1'b0     ;
end
else if (ew_cnt_en && (nxt_state_ew ==  Y_LIGHT_EW3)) begin
time_ew_cnt <= Y_TIME_EW;
ew_cnt_en   <= 1'b0     ;
end
else if (ew_cnt_en && (nxt_state_ew == G_LIGHT_EW)) begin
time_ew_cnt <= G_TIME_EW;
ew_cnt_en   <= 1'b0     ;
end
else if (ew_cnt_en && (nxt_state_ew == Z_LIGHT_EW)) begin
time_ew_cnt <= Z_TIME_EW; 
ew_cnt_en   <= 1'b0     ;
end
else if(time_ew_cnt == 6'd2) begin
ew_cnt_en   <= 1'b1;
time_ew_cnt <= time_ew_cnt - 1'b1;
end
else  begin
time_ew_cnt <= time_ew_cnt - 1'b1;
end
end
/*-----------------------------------------------\
-------------------- ns counter  ---------------
\-----------------------------------------------*/
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
ns_cnt_en   <= 1'b1     ;
time_ns_cnt <= 0;
end
else if (ns_cnt_en && (nxt_state_ew == R_LIGHT_EW)) begin
if(ew_cnt_en)                  time_ns_cnt <= G_TIME_NS;
else if(time_ew_cnt ==  6'd26) time_ns_cnt <= Y_TIME_NS;
else if(time_ew_cnt ==  6'd21) time_ns_cnt <= Z_TIME_NS;
else if(time_ew_cnt ==  6'd6 ) time_ns_cnt <= Y_TIME_NS;
ns_cnt_en   <= 1'b0     ;
end
else if (ns_cnt_en && (nxt_state_ew == Y_LIGHT_EW1)) begin
time_ns_cnt <= R_TIME_NS;
ns_cnt_en   <= 1'b0     ;
end
else if (ns_cnt_en && (nxt_state_ew == Y_LIGHT_EW3)) begin
time_ns_cnt <= Y_TIME_NS;
ns_cnt_en   <= 1'b0     ;
end
else if(time_ns_cnt == 7'd2) begin
ns_cnt_en   <= 1'b1;
time_ns_cnt <= time_ns_cnt - 1'b1;
end
else  begin
time_ns_cnt <= time_ns_cnt - 1'b1;
end
end
/*-----------------------------------------------\
---------------------  FSM  --------------------
\-----------------------------------------------*/
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
cur_state_ew <= R_LIGHT_EW;
end
else begin
cur_state_ew <= nxt_state_ew;
end
end
always @ (*) begin
case(cur_state_ew)
R_LIGHT_EW :if(time_ew_cnt == 1'b1) begin
nxt_state_ew = Y_LIGHT_EW1;
end
else begin
nxt_state_ew = R_LIGHT_EW ;
end
Y_LIGHT_EW1:if(time_ew_cnt == 1'b1) begin
nxt_state_ew = G_LIGHT_EW ;
end
else begin
nxt_state_ew = Y_LIGHT_EW1;
end
G_LIGHT_EW :if(time_ew_cnt == 1'b1) begin
nxt_state_ew = Y_LIGHT_EW2;
end
else begin
nxt_state_ew = G_LIGHT_EW ;
end
Y_LIGHT_EW2:if(time_ew_cnt == 1'b1) begin
nxt_state_ew = Z_LIGHT_EW ;
end
else begin
nxt_state_ew = Y_LIGHT_EW2;
end
Z_LIGHT_EW :if(time_ew_cnt == 1'b1) begin
nxt_state_ew = Y_LIGHT_EW3;
end
else begin
nxt_state_ew = Z_LIGHT_EW ;
end
Y_LIGHT_EW3:if(time_ew_cnt == 1'b1) begin
nxt_state_ew = R_LIGHT_EW ;
end
else begin
nxt_state_ew = Y_LIGHT_EW3;
end
default    :begin
nxt_state_ew = R_LIGHT_EW ;
end
endcase
end
//-- ew out
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
light_ew_ZRYG <= 4'b1111;
end
else if ((time_ew_cnt != 6'b1) && (cur_state_ew == R_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b0100;
end
else if ((time_ew_cnt != 6'b1) && (cur_state_ew == (Y_LIGHT_EW1 || Y_LIGHT_EW2 || Y_LIGHT_EW3))) begin
light_ew_ZRYG <= 4'b0010;
end
else if ((time_ew_cnt != 6'b1) && (cur_state_ew == G_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b0001;
end
else if ((time_ew_cnt != 6'b1) && (cur_state_ew == Z_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b1000;
end
end
//-- ns out
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
light_ns_ZRYG <= 4'b1111;
end
else if ((time_ns_cnt != 6'b1) && (cur_state_ew == R_LIGHT_EW)) begin
if     (time_ew_cnt >  6'd25) light_ns_ZRYG <= 4'b0001;
else if(time_ew_cnt >  6'd20) light_ns_ZRYG <= 4'b0010;
else if(time_ew_cnt >  6'd5 ) light_ns_ZRYG <= 4'b1000;
else if(time_ew_cnt >= 6'd1 ) light_ns_ZRYG <= 4'b0010;
end
else if ((time_ns_cnt != 6'b1) && (cur_state_ew != (R_LIGHT_EW || Y_LIGHT_EW3))) begin
light_ns_ZRYG <= 4'b0100;
end
else if ((time_ns_cnt != 6'b1) && (cur_state_ew == Y_LIGHT_EW3)) begin
light_ns_ZRYG <= 4'b0010;
end
end
endmodule

(2)Test Bench

`timescale 1ms/1ms
module tb_traffic_lights;
reg clk_i;
reg rst_n_i;
wire [3:0] light_ew_ZRYG;
wire [3:0] light_ns_ZRYG;
wire [5:0] time_ew_cnt  ;
wire [6:0] time_ns_cnt  ;
initial begin
clk_i = 0 ;
rst_n_i = 1;
#10 rst_n_i = 0;
#10 rst_n_i = 1;
end
always #500 clk_i = ~clk_i;
traffic_lights tb(
.clk_i        (clk_i        ),
.rst_n_i      (rst_n_i      ),
.light_ns_ZRYG(light_ns_ZRYG),
.light_ew_ZRYG(light_ew_ZRYG),
.time_ew_cnt  (time_ew_cnt  ),
.time_ns_cnt  (time_ns_cnt  )
);
initial begin
#200000 $finish;
$fsdbDumpfile("traffic.fsdb");
$fsdbDumpvars                ;
$fsdbDumpMDA                 ;
end
endmodule

五、Result

(1)复位

在这里插入图片描述

  设置初始状态为东西方向为红灯状态,南北方向设置为绿灯状态。在复位信号来临的时候,东西和南北方向的所有信号灯均亮起来,并且使能东西、南北方向的倒计时计数,波形正确。

(2)倒计时

在这里插入图片描述

bug1:在东西方向红灯倒计时结束后,红灯没有立即变为黄灯,而是保持红灯状态,不符合要求。

//-- ew out
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
light_ew_ZRYG <= 4'b1111;
end
else if ((time_ew_cnt != 6'b1) && (cur_state_ew == R_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b0100;
end
else if ((time_ew_cnt != 6'b1) && (cur_state_ew == (Y_LIGHT_EW1 || Y_LIGHT_EW2 || Y_LIGHT_EW3))) begin
light_ew_ZRYG <= 4'b0010;
end
else if ((time_ew_cnt != 6'b1) && (cur_state_ew == G_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b0001;
end
else if ((time_ew_cnt != 6'b1) && (cur_state_ew == Z_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b1000;
end
end

定位:定位到东西方向的输出代码块,把输出的产生条件改为和倒计时产生的条件一致,输出结果正常

//-- ew out
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
light_ew_ZRYG <= 4'b1111;
end
else if (ew_cnt_en && (nxt_state_ew == R_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b0100;
end
else if (ew_cnt_en && (nxt_state_ew == Y_LIGHT_EW1)) begin
light_ew_ZRYG <= 4'b0010;
end
else if (ew_cnt_en && (nxt_state_ew == Y_LIGHT_EW2)) begin
light_ew_ZRYG <= 4'b0010;
end
else if (ew_cnt_en && (nxt_state_ew == Y_LIGHT_EW3)) begin
light_ew_ZRYG <= 4'b0010;
end
else if (ew_cnt_en && (nxt_state_ew == G_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b0001;
end
else if (ew_cnt_en && (nxt_state_ew == Z_LIGHT_EW)) begin
light_ew_ZRYG <= 4'b1000;
end
end

在这里插入图片描述


在这里插入图片描述

bug2:由仿真波形可以知道,南北方向的亮灯输出与倒计时不匹配,延迟了一秒,不符合时序。

//-- ns out
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
light_ns_ZRYG <= 4'b1111;
end
else if ((time_ns_cnt != 6'b1) && (cur_state_ew == R_LIGHT_EW)) begin
if     (time_ew_cnt >  6'd25) light_ns_ZRYG <= 4'b0001;
else if(time_ew_cnt >  6'd20) light_ns_ZRYG <= 4'b0010;
else if(time_ew_cnt >  6'd5 ) light_ns_ZRYG <= 4'b1000;
else if(time_ew_cnt >= 6'd1 ) light_ns_ZRYG <= 4'b0010;
end
else if ((time_ns_cnt != 6'b1) && (nxt_state_ew != (R_LIGHT_EW || Y_LIGHT_EW3))) begin
light_ns_ZRYG <= 4'b0100;
end
else if ((time_ns_cnt != 6'b1) && (cur_state_ew == Y_LIGHT_EW3)) begin
light_ns_ZRYG <= 4'b0010;
end
end

定位:定位到南北方向的信号灯输出代码块,发现输出逻辑的条件不对,改为和倒计时一致的条件,即可同步输出。

//-- ns out
always @ (posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
light_ns_ZRYG <= 4'b1111;
end
else if (ns_cnt_en && (nxt_state_ew == R_LIGHT_EW)) begin
if(ew_cnt_en)                 light_ns_ZRYG <= 4'b0001;
else if(time_ew_cnt == 6'd26) light_ns_ZRYG <= 4'b0010;
else if(time_ew_cnt == 6'd21) light_ns_ZRYG <= 4'b1000;
else if(time_ew_cnt == 6'd6 ) light_ns_ZRYG <= 4'b0010;
end
else if (ns_cnt_en && (nxt_state_ew == Y_LIGHT_EW1)) begin
light_ns_ZRYG <= 4'b0100;
end
else if (ns_cnt_en && (nxt_state_ew == Y_LIGHT_EW3)) begin
light_ns_ZRYG <= 4'b0010;
end
end

在这里插入图片描述

(3)最终结果

在这里插入图片描述
在这里插入图片描述

结论:倒计时和信号灯的状态都符合要求,并且两个方向实现了互补的状态。


作者:xlinxdu
版权:本文是作者原创,版权归作者所有。
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/189952.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Java中高级工程师面试题及答案,Java面试题及答案汇总(二

    Java中高级工程师面试题及答案,Java面试题及答案汇总(二需要注意Jdk1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)24.说一下HashSet的实现原理?HashSet底层由HashMap实现HashSet的值存放于HashMap的key上HashMap的value统一为PRESENT25.ArrayList和LinkedList的区别是什么?最明显的区别是ArrrayList底层的数据结构是数组,支持随机访问,而Linke

  • 十大经典排序算法-快速排序算法详解

    十大经典排序算法-快速排序算法详解一、什么是快速排序1.概念快速排序(QuickSort)是从冒泡排序算法演变而来的,实际上是在冒泡排序基础上的递归分治法。快速排序在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成了两个部分2.算法原理这是一个无序数列:4、5、8、1、7、2、6、3,我们要将它按从小到大排序。按照快速排序的思想,我们先选择一个基准元素,进行排序我们选取4为我们的基准元素,并设置基准元素的位置为index,设置两个指针left和right,分别指向最左

  • scipy安装_scipy安装成功了就是用不了

    scipy安装_scipy安装成功了就是用不了1.最后正确的方法:pip升级后安装pipinstall–upgradepippipinstallscipy2.中间的报错及尝试方法:尝试1:pipinstallscipy问题1:numpy.distutils.system_info.NotFoundError:NoBLAS/LAPACKlibrariesfound.Note:Accelerateisnolongersupported.尝试2:gitclonehttps://gi

    2022年10月23日
  • K3 官改新手小白配置阿里DDNS 超级详细「建议收藏」

    K3 官改新手小白配置阿里DDNS 超级详细「建议收藏」K3官改新手小白配置阿里DDNS超级详细写的比较仓促,不对之处请指正,这个是写给小白看的,大神勿喷首先介绍一下什么是DDNSDDNS(DynamicDomainNameServer)是动态域名服务的缩写。DDNS是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,服务器…

  • redis 开源_redis 可视化

    redis 开源_redis 可视化前言RedisDeskTopManager可视化工具(之前一直在用的)其实我在本地一直是直接用redis-client直接命令行连接redis,一方面是可以熟悉redis的命令,另一方面实在也没有什么好用的客户端工具。别跟我说rdm,RedisDeskTopManager自从进入了0.9.9版本就开始付费使用或者贡献代码获得免费使用期限。而且rdm实在是太丑了,都不如我用命令行。RedisDeskTopManager可视化界面:最后在GitHub上看到一个开源的redis桌面可视化

  • win32 api函数_c调用webapi接口

    win32 api函数_c调用webapi接口前言如果要在Windows上面写程序,就不得不了解一些Win32Api的使用,Win32Api在C/C++的环境中使用非常的方便,直接调用头文件<Windows.h>使用就行了,但在C#中不会这么简单,需要在指定的模块之中导入想要的Win32,下面我们来学习一下如何在C#之中使用Win32Api…在测试Win32Api之前,我先教大家如何获取有窗口的进程信息,代码如下:有窗口的进程,它的窗口句柄不会为0,所以我们只需在所有运行的程序之中判断一.

    2022年10月11日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号