从计数器到可控线性序列机——LED实验进化六部曲

1.让LED灯按照亮0.25秒,灭0.75秒的状态循环亮灭。
2. 让LED灯按照亮0.25秒,灭0.5秒,亮0.75秒,灭1秒的状态循环亮灭。
3. 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定;以0.25秒为一个变化周期,8个变化状态为一个循环。
4. 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定;8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。
5.让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化。
6. 每隔10ms,让 LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试, 比如设置为10us)


目录

实验一  让LED灯按照亮0.25秒,灭0.75秒的状态循环亮灭

功能分析

设计输入

功能仿真代码

功能仿真结果

实验二  让LED灯按照亮0.25秒,灭0.5秒,亮0.75秒,灭1秒的状态循环亮灭

功能分析

设计输入

         功能仿真代码

         功能仿真结果

 实验三  让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。以0.25秒为一个变化周期,8个变化状态为一个循环。

功能分析

设计输入

功能仿真代码

功能仿真结果

实验四  让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。

功能分析

设计输入

功能仿真代码

功能仿真结果

 实验五  让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化

功能分析

设计输入

功能仿真代码

功能仿真结果

 知识点总结

实验六 每隔10ms,让 LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试, 比如设置为10us)

功能分析

设计输入

功能仿真代码

功能仿真结果

知识点总结


实验一  让LED灯按照亮0.25秒,灭0.75秒的状态循环亮灭

功能分析

一个循环共两个状态,共1s,设置一个计数周期为1s,

设置Led初始状态为高电平,即处于亮的状态,

经过0.25s,即到0.25s时,此时计数到四分之一个周期,使Led反转一次,LED为0;

经过0.75s,即到1s时,此时一个计数周期结束,使Led反转一次,LED为1。

设计输入

module counter_led_1(
    Clk,
    Reset_n,
    Led
);

    input Clk;
    input Reset_n;
    output reg Led;
    
    reg [25:0]counter;
    
//计数周期为1s,1_000_000_000ns/20ns = 50_000_000次
    parameter MCUT = 50_000_000;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if (counter == MCUT - 1 )
        counter <= 0;
    else
         counter <= counter + 1'b1;
  
 //      LED亮0.25s,灭0.75s  
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
       Led <= 0;    //复位的时候,即计数开始的时候,LED为0
    else if(counter == MCUT*3/4 - 1) // 灭0.75秒
        Led <= 1;   //计数到四分之三个周期,即0.75s的时候,LED为1
    else if(counter == MCUT - 1)     //亮0.25s
        Led <= 0;    //一个计数周期结束,即1s的时候,LED为0
    
endmodule

功能仿真代码

`timescale 1ns/1ns

module counter_led_1_tb;

    reg Clk;
    reg Reset_n;
    wire Led;
    
    counter_led_1
    #(
    .MCUT(50000)
    )
    
    counter_led_1(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Led(Led)
    );
    
    initial Clk=1;
    always #10 Clk=!Clk;
    
    initial begin
        Reset_n=0;
        #201;
        Reset_n=1;
        #20000000;
        $stop;
    end

endmodule

功能仿真结果

实验二  让LED灯按照亮0.25秒,灭0.5秒,亮0.75秒,灭1秒的状态循环亮灭

功能分析

一个循环共有四个状态,共2.5s,设置一个计数周期为2.5s,设置Led初始状态为1,即处于亮的状态;

经过0.25s,即到0.25s时,此时计数到十分之一个周期,使Led反转一次,LED为0;

经过0.5s,即到0.75s时,此时计数到十分之三个周期,使Led反转一次,LED为1;

经过0.75s,即到1.5s时,此时计数到十分之六个周期,使Led反转一次,LED为0;

经过1s,即到2.5s时,此时一个计数周期结束,使Led反转一次,LED为1。

设计输入

module counter_led_2(
    Clk,
    Reset_n,
    Led
);

    input Clk;
    input Reset_n;
    output reg Led;
    
    reg [25:0]counter;
    
//计数周期为2.5s,2_500_000_000ns/20ns = 125_000_000次
    parameter MCUT = 125_000_000;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if (counter == MCUT - 1 )
        counter <= 0;
    else
         counter <= counter + 1'b1;
  
 //       LED亮0.25s,灭0.5s,亮0.75s,灭1s;共2.5s 
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
       Led <= 1;    //复位的时候LED为1
    else if(counter == MCUT*1/10 - 1)
        Led <= 0;   //计数到十分之一个周期,即0.25s的时候,LED为0
    else if(counter == MCUT*3/10 - 1)
        Led <= 1;    //计数到十分之三个周期,即0.75s的时候,LED为1
    else if(counter == MCUT*6/10 - 1)
        Led <= 0;   //计数到十分之六个周期,即1.5s的时候,LED为0
    else if(counter == MCUT - 1)
        Led <= 1;   //计数到一个周期,即2.5s的时候,LED为1
    
endmodule

功能仿真代码

`timescale 1ns/1ns

module counter_led_2_tb;

    reg Clk;
    reg Reset_n;
    wire Led;
    
    counter_led_2
    #(
    .MCUT(125000)
    )
    
    counter_led_2(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Led(Led)
    );
    
    initial Clk=1;
    always #10 Clk=!Clk;
    
    initial begin
        Reset_n=0;
        #201;
        Reset_n=1;
        #2000000;
        $stop;
    end

endmodule

功能仿真结果

 实验三  让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。以0.25秒为一个变化周期,8个变化状态为一个循环。

功能分析

一个循环共有八个状态,一个状态0.25s,则一个循环周期为2s,设置一个计数周期为2s;

设置一个指定亮灭状态的输入端口Ctrl,Ctrl为八位,每一位控制Led的一个状态。

设计输入

module counter_led_3(
    Clk,
    Reset_n,
    Ctrl,
    Led
    );
    
    input Clk;
    input Reset_n;
    input [7:0]  Ctrl;
    output reg Led;
    
    
// 八个状态,一个状态0.25s,八个状态一个循环,则一个循环为2s
//计数次数为,2_000_000_000ns/20ns=100_000_000次,计数器要用27位
    reg [26:0] counter;
    parameter MCUT = 100_000_000;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
     counter <= 0;
    else if (counter == MCUT-1)
      counter <= 0;
    else
      counter <= counter + 1'b1;
      
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
     Led <= 0;
    else if(counter == MCUT*1/8 - 1)
     Led <= Ctrl[0];
    else if(counter == MCUT*2/8 - 1)
     Led <= Ctrl[1];  
    else if(counter == MCUT*3/8 - 1)
     Led <= Ctrl[2];
    else if(counter == MCUT*4/8 - 1)
     Led <= Ctrl[3];
    else if(counter == MCUT*5/8 - 1)
     Led <= Ctrl[4];
    else if(counter == MCUT*6/8 - 1)
     Led <= Ctrl[5];
    else if(counter == MCUT*7/8 - 1)
     Led <= Ctrl[6];
    else if(counter == MCUT*8/8 - 1)
     Led <= Ctrl[7];  

//     always@(posedge Clk or negedge Reset_n)
//    if(!Reset_n)
//     Led <= 0;
//    else case(counter)
//        MCUT*1/8 - 1: Led <= Ctrl[0];
//        MCUT*2/8 - 1: Led <= Ctrl[1];
//        MCUT*3/8 - 1: Led <= Ctrl[2];
//        MCUT*4/8 - 1: Led <= Ctrl[3];
//        MCUT*5/8 - 1: Led <= Ctrl[4];
//        MCUT*6/8 - 1: Led <= Ctrl[5];
//        MCUT*7/8 - 1: Led <= Ctrl[6];
//        MCUT*8/8 - 1: Led <= Ctrl[7];
//        default:Led <= Led;
//     endcase
    

endmodule

功能仿真代码

`timescale 1ns/1ns

module tb_counter_led_3;

    reg Clk;
    reg Reset_n;
    reg [7:0]Ctrl;
    wire Led;

 counter_led_3 
 #(
    .MCUT(125000)
 )
 
    counter_led_3(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Ctrl(Ctrl),
        .Led(Led)
    );

    initial Clk = 1;
    always #10 Clk=!Clk;
    
    initial begin
        Reset_n = 0;
        Ctrl = 0;
        #201;
        Reset_n = 1;
        #2000;
        Ctrl = 8'b1010_0110;
        #2000000;
        $stop;
     end

endmodule 

功能仿真结果

实验四  让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。

功能分析

化零为整,设置八个相同时间段,第一个计数器计数每个时间段,位数和每个时间段时间相匹配,Time的值为计数次数,即代表每个时间段是时间长短,计数器位数和Time位数一致;
第二个计数器计数八个时间段,共8次,需要三位的计数器;
根据计数器2的值,共八个值,通过八位的Ctrl分别控制八个信号的亮灭状态。

设计输入

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 [7:0]Led;

    reg [31:0]counter;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if (counter == Time - 1)
        counter <= 0;
    else
        counter <= counter + 1'b1;
        
    reg[2:0]counter2;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter2 <= 0;
    else if (counter == Time - 1)
        counter2 <= counter2 + 1'b1;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_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

功能仿真代码

`timescale 1ns/1ns

module tb_counter_led_4;

    reg Clk;
    reg Reset_n;
    reg [7:0]Ctrl;
    reg [31:0]Time;
    wire Led;
    
    counter_led_4 counter_led_4(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Ctrl(Ctrl),
        .Time(Time),
        .Led(Led)
);

    initial Clk = 1;
    always #10 Clk=!Clk;

    initial begin
        Reset_n = 0;
        Ctrl = 0;
        #201;
        Reset_n = 1;
        #2000;
        Time = 2500; // 2500*20ns=50_000ns 一个时间段
        Ctrl = 8'b1000_0110;
        #2000000;
        $stop;
     end

endmodule

功能仿真结果

 实验五  让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化

功能分析

与实验四基本设计思想相同,区别在于实验四为一个Ctrl控制一个Led,该实验为两个Ctrl控制两个Led

设计输入

module counter_led_5(
    Clk,
    Reset_n,
    CtrlA,
    CtrlB,
    Time,
    Led
);

    input Clk;
    input Reset_n;
    input [7:0]CtrlA,CtrlB;
    input [31:0]Time;
    output reg [1:0]Led;

    reg [31:0]counter;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if (counter == Time - 1)
        counter <= 0;
    else
        counter <= counter + 1'b1;
        
    reg[2:0]counter2;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter2 <= 0;
    else if (counter == Time - 1)
        counter2 <= counter2 + 1'b1;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        Led <= 0;
     else case(counter2)
        0:begin Led[0] <= CtrlA[0];Led[1] <= CtrlB[0];end
        1:begin Led[0] <= CtrlA[1];Led[1] <= CtrlB[1];end
        2:begin Led[0] <= CtrlA[2];Led[1] <= CtrlB[2];end
        3:begin Led[0] <= CtrlA[3];Led[1] <= CtrlB[3];end
        4:begin Led[0] <= CtrlA[4];Led[1] <= CtrlB[4];end
        5:begin Led[0] <= CtrlA[5];Led[1] <= CtrlB[5];end
        6:begin Led[0] <= CtrlA[6];Led[1] <= CtrlB[6];end
        7:begin Led[0] <= CtrlA[7];Led[1] <= CtrlB[7];end
        default:Led <= Led;
     endcase
endmodule

功能仿真代码

`timescale 1ns/1ns

module tb_counter_led_5;

    reg Clk;
    reg Reset_n;
    reg [7:0]CtrlA,CtrlB;
    reg [31:0]Time;
    wire [1:0]Led;
    
    counter_led_5 counter_led_5(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .CtrlA(CtrlA),
        .CtrlB(CtrlB),
        .Time(Time),
        .Led(Led)
);

    initial Clk = 1;
    always #10 Clk=!Clk;

    initial begin
        Reset_n = 0;
        CtrlA = 0;
        CtrlB = 0;
        #201;
        Reset_n = 1;
        #2000;
        Time = 2500; // 2500*20ns=50_000ns 一个时间段
        CtrlA = 8'b1000_0110;
        CtrlB = 8'b0101_0011;
        #2000000;
        $stop;
     end

endmodule

功能仿真结果

 知识点总结

通过计数器序列的方式控制最小时间单位一致的多个信号,在SPI,IIC总线中有应用

实验六 每隔10ms,让 LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试, 比如设置为10us)

功能分析

计数器counter0计数一个大的时间段,为10ms,在这一个大的时间段内,设置一个EN,当EN为高时,LED的一个8状态循环执行一次,执行完之后,EN拉低;

在EN拉高时,counter2计数

设计输入

//每隔10ms,让 LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试, 比如设置为10us)


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 [31:0]counter;
    reg EN;
    
    reg [18:0]counter0; //10ms周期计数器
    reg[2:0]counter2;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter0 <= 0;
    else if (counter0 == 500_000 - 1)
        counter0 <= 0;
    else
        counter0 <= counter0 + 1'b1;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        EN <= 0;
    else if (counter0 == 0)
        EN <= 1;
    else if ((counter2 == 7)&&(counter == Time - 1))//counter2 == 7维持满一个时间段
        EN <= 0; 
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if (EN)begin
        if(counter == Time - 1)
            counter <= 0;
        else
            counter <= counter + 1'b1;
    end
    else
        counter <= 0;
        
        
    //reg[2:0]counter2;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter2 <= 0;
    else if (EN)begin
        if(counter == Time - 1)
            counter2 <= counter2 + 1'b1;
     end
     else
        counter2 <= 0;
        
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_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

功能仿真代码

`timescale 1ns/1ns

module tb_counter_led_6;

    reg Clk;
    reg Reset_n;
    reg [7:0]Ctrl;
    reg [31:0]Time;
    wire Led;
    
    counter_led_6 counter_led_6(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Ctrl(Ctrl),
        .Time(Time),
        .Led(Led)
);

    initial Clk = 1;
    always #10 Clk=!Clk;

    initial begin
        Reset_n = 0;
        Ctrl = 0;
        #201;
        Reset_n = 1;
        #2000;
        Time = 25000; // 25000*20ns=500_000ns 一个时间段
        Ctrl = 8'b0100_0110;
        #200000000;
        $stop;
     end

endmodule

功能仿真结果

知识点总结

可将仿真中用到的所有端口的波形全部显示,用于功能调试

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值