受控线性序列机

题目:有一个中的周期信号(此处为10ms),在该10ms中定义了led的8个状态,其中每个状态为0.1ms。即在周期为10ms的程序中,前0.8msled根据控制亮灭,0,8ms到10ms这一段led灭

首先是一段错误代码

`timescale 1ns / 1ps
module ledflash4(
    input clk,
    input rest,
    input [7:0]ctrl,  //8种状态定义
  //  input [31:0]T,    //总的周期时间
    input [31:0]Time,//一个状态的周期时间
    output reg led
    );
    
    reg [15:0]counter3;//总的周期的计数值
    reg [31:0]counter;//一个状态的小周期时间的计数值
    reg [2:0]counter2;//八种状态的计数值
  
    reg i;//判断一个总的周期内是否要进行8状态循环,如果需要进行则赋值1,否则为0.
///判断是否达到总周期时间十毫秒counter3/
always@(posedge clk or negedge rest)
if(!rest)
    counter3<=0;
else if(counter3==500000-1)
    counter3<=0;
else    
    counter3<=(counter3+1'b1);
     
判断i///	
always@(posedge clk or negedge rest)
if(!rest)
    i<=0;
else if(counter3==0)//在每一次10ms的开始,是i为1,进行8状态循环
	i<=1;
else if(counter2==7)//在完成一次8状态计时后,让i为0,10ms完成一次任务!!!!!!!!!!!!!错误的原因在此处!!!!!!!!!!!!
	i<=0;
	    
/一个状态的小周期时间counter//
always@(posedge clk or negedge rest)
if(!rest)
    counter<=0;
else if(i)//只有i为1时,才能进行led亮灭。此时counter计数
    begin
    if(counter==Time-1)//完成一次周期
        counter<=0;
    else    
        counter<=(counter+1'b1);    
    end
else                    //i为0,led保持全灭,因此counter不计数 
    counter<=0; 

/led八状态循环counter2
always@(posedge clk or negedge rest)
if(!rest)
    counter2<=0;
else if(i)//只有i为1时,才能进行led亮灭
begin
if(counter==Time-1)//判断完成一次小周期
        counter2<=counter2+1'b1;//若完成一次小周期,counter2刚好是3位,即0~7.因此不用使用else来让其counter2<=0
end
else
    counter2<=0;//i=0时,counter2不计数        
led八状态赋值///
always@(posedge clk or negedge rest)
if(!rest)
    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

上述方程似乎看着没有问题,但通过仿真结果,可以看出问题:
在这里插入图片描述

可以看到led在[0]~[6]时都没有任何问题,但是在[7]处,led是很短暂的方波。其原因是程序里在判断i的状态时

always@(posedge clk or negedge rest)
if(!rest)
    i<=0;
else if(counter3==0)//在每一次10ms的开始,是i为1,进行8状态循环
	i<=1;
else if(counter2==7)//在完成一次8状态计时后,让i为0,10ms完成一次任务!!!!!!!!!!错误的原因在此处!!!!!!!!!
	i<=0;

else if(counter2==7)是当counter2为7时,就立刻让i=0,而此时case里面判断counter2为7的语句还没执行结束。因此会出现上面时序图的错误。

只需在判断i的程序里再添加一个条件即可:

always@(posedge clk or negedge rest)
if(!rest)
    i<=0;
else if(counter3==0)
	i<=1;
else if((counter2==7)&&(counter==Time-1))
	i<=0;

else if((counter2==7)&&(counter==Time-1))在counter2=7时,counter此时再经历一个小循环。这样就相当于把状态7运行结束了。这样就可以运行成功了。如下图:
在这里插入图片描述

看到这应该认为就结束了,但是更改ctrl后发现了一个小问题

/led八状态循环counter2
always@(posedge clk or negedge rest)
if(!rest)
    counter2<=0;
else if(i)//只有i为1时,才能进行led亮灭
begin
if(counter==Time-1)//判断完成一次小周期
        counter2<=counter2+1'b1;//若完成一次小周期,counter2刚好是3位,即0~7.因此不用使用else来让其counter2<=0
end
else
    counter2<=0;//i=0时,counter2不计数

的最后一句

else
    counter2<=0;//i=0时,counter2不计数

是当i=0,即已经结束8状态的时候,让counter2为0,回到原始状态。可是此处默认的是counter2=0,在case语句中会一直判断为case(0),使得led一直处于ctrl[0]的状态。

如下图,当ctrl=10000111,当结束完led8状态,counter2此时赋值为0,则case一直认为要赋值led<=ctrl[0]的状态,此时ctrl[0]是1。在时序图显示的就是在[7]到下一个周期的[0]之间led为1的情况。
在这里插入图片描述
这种错误很好解决,只需在case判断语句中添加判断i的条件语句即可

else if(i)
    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
 else
    led<=0; 

在这里插入图片描述
解决好的时序图

至此,该程序运用了一个i来当作判断
总结:case语句,没有列举完的情况,需要加一个默认项列举完

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RonaldoM要努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值