从计数器到可控线性序列机——LED实验进化六部曲
- 让LED灯按照亮0.25s,灭0.25s的状态循环亮灭
- 让LED灯按照亮0.25s,灭0.25s,亮0.75s,灭1s的状态循环亮灭
- 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。以0.25s为一个变化周期,8个变化状态为一个循环
- 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择
- 让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化
- 每隔10ms,让LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试,比如设置10us)
让LED灯按照亮0.5s,灭0.5s的状态循环亮灭
设计一个计数器,计数周期为0.5s,每当计数周期满,就让LED翻转一次
让LED灯按照亮0.25s,灭0.25s的状态循环亮灭
counter_led_0.v:
module counter_led_0(
clk,
reset,
led
);
input clk;
input reset;
output reg led; // 在always块中 所以是reg类型
reg [25:0] counter
parameter MCNT = 50000000;
always@(posedge clk or negedge reset)
if(!reset)
counter <= 0;
else if(counter == MCNT - 1)
counter = counter + 1'b1;
always@(posedge clk or negedge reset)
if(!reset)
led <= 0;
else if(counter == MCNT/2 - 1) // 这里后面再说,如过MCNT是个变量 后面就会有问题
led <= 1;
else if(counter == MCNT - 1)
led <= 0;
endmodule
led_flash_tb.v
module led_flash_tb;
reg clk;
reg reset;
wire led;
counter_led_0
#(
.MCNT(50000)
)
counter_led_0(
.clk(clk),
.reset(reset),
.led(led)
)
initial clk = 1;
always #10 clk = !clk;
initial begin
reset = 0;
#201;
reset = 1;
#2000000000;
$stop;
end
endmodule
第一题:
所以将 这一句话: else if(counter == MCNT/2 - 1) 改成 else if(counter == (MCNT/2+MCNT/4) - 1)
所以第一个问题解决了!
第二个问题:让LED灯按照亮0.25s,灭0.25s,亮0.75s,灭1s的状态循环亮灭
counter_led_2.v:
module counter_led_2(
clk,
reset,
led
);
input clk;
input reset;
output reg led; // 在always块中 所以是reg类型
reg [26:0] counter
parameter MCNT = 125000000;
always@(posedge clk or negedge reset)
if(!reset)
counter <= 0;
else if(counter == MCNT - 1)
counter = counter + 1'b1;
always@(posedge clk or negedge reset)
if(!reset)
led <= 1;
else if(counter == MCNT/10 - 1) // 这里后面再说,如过MCNT是个变量 后面就会有问题
led <= 0;
else if(counter == (MCNT/10+MCNT/5) - 1)
led <= 1;
else if(counter == (MCNT/10 + MCNT/5)*2 - 1)
led <= 0;
else if(counter == MCNT - 1)
led <= 1;
endmodule
testbench 使用上一个一样的,只需要把文件名修改一下
第三题:让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。以0.25s为一个变化周期,8个变化状态为一个循环
思考:什么是指定的亮灭模式?8个变化状态可以由用户随机指定。1. 2s为一个循环周期,2. 有一个指定亮灭状态的端口,来指定亮灭
counter_led_3.v:
module counter_led_3(
clk,
reset,
ctrl,
led
);
input clk;
input reset;
input [7:0] ctrl;
output reg led; // 在always块中 所以是reg类型
reg [26:0] counter
parameter MCNT = 100000000;
always@(posedge clk or negedge reset)
if(!reset)
counter <= 0;
else if(counter == MCNT - 1)
counter = counter + 1'b1;
always@(posedge clk or negedge reset)
if(!reset)
led <= 0;
// else if(counter == MCNT/8 - 1) // 这里后面再说,如过MCNT是个变量 后面就会有问题
//led <= ctrl[0];
//else if(counter == (MCNT*2/8 - 1)
// led <= ctrl[1];
//else if(counter == (MCNT*3/8 - 1)//
// led <= ctrl[2];
//else if(counter == (MCNT*4/8 - 1)
// led <= ctrl[3];
//else if(counter == (MCNT*5/8 - 1)
// led <= ctrl[4];
//else if(counter == (MCNT*6/8 - 1)
// led <= ctrl[5];
//else if(counter == (MCNT*7/8 - 1)
// led <= ctrl[6];
//else if(counter == (MCNT - 1)
// led <= ctrl[7];
else case(counter)
MCNT*1/8 - 1; led <= ctrl[0];
MCNT*2/8 - 1; led <= ctrl[1];
MCNT*3/8 - 1; led <= ctrl[2];
MCNT*4/8 - 1; led <= ctrl[3];
MCNT*5/8 - 1; led <= ctrl[4];
MCNT*6/8 - 1; led <= ctrl[5];
MCNT*7/8 - 1; led <= ctrl[6];
MCNT*8/8 - 1; led <= ctrl[7];
default: led <= led;
endcase
endmodule
counter_led_3_tb.v:
module led_flash_tb;
reg clk;
reg reset;
reg [7:0]ctrl;
reg led;
counter_led_3
#(
.MCNT(100000)
)
counter_led_2(
.clk(clk),
.reset(reset),
.ctrl(ctrl),
.led(led)
)
initial clk = 1;
always #10 clk = !clk;
initial begin
reset = 0;
ctrl = 0;
#201;
reset = 1;
#2000;
ctrl = 8'b10100010;
#2000000000;
$stop;
end
endmodule
第四题:让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择
思考:现在以多少时间为一个周期,未知没有指定。时间值需要用户指定,需要指定parameter
module counter_led_4(
clk,
reset,
ctrl,
time,
led
);
input clk;
input reset;
input [7:0] ctrl;
input [31:0] time;
output reg led; // 在always块中 所以是reg类型
reg [31:0] counter
always@(posedge clk or negedge reset)
if(!reset)
counter <= 0;
else if(counter == Time - 1)
counter = counter + 1'b1;
reg [2:0] counter2;
always@(posedge clk or negedge reset)
if(!reset)
counter2 <= 0;
else if (counter == Time - 1)
counter2 <= counter2 +1'b1;
always@(posedge clk or negedge reset)
if(!reset)
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
testbench 使用3的 文件,修改文件名即可,还要加入 time的端口,定义一个reg类型的输入
counter_led_4_tb.v:
module led_flash_tb;
reg clk;
reg reset;
reg [7:0]ctrl;
reg [31:0]time;
reg led;
counter_led_4
#(
.MCNT(100000)
)
counter_led_4 counter_led_4(
.clk(clk),
.reset(reset),
.ctrl(ctrl),
.time(time),
.led(led)
)
initial clk = 1;
always #10 clk = !clk;
initial begin
reset = 0;
ctrl = 0;
time =0;
#201;
reset = 1;
#2000;
time = 2500;
ctrl = 8'b10100010;
#2000000000;
$stop;
end
endmodule
通过两个计数器嵌套的方式,可以实现指定的时间,设置time的值即可
第五题:让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化
思考:就是多个LED等和第四题相同
同时控制多个信号。
第六题:每隔10ms,让LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试,比如设置10us)
思考:这是图的解释,每隔10ms。10ms怎么来?执行一次怎么做?