LED控制任务3,任务4


前言

本节包含了2个任务,任务3和任务4.下面介绍这两个任务。
任务3
在这里插入图片描述
其实也就根据拨码开关的开通和关闭来决定LED灯的亮灭。
程序不难,但有实际的意义,这是一个在程序的运行过程中能够改变程序的状态的一个程序。

任务4
在这里插入图片描述
程序进入正常的工作状态后,LED熄灭1s,1s之后再让LED输出新一轮8位的状态。

一、任务过程

通过Vivado软件实现对LED控制的仿真。

二、任务3

1.模块构建

代码如下(示例):

`timescale 1ns / 1ps

module led_ctrl2(
    Clk,
    Reset_n,
    SW,
    Led
    );
    input Clk;
    input Reset_n;
    input [7:0]SW;
    output reg Led;
       
    parameter MCNT =12500_000 - 1; 
    reg [26:0]counter0;
    //counter0计数计的是什么。是0.25s的时间间隔。
    always@(posedge Clk or negedge Reset_n)begin
    if(!Reset_n)
        counter0 <= 0;
    else if(counter0 == MCNT) //对应的是整个LED变化完整的结束所需要的时间。
        counter0 <= 0;
    else
        counter0 <= counter0 + 1'd1;
    end

    reg [2:0]counter1;   //7对应的是0111
    always@(posedge Clk or negedge Reset_n)begin
    if(!Reset_n)
        counter1 <= 0;
    else if(counter1 == 7)
        counter1 <= 0;   
    else
        counter1 <= counter1 + 1'd1;
    end
    //根据counter1不同的值指定LED的状态,通过SW不同的位对应不同的LED的值。
    always@(posedge Clk or negedge Reset_n)
    if(!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

2.激励部分

代码如下(示例):

`timescale 1ns / 1ps

module led_ctrl_tb();
   reg Clk;
   reg Reset_n;
   wire Led;  //起连接作用所以是wire类型的
   reg [7:0]SW;
    
   led_ctrl2 led_ctrl2(

    .Clk(Clk),
    .Reset_n(Reset_n), 
    .SW(SW),
    .Led(Led)
    );
    
//    defparam led_ctrl1.TIME_UNIT_MS = 1;

    defparam  led_ctrl2.MCNT = 12_500-1;   
    
    initial Clk = 1;  //初始化时钟Clk信号为逻辑高电平
    always #10 Clk = !Clk;  //每隔10ns翻转一次,模拟时钟的周期。
    
    initial begin  //模拟初始化的过程
        Reset_n = 0;  //Reset_n初始化为0
        SW = 8'b1010_1010;
        #201;         //过了201ns,Reset_n被置1
        Reset_n = 1;
        #4000000;
        SW = 8'b0000_0001;
        #20_000_000;  //8个LED灯每个间隔0.5s。所以是4s,对应的就是4000_000_000ns,减少了100倍缩短仿真的时间。
        $stop;
        
    end

endmodule

问题:
1.存在一个未设置顶层,看不到波形的问题。
2.调counter1的波形观察的时候没有看见,counter计数,发现模块代码中,else if(counter1 == 7),之前未修改,修改后解决问题。

在这里插入图片描述
得到仿真波形。

三、任务4

在这里插入图片描述
基于第4个任务,引出可控序列机。

1.模块构建

`timescale 1ns / 1ps

module led_ctrl3(
    Clk,
    Reset_n,
    SW,
    Led
    );
    input Clk;
    input Reset_n;
    input [7:0]SW;
    output reg Led;
       
    parameter MCNT0 =12500_000 - 1;  //对应的是0.25s。
    parameter MCNT2 =50_000_000 - 1;  //1s对应的时间值。
    
    reg [26:0]counter0;
    reg [26:0]counter2;
    //en_counter对应的是控制信号。用来使用不同的计数器。过程赋值,所以使用reg
    reg en_counter0;
    reg en_counter2;
    reg [2:0]counter1;   //7对应的是0111,计数输出第几个LED状态的计数器
    
    //counter0
    always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
	counter0 <= 0;
    else if(en_counter0)begin
	    if(counter0 == MCNT0)
		counter0 <= 0;
	else
		counter0 <= counter0 + 1'd1;
    end
    else
	    counter0 <= 0;

    //en_counter2部分
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
	    en_counter2 <= 1'd1;
	else if((counter1 == 7) && (counter0== MCNT0))
        en_counter2 <= 1'd1;
    else if(counter2 == MCNT2)
        en_counter2 <= 1'd0;    
        
    //en_counter0部分
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
	    en_counter0 <= 1'd0;
    else if(counter2 == MCNT2)
        en_counter0 <= 1'd1;
    else if((counter1 == 7)&& (counter0 == MCNT0))
        en_counter0 <= 1'd0;

    //counter1部分。
    
    always@(posedge Clk or negedge Reset_n)begin
    if(!Reset_n)
        counter1 <= 0;
    else if(counter1 == 7)
        counter1 <= 0;   
    else
        counter1 <= counter1 + 1'd1;
    end
    
    //counter2部分
    always@( posedge Clk or negedge Reset_n)
    if(!Reset_n)
	   counter2 <= 0;
    else if(en_counter2)begin
	if(counter2 == MCNT2)
		counter2 <= 0;
	else
		counter2 <= counter2+1'd1;
    end
    else
	   counter2 <= 0;
    
    // LED部分:根据counter1不同的值指定LED的状态,通过SW不同的位对应不同的LED的值。
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
         Led <= 0;
    else if(en_counter2 == 1)
        Led <= 1'd0;
    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

解法3:
分别计时。新的模式中,计数器有静有动。何为有静有动,另一个在计数的时候,另外一个就暂停计数。
在这里插入图片描述
不同需要的计数器

在这里插入图片描述
en_counter0的计数原理。

2.激励部分

`timescale 1ns / 1ps

module led_ctrl_tb();
   reg Clk;
   reg Reset_n;
   wire Led;  //起连接作用所以是wire类型的
   reg [7:0]SW;
    
   led_ctrl3 led_ctrl3(

    .Clk(Clk),
    .Reset_n(Reset_n), 
    .SW(SW),
    .Led(Led)
    );
    
//    defparam led_ctrl1.TIME_UNIT_MS = 1;

    defparam  led_ctrl3.MCNT0 = 12_500-1;   
    defparam  led_ctrl3.MCNT2 = 50_000-1; 
    
    
    initial Clk = 1;  //初始化时钟Clk信号为逻辑高电平
    always #10 Clk = !Clk;  //每隔10ns翻转一次,模拟时钟的周期。
    
    //怎么知道这些值的赋值也很重要,这些赋的值要能够我们方便观察结果。
    initial begin  //模拟初始化的过程
        Reset_n = 0;  //Reset_n初始化为0
        SW = 8'b1010_1001;
        #201;         //过了201ns,Reset_n被置1
        Reset_n = 1;
        #40_000_000;  //8个LED灯每个间隔0.5s。所以是4s,对应的就是4000_000_000ns,减少了100倍缩短仿真的时间。
        $stop;
        
    end

endmodule

//怎么知道这些tb文件中值的赋值也很重要,这些赋的值要能够我们方便的观察结果。
这样在状态切换的过程中就一定会出现,高电平变低电平的过程。

难点就是计数器
在这里插入图片描述

在这里插入图片描述

总结

任务3:
这是一个在程序的运行过程中能够改变程序的状态的一个程序。

任务4:
难点在于计数器的一个工作模式,计数器的工作模式不再是简单的持续计数,而是会有暂停态,有计数态。同时,计数器之间的关系也变得复杂,相互关联,相互制约。这些是做FPGA设计逻辑的时候,经常会遇到的问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值