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

交通信号灯代码_交通灯代码一、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
版权:本文是作者原创,版权归作者所有。
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。

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

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

(0)
上一篇 2026年3月5日 下午2:22
下一篇 2026年3月5日 下午3:01


相关推荐

  • Trunk 链路与 Access 链路的区别

    Trunk 链路与 Access 链路的区别Trunk 链路同一时刻可以支持多个 VLAN 的数据转发 数据携带 VLAN 标签 nativevlan 除外 Access 链路同一时刻只能传输一个 VLAN 的数据 发送和接收的数据 都没有标签

    2025年10月3日
    4
  • Platform Device and Drivers

    Platform Device and DriversPlatformDeviceandDrivers从我们可以了解Platformbus上面的驱动模型接口:platform_device,platform_driver。和PCI和USB这些大结构的总线不同,虚拟总线Platformbus使用最小结构来集成SOCpro

    2022年7月24日
    10
  • Hibernate5.0配置C3P0连接池步骤详解

    Hibernate5.0配置C3P0连接池步骤详解Hibernate5.0拥有自己的数据库连接池,但是无论性能和功能都不如C3P0(本人新手,查取资料得知),由于之前苦搜资源都不得愿,所以写下此篇文章以供像我一样苦于搜索的新手,以供参考。   Hibernate5.0整合C3P0实现连接池的步骤如下:   首先第一步   1).到https://sourceforge.net/projects/hibernate/到该网站

    2022年5月7日
    33
  • [MySQL] MySQL的自己主动化安装部署

    [MySQL] MySQL的自己主动化安装部署

    2021年11月28日
    39
  • django笔记_django 异步

    django笔记_django 异步前言Django是一个开放源代码的Web应用框架,由Python写成,最初用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站,即CMS(内容管理系统)软件,于2005年7月在BSD许可证下发布,这

    2022年7月31日
    10
  • 重磅!2021年国内Java培训机构排名前十最新出炉啦

    重磅!2021年国内Java培训机构排名前十最新出炉啦2021年国内Java培训机构排名前十的学校会是哪些呢?国内Java培训机构排名前十名该依据什么来评定呢?2021年国内Java培训机构排行榜排名的依据是按学员口碑、教学质量、就业率等多方面来进行评判,这次的排名是官方发布,具有权威性、公正性,可参考意义很强。下面,就为大家揭晓2021年最新的国内Java培训机构排名,这些机构在此次的评选活动中的得分又是多少呢。1、动力节点动力节点是成立于2009年,成立时间比较长,到现在为止还是只做Java单科教育,从动力节点毕业的程序员说讲的不错,创始人

    2022年7月7日
    1.1K

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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