至简设计系列_定时转换的LED交通灯1

–作者:肖肖肖
本文为明德扬原创及录用文章,转载请注明出处!

1.1 总体设计
1.1.1 概述
发光二极管简称为LED,是一种常用的发光器件,通过电子与空穴复合释放能量发光,它可以高效的将电能转化为光能,在现代社会具有广泛的用途,如照明、平板显示、医疗器件等。可通过高低电平的变化来控制LED灯的明灭状态,当输出信号为低电平时,LED灯亮,反之,当输出信号为高电平时,LED灯灭。

1.1.2 设计目标
实现开发板上东西南北 4 个方向,每个方向上的 3 个 LED 灯按照“绿灯–黄灯–红灯–绿灯–黄灯…”依次循环变化。变化的速度不同,东面的间隔时间为 1 秒;西面的间隔时间为 2 秒;南面的间隔时间为 3 秒;北面的间隔时间为 4 秒。
具体要求:
1、每个方向的灯分开独立设计。
2、首先设计东向的灯:设计一个计时 1 秒的计数器,用来计算灯的状态变化的时间间隔。
3、如果计时 1 秒到了,把黄灯点亮;再过 1 秒把红灯点亮;再过 1 秒,把绿灯点亮…
依次循环。
4、设计西方向的灯:设计一个计时 2 秒的计数器,其他的类似。
5、其它两个方向的设计类似。

1.1.3 信号列表

信号名I/O位宽定义
clkI1系统工作时钟 50M
rst_nI1系统复位信号,低电平有效
led_eastO33 比特信号,表示东面三个 led 灯,最高位为红灯,最低位为绿灯,低电平时灯亮。
led_southO33 比特信号,表示南面三个 led 灯,最高位为红灯,最低位为绿灯,低电平时灯亮。
led_westO33 比特信号,表示西面三个 led 灯,最高位为红灯,最低位为绿灯,低电平时灯亮。
led_northO33 比特信号,表示北面三个 led 灯,最高位为红灯,最低位为绿灯,低电平时灯亮。

1.1.4 设计思路
根据题目功能要求,东西南北四个方向LED灯颜色变换的速度都不同。因为在数字电路中的延时都是通过计数器实现的,计数器*时钟周期=延时时间。本模块中,由于输入时钟是50MHz,时钟周期为20ns,功能要求每1秒变化一次。我们通过counter来表示延时,当其值为1s/20ns=5000_0000时,表示1秒时间到。

本工程架构由四个计数器组成:
在这里插入图片描述
东方向计数器e_counter:该计数器用于计算东向1s的时钟个数,加一条件为1,表示一直计数;数到5000_0000下,则表示数到1秒了。

西方向计数器w_counter:该计数器用于计算西向2s的时钟个数,加一条件为1,表示一直计数;数到2*5000_0000下,则表示数到2秒了。

南方向计数器s_counter:该计数器用于计算南向3s的时钟个数,加一条件为1,表示一直计数;数到3*5000_0000下,则表示数到3秒了。

北方向计数器n_counter:该计数器用于计算北向4s的时钟个数,加一条件为1,表示一直计数;数到4*5000_0000下,则表示数到4秒了。

下面是东西南北四个方向的秒计数器的代码。

parameter   COUNT_1S        =   26'd5000_0000;
parameter   COUNT_WID       =   28;

reg	   [COUNT_WID-1:0] e_counter;        
reg     [COUNT_WID-1:0] s_counter;
reg     [COUNT_WID-1:0] w_counter;
reg     [COUNT_WID-1:0] n_counter;

wire                    add_e_counter;
wire                    end_e_counter;
wire                    add_w_counter;
wire                    end_w_counter;
wire                    add_s_counter;
wire                    end_s_counter;
wire                    add_n_counter;
wire                    end_n_counter;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        e_counter <= 0; 
    end
    else if(add_e_counter) begin
        if(end_e_counter)
            e_counter <= 0; 
        else
            e_counter <= e_counter+1 ;
   end
end
assign add_e_counter = 1;
assign end_e_counter = add_e_counter  && e_counter == COUNT_1S-1 ;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        w_counter <= 0; 
    end
    else if(add_w_counter) begin
        if(end_w_counter)
            w_counter <= 0; 
        else
            w_counter <= w_counter+1 ;
   end
end
assign add_w_counter = 1;
assign end_w_counter = add_w_counter  && w_counter == 2*COUNT_1S-1 ;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        s_counter <= 0; 
    end
    else if(add_s_counter) begin
        if(end_s_counter)
            s_counter <= 0; 
        else
            s_counter <= s_counter+1 ;
   end
end
assign add_s_counter = 1;
assign end_s_counter = add_s_counter  && s_counter == 3*COUNT_1S-1 ;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        n_counter <= 0; 
    end
    else if(add_n_counter) begin
        if(end_n_counter)
            n_counter <= 0; 
        else
            n_counter <= n_counter+1 ;
   end
end
assign add_n_counter = 1;
assign end_n_counter = add_n_counter  && n_counter == 4*COUNT_1S-1 ;

LED灯信号的变化,根据功能要求,东面的间隔时间为 1 秒;西面的间隔时间为 2 秒;南面2的间隔时间为 3 秒;北面的间隔时间为 4 秒。计数时间到时变化;时间没到,则不变化。每一时刻每个方向只有一个灯亮,并且亮灯的颜色顺序按照“绿灯–黄灯–红灯–绿灯–黄灯…”依次循环变化。
东西南北四个方向的各有三盏不同颜色的LED灯,每个方向的三个LED灯都由3 比特信号控制,最高位为红灯,最低位为绿灯,并且低电平时LED灯亮。led_east表示东面三个LED灯,led_west表示西面三个LED灯,led_south表示南面三个LED灯,led_north表示北面三个LED灯。
三色LED灯的循环变换控制可以通过拼接的方法使数据循环左移来实现。

以led_east的变化为例,上电后,led_east[2:0]=3’b110;然后每隔1秒,依次循环变化:101,011,110。即end_e_counter(每隔1秒)时,led_east[2:0]数值循环左移,其他时候不变。

led_west、led_south、led_north也是同理,即:
上电后,led_west[2:0]=3’b110;然后每隔2秒,依次循环变化:101,011,110。即end_w_counter(每隔2秒)时,led_west[2:0]数值循环左移,其他时候不变。
上电后,led_south[2:0]=3’b110;然后每隔3秒,依次循环变化:101,011,110。即end_s_counter(每隔3秒)时,led_south[2:0]数值循环左移,其他时候不变。
上电后,led_north[2:0]=3’b110;然后每隔4秒,依次循环变化:101,011,110。即end_n_counter(每隔4秒)时,led_north[2:0]数值循环左移,其他时候不变。

下面是个东西南北四个方向的LED灯亮灯控制代码。

parameter   LED_LEN         =   3;

output  [LED_LEN-1:0]   led_east;
output  [LED_LEN-1:0]   led_south;
output  [LED_LEN-1:0]   led_west;
output  [LED_LEN-1:0]   led_north;

reg     [LED_LEN-1:0]   led_east;
reg     [LED_LEN-1:0]   led_south;
reg     [LED_LEN-1:0]   led_west;
reg     [LED_LEN-1:0]   led_north;

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_east<={{(LED_LEN-1){1'b1}},1'b0};
    end
    else if(end_e_counter)begin
        led_east<={led_east[LED_LEN-2:0],led_east[LED_LEN-1]};
    end
    else begin
        led_east<=led_east;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_west<={{(LED_LEN-1){1'b1}},1'b0};
    end
    else if(end_w_counter)begin
        led_west<={led_west[LED_LEN-2:0],led_west[LED_LEN-1]};
    end
    else begin
        led_west<=led_west;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_south<={{(LED_LEN-1){1'b1}},1'b0};
    end
    else if(end_s_counter)begin
        led_south<={led_south[LED_LEN-2:0],led_south[LED_LEN-1]};
    end
    else begin
        led_south<=led_south;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_north<={{(LED_LEN-1){1'b1}},1'b0};
    end
    else if(end_n_counter)begin
        led_north<={led_north[LED_LEN-2:0],led_north[LED_LEN-1]};
    end
    else begin
        led_north<=led_north;
    end
end


1.1.5 参考设计代码

module  traf_light1(
    clk             ,
    rst_n           ,
    led_east        ,
    led_south       ,
    led_west        ,
    led_north       
    );


parameter   LED_LEN         =   3;
parameter   COUNT_1S        =   26'd5000_0000;
parameter   COUNT_WID       =   28;

input                   clk      ;
input                   rst_n    ;
output  [LED_LEN-1:0]   led_east ;
output  [LED_LEN-1:0]   led_south;
output  [LED_LEN-1:0]   led_west ;
output  [LED_LEN-1:0]   led_north;

reg     [LED_LEN-1:0]   led_east ;
reg     [LED_LEN-1:0]   led_south;
reg     [LED_LEN-1:0]   led_west ;
reg     [LED_LEN-1:0]   led_north;

reg	    [COUNT_WID-1:0] e_counter;        
reg     [COUNT_WID-1:0] s_counter;
reg     [COUNT_WID-1:0] w_counter;
reg     [COUNT_WID-1:0] n_counter;

wire                    add_e_counter;
wire                    end_e_counter;
wire                    add_w_counter;
wire                    end_w_counter;
wire                    add_s_counter;
wire                    end_s_counter;
wire                    add_n_counter;
wire                    end_n_counter;

always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        e_counter <= 0; 
    end
    else if(add_e_counter) begin
        if(end_e_counter)
            e_counter <= 0; 
        else
            e_counter <= e_counter+1 ;
   end
end
assign add_e_counter = 1;
assign end_e_counter = add_e_counter  && e_counter == COUNT_1S-1 ;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        w_counter <= 0; 
    end
    else if(add_w_counter) begin
        if(end_w_counter)
            w_counter <= 0; 
        else
            w_counter <= w_counter+1 ;
   end
end
assign add_w_counter = 1;
assign end_w_counter = add_w_counter  && w_counter == 2*COUNT_1S-1 ;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        s_counter <= 0; 
    end
    else if(add_s_counter) begin
        if(end_s_counter)
            s_counter <= 0; 
        else
            s_counter <= s_counter+1 ;
   end
end
assign add_s_counter = 1;
assign end_s_counter = add_s_counter  && s_counter == 3*COUNT_1S-1 ;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        n_counter <= 0; 
    end
    else if(add_n_counter) begin
        if(end_n_counter)
            n_counter <= 0; 
        else
            n_counter <= n_counter+1 ;
   end
end
assign add_n_counter = 1;
assign end_n_counter = add_n_counter  && n_counter == 4*COUNT_1S-1 ;

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_east<={{(LED_LEN-1){1'b1}},1'b0};
    end
    else if(end_e_counter)begin
        led_east<={led_east[LED_LEN-2:0],led_east[LED_LEN-1]};
    end
    else begin
        led_east<=led_east;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_west<={{(LED_LEN-1){1'b1}},1'b0};
    end
    else if(end_w_counter)begin
        led_west<={led_west[LED_LEN-2:0],led_west[LED_LEN-1]};
    end
    else begin
        led_west<=led_west;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_south<={{(LED_LEN-1){1'b1}},1'b0};
    end
    else if(end_s_counter)begin
        led_south<={led_south[LED_LEN-2:0],led_south[LED_LEN-1]};
    end
    else begin
        led_south<=led_south;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_north<={{(LED_LEN-1){1'b1}},1'b0};
    end
    else if(end_n_counter)begin
        led_north<={led_north[LED_LEN-2:0],led_north[LED_LEN-1]};
    end
    else begin
        led_north<=led_north;
    end
end

endmodule

1.2 效果和总结
点拨板
1.复位,东西南北四面都是绿灯
在这里插入图片描述
2.时间经过1秒后,东面变为黄灯,其余三面还是绿灯
在这里插入图片描述

3.时间经过2秒后,东面变为红灯,西面变为黄灯,其余两面不变
在这里插入图片描述
4.时间经过3秒后,东面又变回绿灯,南面变为黄灯,西面还是黄灯,北面还是绿灯不变
在这里插入图片描述
5.时间经过4秒后,东面循环变为黄灯,南面还是黄灯,西面变为红灯,北面变为黄灯
在这里插入图片描述

Mp801
1.复位,东西南北四面都是绿灯
在这里插入图片描述
2.时间经过1秒后,东面变为黄灯,其余三面还是绿灯
在这里插入图片描述
3.时间经过2秒后,东面变为红灯,西面变为黄灯,其余两面不变
在这里插入图片描述
4.时间经过3秒后,东面又变回绿灯,南面变为黄灯,西面还是黄灯,北面还是绿灯不变
在这里插入图片描述
5.时间经过4秒后,东面循环变为黄灯,南面还是黄灯,西面变为红灯,北面变为黄灯
在这里插入图片描述
实验箱
1.复位,东西南北四面都是绿灯
在这里插入图片描述
2.时间经过1秒后,东面变为黄灯,其余三面还是绿灯
在这里插入图片描述
3.时间经过2秒后,东面变为红灯,西面变为黄灯,其余两面不变
在这里插入图片描述
4.时间经过3秒后,东面又变回绿灯,南面变为黄灯,西面还是黄灯,北面还是绿灯不变
在这里插入图片描述
5.时间经过4秒后,东面循环变为黄灯,南面还是黄灯,西面变为红灯,北面变为黄灯
在这里插入图片描述

观看上面的现象,可以发现,工程各项功能正常:开发板上东西南北 4 个方向,每个方向上的 3 个 LED 灯按照“绿灯–黄灯–红灯–绿灯–黄灯…”依次循环变化,并且东西南北 4 个方向LED灯变化的速度不同,东面的间隔时间为 1 秒;西面的间隔时间为 2 秒;南面的间隔时间为 3 秒;北面的间隔时间为 4 秒,成功完成设计目标。
感兴趣的朋友也可以访问论坛进行FPGA相关工程设计学习,也欢迎大家在评论进行讨论!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值