(6)从计数器到可控线性序列机——led实验六部曲

实验一:让一个灯亮0.25s,灭0.75s,循环

always@(posedge clk or negedge rst)
    if(!rst)
        cnt <= 0;
    else if (cnt == 49_999_999)
        cnt <= 0;
    else    
        cnt <= cnt + 1;

always@(posedge clk or negedge rst)
    if(!rst)
        led <= 0;
    else if (cnt == 37_499_999)    //灭0.75s,即计数到0.75/(20*10e-9)-1
        led <= 1;
    else if (cnt == 49_999_999)   
        led <= 0;   //亮0.25s

 

实验二:亮0.25s,灭0.5s,亮0.75s,灭1s的状态循环

parameter  max = 125_000_000;   //2.5s为一个周期
reg [26:0] cnt; 
always@(posedge clk or negedge rst)
    if(!rst)
        cnt <= 0;
    else if (cnt == 49_999_999)
        cnt <= 0;
    else    
        cnt <= cnt + 1;

always@(posedge clk or negedge rst)
    if(!rst)
        led <= 0;
    else if (cnt == max/5-1)    //0.5s,
        led <= 1;
    else if (cnt == max/2-1)   //0.5s 0.75s
        led <= 0;   
    else if (cnt == max*9/10-1)   //0.5s 0.75s 1s
        led <= 1;   
    else if (cnt == max)   //0.5s 0.75s 1s 0.25s
        led <= 0;    

  和实验一的思路差不多,不过这里我和视频写的不一样,对于第三个else if括号里的不太确定,也没用tb仿真

 

实验三:led按指定亮灭模式运行,模式未知,由用户给定,以0.25s为一个状态,8个状态为一个循环。

//2s为一个实验周期,有一个输入端口

parameter  max = 100_000_000;   //2s为一个周期

input [7:0] ctrl;   //输入端口
reg [26:0] cnt; 

always@(posedge clk or negedge rst)
    if(!rst)
        cnt <= 0;
    else if (cnt == 49_999_999)
        cnt <= 0;
    else    
        cnt <= cnt + 1;

always@(posedge clk or negedge rst)
    if(!rst)
        led <= 0;
    else if (cnt == max/8-1)    //0.25s,
        led <= ctrl[0];
    else if (cnt == max*2/8-1)   //
        led <= ctrl[1];   
    else if (cnt == max*3/8-1)   //
        led <= ctrl[2];   
    .......//后面懒得写了

  当然,还有一种方法:

 

实验三:led按指定亮灭模式运行,模式未知,由用户给定,8个状态为一个循环,每个状态的时间可自定义。

  input [7:0] ctrl;   //输入端口
  input [31:0] time;   //输入时间端口
  reg [26:0] cnt;
  reg [2:0] counter = 0;  //八个状态
//设计思路:每计满一个小状态,counter+1,然后根据counter的值去
//选择led的电平
always@(posedge clk or negedge rst)
    if(!rst)
        cnt <= 0;
    else if (cnt == time-1)
        cnt <= 0;
    else    
        cnt <= cnt + 1;

always@(posedge clk or negedge rst)
    if(!rst)
        counter <= 0;
    else if (cnt == time-1)
        counter <= counter + 1;
always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (counter == 0) // led <= ctrl[0]; else if (counter == 1) // led <= ctrl[1]; else if (counter == 2) // led <= ctrl[2]; .......//后面懒得写了

 

实验四:多个led各自在不同的模式下循环闪烁

  差不多就是这样的思路:

 

实验五:每隔10ms让led的8个状态循环执行一次

  设计思路:

   代码:

input [7:0] ctrl;   //输入端口
reg [26:0] cnt; 
reg [26:0] cnt1; 
reg [31:0] time; 
reg [2:0] counter = 0;  //八个状态
reg en;

//计满一个小状态
always@(posedge clk or negedge rst)
    if(!rst)
        cnt <= 0;
    else if (en) begin 
        if  (cnt == time-1)
                cnt <= cnt + 1;
        end
    else    
        cnt <= cnt + 1;

//计满10ms
always@(posedge clk or negedge rst)
    if(!rst)
        cnt1 <= 0;
    else if (cnt == 500000-1)
        cnt1 <= 0;
    else    
        cnt1 <= cnt1 + 1;

//状态切换
always@(posedge clk or negedge rst)
    if(!rst)
        counter <= 0;
    else if(en)
        begin
            if (cnt == time-1)
                counter <= counter +1;  
        end
    else    
        counter <= 0; 
        

//使能控制,cnt1为0(即新的10ms开始)时拉高,8个状态完成后拉低
always@(posedge clk or negedge rst)
    if(!rst)
        en <= 0;
    else if (cnt1 == 0)
        en <= 1;
    else if(counter == 7)
        en <= 0;

always@(posedge clk or negedge rst)
    if(!rst)
        led <= 0;
    else if (counter == 0)    //
        led <= ctrl[0];
    else if (counter == 1)   //
        led <= ctrl[1];   
    else if (counter == 2)   //
        led <= ctrl[2];   
    .......//后面懒得写了

    注意的是,只有在en使能的情况下,计一个小状态的计数和状态切换的计数才能够计数,否则需要暂停

posted @ 2024-04-06 01:39  xuxuxu69  阅读(20)  评论(0编辑  收藏  举报