Verilog Practice 01: Led
Led 练习:从点灯到串口练习1
题目
一、基础部分
1.让LED灯按照亮0.25s,灭0.75s的状态循环亮灭
2.让LED灯按照亮0.25s,灭0.5秒,亮0.75秒,灭1秒的状态循环亮灭
3.让LED灯按照指定的亮灭模式亮灭,亮灭模式位置,由用户随机指定。以0.25秒为一个变化周期,8个变化状态为一个循环。
二、提高部分
4.让LED灯按照指定亮灭模式亮灭,亮灭模式位置。由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同应用场景选择
5.让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化
6.每隔10ms,让LED灯的一个8状态循环执行一次(每个状态变化时间值小一点,方便测试,比如设定在10us)
7.请了解串口的通信协议(学会阅读手册也是一种能力)
8.实现串口通信协议
说明:1.对于基础部分第三问“随机指定”(规定亮为1,灭为0):假设,用户随机指定数据为1100_1010,那么这个周期灯的亮灭就应该是:亮亮灭灭,亮灭亮灭
练习
第一题 counter_led_1.v:
module counter_led_1 (
clk,
rst_n,
led
);
input clk;
input rst_n;
output reg led;
reg [25:0] counter;
parameter CNT = 50000000;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter <= 0;
else if(counter == CNT - 1)
counter <= 0;
else
counter <= counter + 1'b1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
led <= 0;
else if(counter == (CNT / 2 + CNT / 4) - 1)
led <= 1;
else if(counter == CNT - 1)
led <= 0;
endmodule
第二题 counter_led_2.v:
module counter_led_2 (
clk,
rst_n,
led
);
input clk;
input rst_n;
output reg led;
reg [26:0] counter;
parameter CNT = 125000000;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter <= 0;
else if(counter == CNT - 1)
counter <= 0;
else
counter <= counter + 1'b1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
led <= 0;
else if(counter == (CNT / 5 + CNT / 5) - 1)
led <= 1;
else if(counter == (CNT / 5 * 2 + CNT / 10) - 1)
led <= 0;
else if(counter == (CNT / 10 + CNT / 5 * 3) - 1)
led <= 1;
else if(counter == CNT - 1)
led <= 0;
endmodule
第三题 counter_led_3.v:
module counter_led_3 (
clk,
rst_n,
ctrl,
led
);
input clk;
input rst_n;
input [7:0] ctrl;
output reg led;
reg [26:0] counter;
parameter CNT = 100000000;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter <= 0;
else if(counter == CNT - 1)
counter <= 0;
else
counter <= counter + 1'b1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
led <= 0;
else if(counter == CNT / 8 - 1)
led <= ctrl[0];
else if(counter == CNT / 4 - 1)
led <= ctrl[1];
else if(counter == CNT / 8 * 3 - 1)
led <= ctrl[2];
else if(counter == CNT / 2 - 1)
led <= ctrl[3];
else if(counter == CNT / 8 * 5 - 1)
led <= ctrl[4];
else if(counter == CNT / 4 * 3 - 1)
led <= ctrl[5];
else if(counter == CNT / 8 * 7 - 1)
led <= ctrl[6];
else if(counter == CNT - 1)
led <= ctrl[7];
endmodule
第四题 counter_led_4.v:
module counter_led_4 (
clk,
rst_n,
ctrl,
Time,
led
);
input clk;
input rst_n;
input [7:0] ctrl;
input [31:0] Time;
output reg led;
reg [31:0] counter;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter <= 0;
else if(counter == Time - 1)
counter <= 0;
else
counter <= counter + 1'b1;
reg [2:0] counter2;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter2 <= 0;
else if(counter == Time - 1)
counter2 <= counter2 + 1'b1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
led <= 0;
else case(counter2)
0:led <= ctrl[0];
1:led <= ctrl[1];
2:led <= ctrl[2];
3:led <= ctrl[3];
4:led <= ctrl[4];
5:led <= ctrl[5];
6:led <= ctrl[6];
7:led <= ctrl[7];
default: led <= led;
endcase
endmodule
第五题 counter_led_5.v:
module counter_led_5 (
clk,
rst_n,
ctrl_1,
ctrl_2,
ctrl_3,
ctrl_4,
ctrl_5,
ctrl_6,
ctrl_7,
ctrl_8,
Time,
led,
);
input clk;
input rst_n;
input [7:0] ctrl_1;
input [7:0] ctrl_2;
input [7:0] ctrl_3;
input [7:0] ctrl_4;
input [7:0] ctrl_5;
input [7:0] ctrl_6;
input [7:0] ctrl_7;
input [7:0] ctrl_8;
input [31:0] Time;
output reg [7:0] led;
reg [31:0] counter;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter <= 0;
else if(counter == Time - 1)
counter <= 0;
else
counter <= counter + 1'b1;
reg [2:0] counter2;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter2 <= 0;
else if(counter == Time - 1)
counter2 <= counter2 + 1'b1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
led <= 0;
else case(counter2)
0:begin led[0] <= ctrl_1[0];
led[1] <= ctrl_2[0];
led[2] <= ctrl_3[0];
led[3] <= ctrl_4[0];
led[4] <= ctrl_5[0];
led[5] <= ctrl_6[0];
led[6] <= ctrl_7[0];
led[7] <= ctrl_8[0]; end
1:begin led[0] <= ctrl_1[1];
led[1] <= ctrl_2[1];
led[2] <= ctrl_3[1];
led[3] <= ctrl_4[1];
led[4] <= ctrl_5[1];
led[5] <= ctrl_6[1];
led[6] <= ctrl_7[1];
led[7] <= ctrl_8[1]; end
2:begin led[0] <= ctrl_1[2];
led[1] <= ctrl_2[2];
led[2] <= ctrl_3[2];
led[3] <= ctrl_4[2];
led[4] <= ctrl_5[2];
led[5] <= ctrl_6[2];
led[6] <= ctrl_7[2];
led[7] <= ctrl_8[2]; end
3:begin led[0] <= ctrl_1[3];
led[1] <= ctrl_2[3];
led[2] <= ctrl_3[3];
led[3] <= ctrl_4[3];
led[4] <= ctrl_5[3];
led[5] <= ctrl_6[3];
led[6] <= ctrl_7[3];
led[7] <= ctrl_8[3]; end
4:begin led[0] <= ctrl_1[4];
led[1] <= ctrl_2[4];
led[2] <= ctrl_3[4];
led[3] <= ctrl_4[4];
led[4] <= ctrl_5[4];
led[5] <= ctrl_6[4];
led[6] <= ctrl_7[4];
led[7] <= ctrl_8[4]; end
5:begin led[0] <= ctrl_1[5];
led[1] <= ctrl_2[5];
led[2] <= ctrl_3[5];
led[3] <= ctrl_4[5];
led[4] <= ctrl_5[5];
led[5] <= ctrl_6[5];
led[6] <= ctrl_7[5];
led[7] <= ctrl_8[5]; end
6:begin led[0] <= ctrl_1[6];
led[1] <= ctrl_2[6];
led[2] <= ctrl_3[6];
led[3] <= ctrl_4[6];
led[4] <= ctrl_5[6];
led[5] <= ctrl_6[6];
led[6] <= ctrl_7[6];
led[7] <= ctrl_8[6]; end
7:begin led[0] <= ctrl_1[7];
led[1] <= ctrl_2[7];
led[2] <= ctrl_3[7];
led[3] <= ctrl_4[7];
led[4] <= ctrl_5[7];
led[5] <= ctrl_6[7];
led[6] <= ctrl_7[7];
led[7] <= ctrl_8[7]; end
default:begin led[0] <= led[0]; led[1] <= led[1]; led[2] <= led[2]; led[3] <= led[3]; led[4] <= led[4]; led[5] <= led[5]; led[6] <= led[6]; led[7] <= led[7]; end
endcase
endmodule
第六题 counter_led_6.v:
module counter_led_6 (
clk,
rst_n,
ctrl,
Time,
led
);
input clk;
input rst_n;
input [7:0] ctrl;
input [31:0] Time;
output reg led;
reg [31:0] counter0;
reg EN;
reg [31:0] counter;
reg [2:0] counter2;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter0 <= 0;
else if(counter0 == 500000 - 1)
counter0 <= 0;
else
counter0 <= counter0 + 1'b1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
EN <= 0;
else if(counter0 == 0)
EN <= 1;
else if((counter2 == 7)&&(counter == Time - 1))
EN <= 0;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter <= 0;
else if(EN)begin
if(counter == Time - 1)
counter <= 0;
else
counter <= counter + 1'b1;
end
always @ (posedge clk or negedge rst_n)
if(!rst_n)
counter2 <= 0;
else if(counter == Time - 1)
counter2 <= counter2 + 1'b1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
led <= 0;
else case(counter2)
0:led <= ctrl[0];
1:led <= ctrl[1];
2:led <= ctrl[2];
3:led <= ctrl[3];
4:led <= ctrl[4];
5:led <= ctrl[5];
6:led <= ctrl[6];
7:led <= ctrl[7];
default: led <= led;
endcase
endmodule
总结
第一题中的led设计,围绕着一个计数器开始,在计数器的辅助下,将clk信号量化,实现对时间的记录,并让固定时间的亮灭成为可能。值得注意的是,counter的最大值,代表了一个完整的周期,这意味着我们对led亮灭的控制来源于counter(current)/counter(max),从而达到led不等时长的亮灭。
第二题延续第一题的设计思路,但是将时长增长,并将counter的比例划分细化,从而实现了4种不同时长的亮灭状态。
第三题引入ctrl,实现了用户对led亮灭的控制。8个状态意味着将counter划分为八等份,通过对8位的ctrl在testbench中赋值,来决定led的亮灭。
第四题由于是用户决定时间,因此引入了Time,作为一次变化的时长,相应的,原有的counter不再作为完整的一周期的时长的计数器,成为了每次变化时长的计数器,而counter2的引入则实现了亮灭状态的计数。
第五题沿用counter_led_4.v的设计,不过将led的数量增加到8个,对应地引入了8个ctrl。
第六题由于需要间隔10ms循环亮灭,所以引入counter0来对间隔的10ms进行计数,并加入了EN信号,指示状态执行,在led亮灭中,沿用了counter_led_4.v的设计。
整个led题目中,围绕着时间控制和亮灭状态控制展开,对于时间控制,我们选择了引入计数器,让时间量化,间接实现计时功能;对于状态控制,我们选择加入ctrl信号来指示灯的亮灭状态,EN信号指示亮灭循环的开始与结束。
6道led题目意在为串口通信进行铺垫,8个led和串口的8位信号相对应,而状态的控制,尤其是EN信号的引入,也是串口通信的重要组成部分。