隔10ms让led亮8种状态1010_1010

一、如何隔10ms发送8bit的数据 , 让led实现这8bit的数据

1. 想实现的led样式

想要让一个led灯每隔10ms就重新按照 1010_1010 流一遍。其中 1 代表高电平,0 代表低电平。右边是低位,左边是高位。也就是先灭,再亮,再灭,再亮…直到亮完最后一位。这个过程包含在10ms内,10ms一到,重新发数据,然后先灭,再亮,再灭,再亮…直到亮完最后一位…一直重复。

2. 具体数据怎么发,其中的时间怎么定

2.1 一组数据的存储

1个 led 要实现完一组的 1010_1010 ,也就是先亮0,隔一点时间再亮1,再隔一点时间亮0(这样的描述对应1010_1010),中间的间隔时间,可以是1ms,这个正好符合人眼习惯。为了准备 1ms ,这里设置了一个定时器 cnt ,从0加到1ms,到时间了就切换下一个led的亮灭状态。对led的赋值可以选择隔1ms,重新给led赋值,如果这样做,会让一组数据只传输一遍就停止了。

2.2 定时循环传数据

也可以把1个字节的数据存在数组里面,1ms切换一个元素。用序号来取数组里面的值,序号先是0,1ms之后+1,直到序号是7的时候,重新清零,继续加,继续清零。这样就可以循环取8位里的每一位值了。为了取完8个bit,这里装一个2级计数器 cnt2,来记取数据的序号。项目想要达到的效果是隔10ms发一次数据,那led亮完最后一位的时候,消耗了7ms,要等待3ms再重新发数据。可以选择写一个3ms计数器,不过还是引入一个En使能信号吧。

2.3 如何理解En信号

在En信号拉高的时候,允许传数据,cnt 和 cnt2 可以计数;En失能的时候 ,不传数据,所以cnt 和 cnt2 通通不计数。这样一旦一组数据传完,就停止传数据,直到10ms到了再传下一组数据。这样想的话,可能还需要创建一个10ms 计数器 cnt_10ms ,cnt_10ms为0的时候,En信号拉高;传输完成En信号拉低。其中无论En信号是否使能,这个计数器都不受影响。

2.4 En信号的疑问

En信号的拉高拉低,不是依靠简单的时间划分:前7ms使能,后3ms失能——这样的做法相当于直接写一个3ms计数器。

En信号的拉高拉低是依靠判断 “ 数据是否传输完成 ” 来控制的。这样,万一之后传完一组数据花费的时间,不是7ms,而是任何其他的时间,也不用依靠更改后面的3ms来控制En信号了,继而凑成10ms。

二、代码

1. 设计代码

module Q6(
input  sys_clk               ,
input  rst_n                 ,
input  [7:0] ctrl            ,
input  [31:0] time_ctrl      ,
output reg led
    );
//---------------计数的变量--------------------//
parameter time_10ms=500_000;
reg [31:0] cnt;//基本计时器
reg [3:0] cnt2;//想要传输的数字传到第几位了,记序号
reg [18:0] cnt_10ms;//每10ms传输一次8位数据
reg En;
//-----------------基本时钟--------------------///
always@(posedge sys_clk)
if(!rst_n)
    cnt<=0;
else if(En)begin
    if (cnt==time_ctrl-1)
        cnt<=0;
    else
        cnt<=cnt+1;
end
else
    cnt<=0;
//--------------------2级时钟--------------------
always@(posedge sys_clk)
if(!rst_n)
    cnt2<=0;
else if(En)begin
    if(cnt==time_ctrl-1)
        cnt2<=cnt2+1; end  
else//(!En)
    cnt2<=0;
//10ms时钟/
always@(posedge sys_clk)
if(!rst_n)
    cnt_10ms<=0;
else if(cnt_10ms==time_10ms-1)
    cnt_10ms<=0;
else
    cnt_10ms<=cnt_10ms+1;
//--------------------En使能信号--------------------///
always@(posedge sys_clk)
if(!rst_n)
    En<=0;
else if(cnt_10ms==0)
    En<=1;
else if(cnt2==7 && cnt==time_ctrl-1)
    En<=0;
else
    En<=En;
//--------------------LED----------------------------
always@(posedge sys_clk)
if(!rst_n)
    led<=1'b0;
else
    case(cnt2)
        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

2. 测试代码

`timescale 1ns / 1ps
module tb;
//-------------------例化-------------------//
reg sys_clk               ;  
reg rst_n                 ;  
reg [7:0] ctrl            ;  
reg [31:0] time_ctrl      ;  
wire led                  ;

Q6 q6(
.  sys_clk     (sys_clk  )          ,
.  rst_n       (rst_n    )          ,
.  ctrl        (ctrl     )          ,
.  time_ctrl   (time_ctrl)          ,
.  led         (led      )
    );
//-------------------时钟-------------------///
initial begin 
    sys_clk=0;
    forever #10 sys_clk=~sys_clk;
end

//-------------------复位-------------------//
initial begin 
    rst_n=0;
    #50 rst_n=1;
end

//-------------------ctrl 传输的数据-------------------///
initial begin 
    ctrl=8'd0;
    #100 ctrl=8'b1010_1010;//波形是先低位再高位---0101_0101----
end

//-------------------time_ctrl 想要隔多久变化下一个灯-------------//
initial begin 
    time_ctrl=32'd0;
    #120 time_ctrl=32'd250_00;//10ms(500_000) 发送一次数据,这里设置每个数据隔10ms的 1/20(250_00)继续发送下一个数据
end
endmodule

3. 仿真图

-------------p1---------------------En信号的一个周期确实是10ms
在这里插入图片描述
------------p2------------------我这里1bit 与 1 bit之间的时间间隔是 0.5 ms

三、希望大家可以多多 交流评论,我们一起学习FPGA

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值