状态机-学习记录

从别人那学习的,要转载还是什么嘛?
https://blog.csdn.net/CLL_caicai/article/details/104427711
这是学习来源的网址,这应该就不会侵权了,要是侵权了就联系我,我就改一下
接下来步入正题
学习三段式状态机的过程中,我把状态转移条件写错了,仿真中出现了问题,所以这里纪记录以下
对本设计说明:
输入:clk、rst_n
输出:seq
功能:三段式状态机控制输出1011序列
首先是正确的结果:
从图中可以发现,当c_state是3时,下一个clk就输出序列中的第一个数字“1”,之后就按照“011”的顺序输出;这也就对应着状态0的时候输出1,状态1的时候输出0,状态2输出1,状态3输出1。这个也就解释了代码中“=”和“<=”的使用情况。
在这里插入图片描述
对应代码展开再看一下:
(1)状态转移部分:使用非阻塞赋值,当n_state发生变化是,下一个clk后c_state才变化,和仿真图中是对应的上的

always @(posedge clk or negedge rst_n)
begin
  if(!rst_n)
    c_state <= s0;
  else 
    c_state <= n_state;
end

突发奇想,我把这个改成阻塞赋值试一下,报错了

Error (suppressible): (vsim-3601) Iteration limit 10000000 reached at time 10 ns.

翻译了一下:
错误(可禁止):(vsim-3601) 在 10 ns 时达到迭代限制 10000000。
查了一下问题,也有关于这个的帖子:
有关这个问题描述的链接
里边写的是: 代码中存在逻辑回环,即将一个组合逻辑单元赋值产生的敏感变量与另一个组合逻辑相关,同时作为另一个组合逻辑单元的敏感变量。
奥!是因为下边的转台转移条件也是组合逻辑模块,它的敏感变量是c_state,而c_state是这个模块产生的敏感变量
行,那就放弃这个想法了
(2)状态转移条件:这里是组合逻辑,阻塞赋值,也就是当c_state变化时,n_state立刻变化,同时的,感觉这里还是挺巧妙的,c_state变成n_state的状态,然后n_state变成下一个状态,写代码的真厉害!

always @(c_state or rst_n)//这里没有posedge negedge,也不是clk
begin
    if(!rst_n)
        begin
            n_state = s0; 
        end
    else 
        begin
            case(c_state)
            s0:n_state = s1;//注意这里用的是=,这是为什么
            s1:n_state = s2;
            s2:n_state = s3;
            s3:n_state = s0;
            default:n_state = s0;
            endcase
        end
end

从代码的注释中就可以看出我当时犯了两个错误,
①case中使用的<=;
②always@()中写的是clk和rst_n两个信号,所以我觉得以后写组合逻辑还是直接写@(*)好了,这样就可以避免习惯写成时序逻辑的形式
------还是再记录一下错误代码对应的仿真结果:把c_state写成clk

//状态转移条件
always @(clk or rst_n)//这里没有posedge negedge,也不是clk
begin
    if(!rst_n)
        begin
            n_state = s0; 
        end
    else 
        begin
            case(c_state)
            s0:n_state = s1;//注意这里用的是=,这是为什么
            s1:n_state = s2;
            s2:n_state = s3;
            s3:n_state = s0;
            default:n_state = s0;
            endcase
        end
end

看一下仿真结果,先只看n_state,其第一次变化是在rst_n由低变高时,这时clk时上升沿的状态(那如果rst_n没处于clk的上升沿,n_state还会变吗???);第二次以及后边每一次都是在clk下降沿的时候,clk下降沿之前c_state发生一次变化,和这个变化不同步,和clk的下降沿同步,所以是随着always@()内的敏感信号发生变化的
在这里插入图片描述
针对上边的问题,我把rst_n的上升沿和clk的上升沿时刻时间差开了,得到结果如下:n_state在rst_n的上升沿处发生改变,所以是敏感信号之间or的关系
在这里插入图片描述
总结一下:

  • 组合逻辑的"always@()“和”="要注意
  • 仿真结果中,组合逻辑的输出信号是随敏感信号同时变化的,阻塞赋值的体现
  • 组合逻辑中,只有always@()中的敏感信号变化时才会变化,即使下边代码中写的信号和敏感信号不一样,也时随着敏感信号发生变化

(3)输出部分
case中是根据n_state输出结果,这样就能做到在状态0时输出1,状态1时输出0,后续等等

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            seq <= 1'b0;
        end
    else 
        begin
            case(n_state)
            s0:seq <= 1'b1;
            s1:seq <= 1'b0;
            s2:seq <= 1'b1;
            s3:seq <= 1'b1;
            default:seq <= 1'b0;            
            endcase
            
        end

end
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值