FPGA学习1--从计数器到状态机

小梅哥FPGA教学视频跟学记录11.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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值