小梅哥FPGA教学视频跟学记录1
1.LED灯亮0.25秒,灭0.75秒的状态循环亮灭
设计思路:使用计数器,分别满0.25秒和0.75秒时对LED进行操作。
默认LED为1(亮),计数器满0.25秒,使LED为0;计数器满0.75秒,使LED为1,计数器清零,进入下一周期。所以计数器最大值为1秒(0.25+0.75),设MCNT=1s所对应周期数
开发板的晶振为50MHz,对应得到时钟周期为20ns。可得
0.25秒需要计数 250000000/20=12,500,000个周期
0.75秒需要计数750000000/20=37,500,000个周期
设计文件代码如下:
//1s频率闪烁,亮0.25s,灭0.75s
//50MHz =20ns
module counter_led(
Clk,
Reset_n,
led
);
input Clk;
input Reset_n;
output reg led;
reg [25:0]counter;
parameter MCNT=49999999; //一个周期为1s,从0开始计数,所以减1
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
led<=1;
else if (counter == MCNT/4)
led<=0;
else if(counter == MCNT)
led<=1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <=0;
else if(counter==MCNT)
counter <=0;
else
counter <=counter+1'b1;
endmodule
2.让LED灯亮0.25s,灭0.5s,亮0.75s,灭1s
MCNT=2.5s对应周期数
//1s频率闪烁,亮0.25s,灭0.5s,亮0.75s,灭1s
//50MHz =20ns
module counter_led_2(
Clk,
Reset_n,
led
);
input Clk;
input Reset_n;
output reg led;
reg [26:0]counter;
parameter MCNT=125000000;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <=0;
else if(counter==MCNT-1)
counter <=0;
else
counter <=counter+1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
led<=1;
else if (counter == MCNT/10-1)
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
3.让LED灯按照指定亮灭模式亮灭,由用户指定。0.25s为一个亮灭状态周期,8个周期为一个循环。
//0.25s一个周期,8个周期一循环,每个周期亮灭由用户随机指定
//50MHz =20ns
module counter_led_3(
Clk,
Reset_n,
Ctrl,
led
);
input Clk;
input Reset_n;
input [7:0] Ctrl;
output reg led;
reg [26:0]counter;
parameter MCNT=100000000;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0;
else if(counter==MCNT-1)
counter <= 0;
else
counter <= counter+1'b1;
//方法一用else if语句
// always@(posedge Clk or negedge Reset_n)
// if(!Reset_n)
// led<=1;
// else if (counter == MCNT/8-1)
// 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];
//方法二:用case语句
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
led<=1;
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];
endcase
endmodule
4.在3的基础上,每个变化周期时间由用户指定
//一个周期是时长由用户指定,8个周期一循环,每个周期亮灭由用户随机指定
//50MHz =20ns
//Time为用户指定时长,counter作为基本时间计数器,记一个周期
//counter2(三位)作为周期计数器,记第几个周期
//counter=Time-1,即为一个周期,counter2+1,加到7再加1则为0(自动清零)
module counter_led_4(
Clk,
Reset_n,
Ctrl,
Time,
led
);
input Clk;
input Reset_n;
input [7:0] Ctrl;
input [31:0] Time;
output reg led;
reg [26:0]counter;
reg [2:0]counter2;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0;
else if(counter==Time-1)
counter <= 0;
else
counter <= counter+1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2 <= 0;
else if(counter==Time-1)
counter2 <= 0;
else
counter2 <= counter2+1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
led<=1;
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
6.每隔10ms,让LED的一个8状态循环执行一次。(每个状态的变化时间值小一点,方便测试,比如设置10us)
使用计数器
//一个周期是时长由用户指定,8个周期一循环,每个周期亮灭由用户随机指定
//50MHz =20ns
//Time为用户指定时长,counter作为基本时间计数器,记一个周期
//counter2(三位)作为周期计数器,记第几个周期
//counter=Time-1,即为一个周期,counter2+1,加到7再加1则为0(自动清零)
module counter_led_6(
Clk,
Reset_n,
Ctrl,
Time,
led
);
input Clk;
input Reset_n;
input [7:0] Ctrl;
input [31:0] Time;
output reg led;
reg [13:0]counter; //基本时间计数器
reg [2:0]counter2; //8状态计数
reg [18:0]counter3; //每隔10ms清零10ms 500000
reg EN; //计数使能
parameter MCNT=500000;//10ms
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0;
else if(counter==Time-1)
counter <= 0;
else
counter <= counter+1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2 <= 0;
else if (counter==Time-1 && EN ==1)
counter2 <= counter2+1'b1;
else if(counter3==MCNT-1)
counter2 <= 0;
else
counter2 <= counter2;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter3 <= 0;
else if(counter3==MCNT-1)
counter3 <= 0;
else
counter3 <= counter3 +1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
EN <= 1;
else if (counter3 > Time*7 -1)
EN <=0;
else
EN <=1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
led<=1;
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 <= 0;
endcase
endmodule
对应的tb文件代码:
//一个周期是时长由用户指定,8个周期一循环,每个周期亮灭由用户随机指定
//50MHz =20ns
//Time为用户指定时长,counter作为基本时间计数器,记一个周期
//counter2(三位)作为周期计数器,记第几个周期
//counter=Time-1,即为一个周期,counter2+1,加到7再加1则为0(自动清零)
module counter_led_6(
Clk,
Reset_n,
Ctrl,
Time,
led
);
input Clk;
input Reset_n;
input [7:0] Ctrl;
input [31:0] Time;
output reg led;
reg [13:0]counter; //基本时间计数器
reg [3:0]counter2; //8状态计数
reg [18:0]counter3; //每隔10ms清零10ms 500000
reg EN; //计数使能
parameter MCNT=500000;//10ms
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0;
else if(counter==Time-1)
counter <= 0;
else
counter <= counter+1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2 <= 0;
else if (counter==Time-1 && EN ==1)
counter2 <= counter2+1'b1;
else if(counter3==MCNT-1)
counter2 <= 0;
else
counter2 <= counter2;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter3 <= 0;
else if(counter3==MCNT-1)
counter3 <= 0;
else
counter3 <= counter3 +1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
EN <= 1;
else if (counter3 > Time*8 -1)
EN <=0;
else
EN <=1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
led<=0;
else if (EN==0)
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 <= 0;
endcase
endmodule
可以得到仿真结果:
从图中可以看到counter2计数到第9个状态之后直到第一个10ms结束才重新开始计数,led转换也符合预期(Ctrl=8'b10101010),led分别为01010101;如果counter2保持为7,所以LED也保持为1.所以代码中设计counter2加到8,可以使得led在默认状态下为0