verilog线性序列机的应用

应用1:写一个周期变化的流水灯如下图

实现思路:用计数器计数一秒的周期,然后在指定位置实现变化(想象计数器是一个线性尺子,每一个时间长度单位就是一个刻度)

代码框架:计数器实现一秒周期——在0.25秒时拉低点评

module led_run(
    Clk,
    Reset_n,
    Led
 );
    input Clk;
    input Reset_n;
    output reg Led;
    //计数一秒钟
    reg [24:0]counter;
    parameter MCNT = 50000000-1;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if(counter == MCNT)
//    else if(counter == 25'd24999)
        counter <= 0;
    else    
        counter <= counter + 1'b1;
    //控制led
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        led <= 0;
    else if(counter == 0)
        led <= 1'b1;   
    else if(counter == 12500000)
        led <= 1'b0; 
        
endmodule

注意:为何在0.25秒counter == 12500000而不是== 12500000-1

答:最大值变零的时候还依旧需要耗费一个时钟周期,而在取值的过程中需不要耗费额外的周期

应用2:写一个周期变化的流水灯如下图

按照上面的常规写法就是多写几个else if的分支就行

下面介绍另一种思路,如图,吧最小的变化周期当作一个单位

代码框架:一个周期计数器——周期内最小单位的计数——对每一个单位的电平进行赋值

module led_run(
    Clk,
    Reset_n,
    Led
 );
    input Clk;
    input Reset_n;
    output reg Led;
    //计数一秒钟
    reg [24:0]counter;
    parameter MCNT = 50000000-1;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if(counter == MCNT)
        counter <= 0;
    else    
        counter <= counter + 1'b1;

    //计数一个周期
    reg [24:0]counter0;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter0 <= 0;
    else if(counter == 12500000)
        counter0 <= 0;
    else    
        counter0 <= counter0 + 1'b1;
    //控制每一个周期的电平
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        led <= 0;
    else begin
        case(counter0)
            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

应用3:每过一段时间执行一轮8个led的状态切换

在上一个代码进行修改即可,使用一个拨码开关来对八个led的状态进赋值,在case语句中把拨码开关赋值到led即可

module led_run(
    Clk,
    Reset_n,
    sw,
    Led
 );
    input Clk;
    input Reset_n;
    input [7:0] sw;
    output reg Led;
    //计数一秒钟
    reg [24:0]counter;
    parameter MCNT = 50000000-1;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if(counter == MCNT)
        counter <= 0;
    else    
        counter <= counter + 1'b1;

    //计数一个周期
    reg [24:0]counter0;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter0 <= 0;
    else if(counter == 12500000)
        counter0 <= 0;
    else    
        counter0 <= counter0 + 1'b1;
    //控制每一个周期的电平
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        led <= 0;
    else begin
        case(counter0)
            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

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值