【上板现象】
定时转换的LED交通灯1在MP801的上板现象
https://www.bilibili.com/video/BV1h4411175c?p=79
定时转换的LED交通灯1在点拨开发板的上板现象
https://www.bilibili.com/video/BV1h4411175c?p=80
定时转换的LED交通灯1在实验箱的上板现象
https://www.bilibili.com/video/BV1h4411175c?p=81
【设计教程】
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 信号列表 | | | | | | | | | | | | | | | 3 比特信号,表示东面三个 led 灯,最高位为红灯,最低位为绿灯,低电平时灯亮。 | | | | 3 比特信号,表示南面三个 led 灯,最高位为红灯,最低位为绿灯,低电平时灯亮。 | | | | 3 比特信号,表示西面三个 led 灯,最高位为红灯,最低位为绿灯,低电平时灯亮。 | | | | 3 比特信号,表示北面三个 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秒后,东面循环变为黄灯,南面还是黄灯,西面变为红灯,北面变为黄灯
Mp8011. 复位,东西南北四面都是绿灯
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 秒,成功完成设计目标。
【设计视频教程】
【工程源码】
【设计教程下载】
2
|
|
|
|