赞
踩
目录
任务1:让LED灯按照亮0.25秒,灭0.75秒的状态循环亮灭
任务2:让LED灯按照亮0.25秒,灭0.5秒,亮0.75秒,灭1秒的状态循环亮灭
任务3:以0.25为基本的LED状态变化间隔(最小时间单元)以8小段·为一个循环周期(参考任务二10个小段);LED在每一小段该点亮还是该熄灭由8个输入端口决定。
任务4:在任务三的基础上,实现每隔一定时间,比如1秒钟,执行一轮LED8个状态的切换控制。
实现思路:计数器相当于一个刻度时间尺,在一秒的时间内,首先led应该是高电平,即计数器开始计数时LED电平就是高电平,然后当计数器计到0.25s后,LED就变成低电平了,什么时候又变成高电平呢?当然是1秒结束后,也就是计数器重新从0计数时LED变为高电平,此时第一个1秒循环结束,开始下一循环。
- //功能实现led亮0.25s,灭0.75s
- module LED_ctrl0(
- input Clk,
- input Reset_n,
- output reg Led
- );
-
- reg [25:0]counter;//定义计数器位数,板上时钟资源是20ns为一个周期,所以要用计时数除以20ns来计算计时次数。最后将次数转化成二进制位,有几位就定义几位计时器
- //计数器计数
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter <= 0;
- else if(counter == 50_000_000-1)
- counter <= 0;
- else
- counter <= counter + 1'd1;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- Led <= 0;
- else if(counter == 0)
- Led <= 1;
- else if(counter == 12_500_000-1)
- Led <= !Led;
- else
- Led <= Led;
- endmodule
- `timescale 1ns / 1ns
-
- module LED_ctrl0_tb();
-
- reg Clk;
- reg Reset_n;
- wire Led;
-
- LED_ctrl0 LED_ctrl0(
- .Clk(Clk),
- .Reset_n(Reset_n),
- .Led(Led)
- );
-
- initial Clk = 1;//初始信号为高电平
- always #10 Clk = ~Clk;//延时10ns以后初始信号取反,这句话是总是执行的。
-
- //产生激励复位信号
- initial begin
- Reset_n = 0;//开始复位信号为0,有效复位
- #201 Reset_n = 1;//201ns以后复位信号变为高电平,无效电平。开始仿真
- #2000000000;//两秒仿真
- $stop;//停止仿真
- end
- endmodule
计数器相当于一个刻度时间尺,在2.5s的时间内,首先led应该是高电平,保持0.25s,然后是低电平并保持0.5s,然后是高电平保持0.75s,最后是低电平保持1s。即计数器开始计数时LED电平就是高电平,然后当计数器计到0.25s后,LED就变成低电平了,什么时候又变成高电平呢?当然是0.75s秒后,那什么时候又变成低电平呢?当然是1.5s后啦,最后就是2s也就是计数器变为0时led重新拉高,一个循环结束。
- //功能实现led亮0.25s,灭0.5s,亮0.75s,灭1s
- module LED_ctrl1(
- input Clk,
- input Reset_n,
- output reg Led
- );
-
- parameter MCNT = 1000;
-
- reg [26:0]counter;//定义计数器位数,板上时钟资源是20ns为一个周期,所以要用计时数除以20ns来计算计时次数。最后将次数转化成二进制位,有几位就定义几位计时器
- //计数器计数
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter <= 0;
- else if(counter == 125_000*MCNT -1)
- counter <= 0;
- else
- counter <= counter + 1'd1;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- Led <= 0;
- else if(counter == 0)
- Led <= 1;
- else if(counter == 12_500*MCNT)
- Led <= !Led;
- else if(counter == 37_500*MCNT)
- Led <= !Led;
- else if(counter == 75_000*MCNT)
- Led <= !Led;
- else
- Led <= Led;
- endmodule
- `timescale 1ns / 1ns
-
- module LED_ctrl0_tb();
-
- reg Clk;
- reg Reset_n;
- wire Led;
-
- LED_ctrl1 LED_ctrl3_inst0(
- .Clk(Clk),
- .Reset_n(Reset_n),
- .Led(Led)
- );
-
- defparam LED_ctrl3_inst0.MCNT = 1;
-
- initial Clk = 1;//初始信号为高电平
- always #10 Clk = ~Clk;//延时10ns以后初始信号取反,这句话是总是执行的。
-
- //产生激励复位信号
- initial begin
- Reset_n = 0;//开始复位信号为0,有效复位
- #201 Reset_n = 1;//201ns以后复位信号变为高电平,无效电平。开始仿真
- #2000000;//两毫秒仿真
- #2000000;//两毫秒仿真
- $stop;//停止仿真
- end
- endmodule
可以将2.5S等分为10份,每一份做不同的事情。此时使用两个计数器来实现,其中一个计数器用来计时0.25S另外一个计时器用来计算计数器1计满0.25S的次数。这样就可以在不同的时刻做不同的事情了。框图如下图所示,有助于理解。
- //功能实现led亮0.25s,灭0.5s,亮0.75s,灭1s
- module LED_ctrl2(
- input Clk,
- input Reset_n,
- output reg Led
- );
-
- reg [23:0]counter0;//定义计数器位数,板上时钟资源是20ns为一个周期,所以要用计时数除以20ns来计算计时次数。最后将次数转化成二进制位,有几位就定义几位计时器
- reg [3:0]counter1;
-
- parameter MCNT = 1000;
-
- //计数器计数
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter0 <= 0;
- else if(counter0 == 12_500*MCNT -1)
- counter0 <= 0;
- else
- counter0 <= counter0 + 1'd1;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter1 <= 0;
- else if(counter0 == 12_500*MCNT-1)
- begin
- if(counter1 == 9)
- counter1 <= 0;
- else
- counter1 <= counter1+1'd1;
- end
- else
- counter1 <= counter1;
- //使用if else语句实现
- // always@(posedge Clk or negedge Reset_n)
- // if(!Reset_n)//可见Reset_n复位是低电平有效
- // Led <= 0;
- // else if(counter1 == 0)
- // Led <= 1;
- // else if(counter1 == 1||counter1 == 2)
- // Led <= 0;
- // else if(counter1 == 3||counter1 == 4||counter1 == 5)
- // Led <= 1;
- // else if(counter1 == 6||counter1 == 7||counter1 == 8||counter1 == 9)
- // Led <= 0;
- // else
- // Led <= Led;
- //使用case语句实现
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- Led <= 0;
- else begin
- case(counter1)
- 0:Led <= 1;
- 1:Led <= 0;
- 2:Led <= 0;
- 3:Led <= 1;
- 4:Led <= 1;
- 5:Led <= 1;
- 6:Led <= 0;
- 7:Led <= 0;
- 8:Led <= 0;
- 9:Led <= 0;
- default:Led <= Led ;
- endcase
- end
- endmodule
-
同实现思路一
同实现思路一
实现思路二:可以将2S等分为8份,每一份做不同的事情。此时使用两个计数器来实现,其中一个计数器用来计时0.25S另外一个计时器用来计算计数器1计满0.25S的次数。这样就可以在不同的时刻做不同的事情了。
- //功能实现led亮0.25s,灭0.5s,亮0.75s,灭1s
- module LED_ctrl3(
- input Clk,
- input Reset_n,
- input [7:0]SW,
- output reg Led
- );
-
- reg [23:0]counter0;//定义计数器位数,板上时钟资源是20ns为一个周期,所以要用计时数除以20ns来计算计时次数。最后将次数转化成二进制位,有几位就定义几位计时器
- reg [2:0]counter1;
-
- parameter MCNT = 12500000-1;
- //计数器计数
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter0 <= 0;
- else if(counter0 == MCNT)
- counter0 <= 0;
- else
- counter0 <= counter0 + 1'd1;
-
- //8个数计数计到7自动清零。
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter1 <= 0;
- else if(counter0 == MCNT)
- counter1 <= counter1+1;
- else
- counter1 <= counter1;
-
- //使用case语句实现
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- Led <= 0;
- else begin
- case(counter1)
- 0:Led <= SW[0];
- 1:Led <= SW[1];
- 2:Led <= SW[2];
- 3:Led <= SW[3];
- 4:Led <= SW[4];
- 5:Led <= SW[5];
- 6:Led <= SW[6];
- 7:Led <= SW[7];
- default:Led <= Led ;
- endcase
- end
- endmodule
- `timescale 1ns / 1ns
-
- module LED_ctrl0_tb();
-
- reg Clk;
- reg Reset_n;
- reg [7:0]SW;
- wire Led;
-
- LED_ctrl3 LED_ctrl3_inst0(
- .Clk(Clk),
- .Reset_n(Reset_n),
- .Led(Led),
- .SW(SW)
- );
-
- defparam LED_ctrl3_inst0.MCNT = 12500-1;
-
- initial Clk = 1;//初始信号为高电平
- always #10 Clk = ~Clk;//延时10ns以后初始信号取反,这句话是总是执行的。
-
- //产生激励复位信号
- initial begin
- Reset_n = 0;//开始复位信号为0,有效复位
- SW = 8'b0010_1010;
- #201 Reset_n = 1;//201ns以后复位信号变为高电平,无效电平。开始仿真
- #2_000_000;//仿真2ms
- SW = 8'b0000_0001;
- #2_000_000;//仿真2ms
- $stop;//停止仿真
- end
- endmodule
实现思路一:可以将3S等分为12份,每一份做不同的事情。此时前4份为空闲状态,后8位为动态变化状态,其中一个计数器用来计时0.25S,另外一个计时器用来计算计数器1计满0.25S的次数。这样就可以在不同的时刻做不同的事情了。
实现思路二(百用):计数器是一个刻度尺,写一个周期为3S的计数器,将这个计数器作为一个时间刻度尺,找到1S,1.25S,1.5S,1.75S,2S,2.25S,2.5S,2.75S,3S对应的计数器的值1。分别在计数器到达这些值的时候,控制LED输出SW的位,或者空闲态的0值。
实现思路三:使用3个计时器counter0,counter1,counter2;他们各自的作用是如下图:
counter1用于计时counter计满的次数,所以代码不用修改。
上面counter0和counter2中的en_counter0和en_counter2都是控制各个计时器是否开始计数的开关。en_counter2什么时候计数,什么时候不计数的框图如下图所示。
本文仅使用思路三进行实验。
- //功能实现led亮0.25s,灭0.5s,亮0.75s,灭1s
- module LED_ctrl5(
- input Clk,
- input Reset_n,
- input [7:0]SW,
- output reg Led
- );
-
- reg [23:0]counter0;//定义计数器位数,板上时钟资源是20ns为一个周期,所以要用计时数除以20ns来计算计时次数。最后将次数转化成二进制位,有几位就定义几位计时器
- reg [2:0]counter1;//定时7个状态
- reg [25:0]counter2;//定时1s用来表示空闲状态
- reg encounter2;
- reg encounter0;
-
- parameter MCNT0 = 12500000-1;
- parameter MCNT2 = 50000000-1;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- encounter2 <= 1'd1;//一开始就给一个有效值,等复位结束后就保持为有效值,然后题目要求就是一开始就是开始1S空闲,所以一开始counter2就开始计时。
- else if((counter1 == 7) && (counter0 == MCNT0))
- encounter2 <= 1'd1;
- else if(counter2 == MCNT2)
- encounter2 <= 1'd0;
- else
- encounter2 <= encounter2;
-
- //assign encounter0 = !encounter2;
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- encounter0 <= 1'd0;//一开始就给一个有效值,等复位结束后就保持为有效值,然后题目要求就是一开始就是开始1S空闲,所以一开始counter2就开始计时。
- else if(counter2 == MCNT2)
- encounter0 <= 1'd1;
- else if((counter1 == 7) && (counter0 == MCNT0))
- encounter0 <= 1'd0;
- else
- encounter0 <= encounter0;
-
- //计数器计数
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter0 <= 0;
- else if(encounter0)
- begin
- if(counter0 == MCNT0)
- counter0 <= 0;
- else
- counter0 <= counter0 + 1'd1;
- end
- else
- counter0 <= 0;//counter0未使能不计数
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter1 <= 0;
- else if(counter0 == MCNT0)
- counter1 <= counter1+1;
- else
- counter1 <= counter1;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- counter2 <= 0;
- else if(encounter2)
- begin
- if(counter2 == MCNT2)
- counter2 <= 0;
- else
- counter2 <= counter2 + 1'd1;
- end
- else
- counter2 <= 0;//counter0未使能不计数
-
- //使用case语句实现
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- Led <= 0;
- else if(encounter2 == 1)
- Led <= 0;
- else //if(encounter2 == 0)
- begin
- case(counter1)
- 0:Led <= SW[0];
- 1:Led <= SW[1];
- 2:Led <= SW[2];
- 3:Led <= SW[3];
- 4:Led <= SW[4];
- 5:Led <= SW[5];
- 6:Led <= SW[6];
- 7:Led <= SW[7];
- default:Led <= Led ;
- endcase
- end
- endmodule
- `timescale 1ns / 1ns
-
- module LED_ctrl0_tb();
-
- reg Clk;
- reg Reset_n;
- reg [7:0]SW;
- wire Led;
-
- LED_ctrl5 LED_ctrl5(
- .Clk(Clk),
- .Reset_n(Reset_n),
- .Led(Led),
- .SW(SW)
- );
-
- defparam LED_ctrl5.MCNT0 = 12500-1;
- defparam LED_ctrl5.MCNT2 = 50000-1;
-
- initial Clk = 1;//初始信号为高电平
- always #10 Clk = ~Clk;//延时10ns以后初始信号取反,这句话是总是执行的。
-
- //产生激励复位信号
- initial begin
- Reset_n = 0;//开始复位信号为0,有效复位
- SW = 8'b1010_1001;
- #201 Reset_n = 1;//201ns以后复位信号变为高电平,无效电平。开始仿真
- #40000000;//仿真40ms
-
- $stop;//停止仿真
- end
- endmodule
1.case语句,没有列举完的情况,需要加一个默认项列举完
- case(counter)
- MCNT*1/8 -1:led <= ctrl[0];//语句1
- 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
2.计数器可以用作时间刻度尺,每个时间都可以进行断点,然后在不同的时间点去做不同的事情。
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)//可见Reset_n复位是低电平有效
- Led <= 0;
- else if(counter == 0)
- Led <= 1;
- else if(counter == 12_500*MCNT)
- Led <= !Led;
- else if(counter == 37_500*MCNT)
- Led <= !Led;
- else if(counter == 75_000*MCNT)
- Led <= !Led;
- else
- Led <= Led;
- endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。