草庐IT

状态机详解(Verilog编写状态机)(一)

时光瞎搞 2023-07-20 原文

verilog实现状态机

背景

在学习spinalHDL的时候对他的状态机的实现有很多不懂的地方,特地使用了verilog编写了一个相同的状态机来学习其中的时序。

问题:计数状态机的实现

状态转移图如下图所示

  1. stateA:直接跳转到stateB,同时赋值cnt = 2
  2. stateB:判断cnt的值是否为6,若是则跳转到stateC,没有则继续执行stateB,同时cnt <= cnt + 1’b1
  3. stateC:什么也不做直接跳转到stateA

Verilog实现此状态机

1. 代码如下

这里的非阻塞赋值后加了 #1,方便后续的仿真

`timescale 1ns/1ns
module test(
  input clk,
  input rst,
  output reg signal_out
);
parameter stateA = 2'b01, stateB = 2'b10, stateC = 2'b11;
reg [1:0] state;
reg [2:0] cnt;
always @(posedge clk or posedge rst) begin
  if(rst) begin
    state <= #1 stateA;
    cnt <= #1 'h0;
  end else begin
    case(state)
      stateA: begin
        state <= #1 stateB;
        cnt <= #1 'h2;
      end
      stateB: begin
        cnt <= #1 cnt + 1'b1;
        if(cnt == 'h6) begin
          state <= #1 stateC;
        end else begin
          state <= #1 stateB;
        end
      end
      stateC: state <= #1 stateA;
      default: begin
        state <= #1 stateA;
        cnt <= #1 'h0;
      end
    endcase
  end
end

always @(*) begin
  if(state == stateB && cnt == 'h6) begin
    signal_out = 'h1;
  end else begin
    signal_out = 'h0;
  end
end
endmodule

2. 代码的说明

对上面的代码进行一个解释说明:
首先状态机有三个状态分别是stataA, stateB, stateC。

  1. 代码13、14行对信号进行复位操作此时state的状态为stateA,cnt值为0。

  2. 复位操作完成之后在时钟的上升沿进行代码16行的状态判断,由于之前的复位状态state为stateA,所以执行分支stateA里的代码块即18,19行代码,将状态转移到stateB, cnt赋值为2,如图所示。==需要注意的是虽然这里的cnt <= 2是在stateA里面的但是由于非阻塞赋值的并行性,state <= stateB语句和cnt <= 2语句都在同一个时钟上升沿作用,所以在图中可以看到状态为stateB时cnt的值才为2。

  3. 在下一个时钟上升沿的时候判断执行stateB分支中的代码块,22行代码执行cnt加1操作, 同时判断cnt是否等于6,注意这里判断cnt是否等于6中的cnt其实是还没有加1之前的cnt。如果cnt的值不等于6则继续执行stateB中的代码,直到cnt等于6。从图中我们可以看出当在时钟上升沿的时候判断出了cnt的值等于6了,那为什么在stateC状态下cnt还可以继续加1呢,这是因为cnt和state的赋值是并行的,当state从stateB状态跳转到stateC时,cnt的赋值也是同步进行的即cnt <= cnt + 1也是要执行的,所以才有了cnt = 7

  4. 状态跳转到了stateC时, 其中的代码块直接跳转到了stateA, 此时cnt的值保持不变还为7。

    图二、

3. 代码的仿真

testbench如下所示

`timescale 1ns/1ns
`define clock_period 20
module test_tb;

reg clk       ;
reg reset      ;
wire io_signal_out;

test u_test(
    .clk       ( clk       ),
    .rst       ( reset       ),
    .signal_out  ( io_signal_out  )
);
initial begin
    clk = 1;
    forever begin
        #(`clock_period/2) clk = ~clk;
    end
end

initial begin
    reset = 1;
        #(`clock_period*10-1);
    reset = 0;
    #(`clock_period*30);
    $stop;
end
endmodule 

仿真波形如下图所示

有关状态机详解(Verilog编写状态机)(一)的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  3. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  4. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  5. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  6. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  7. ruby-on-rails - 为模型创建状态属性 - 2

    我想为我的Task模型创建一个status属性,该属性将按以下顺序指示它在三部分进度中的位置:打开=>进行中=>完成。它的工作方式类似于亚马逊包裹的交付方式:已订购=>已发货=>已交付。我想知道设置此属性的最佳方法是什么。我可能是错的,但创建三个独立的bool属性似乎有点多余。实现此目标的最佳方法是什么? 最佳答案 Rails4有一个内置的enummacro.它使用单个整数列并映射到键列表。classOrderenumstatus:[:ordered,:shipped,:delivered]end状态映射如下:{ordered:0,

  8. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  9. ruby-on-rails - 如何为空白字段编写 rspec? [Rails3.1] - 2

    我使用rails3.1+rspec和factorygirl。我对必填字段(validates_presence_of)的验证工作正常。我如何让测试将该事实用作“成功”而不是“失败”规范是:describe"Addanindustrywithnoname"docontext"Unabletocreatearecordwhenthenameisblank"dosubjectdoind=Factory.create(:industry_name_blank)endit{shouldbe_invalid}endend但是我失败了:Failures:1)Addanindustrywithnona

  10. ruby - 在 ruby​​ 中生成一个进程,捕获 stdout,stderr,获取退出状态 - 2

    我想从ruby​​rake脚本运行一个可执行文件,比如foo.exe我希望将foo.exe的STDOUT和STDERR输出直接写入我正在运行rake任务的控制台.当进程完成时,我想将退出代码捕获到一个变量中。我如何实现这一目标?我一直在玩backticks、process.spawn、system但我无法获得我想要的所有行为,只有部分更新:我在Windows上,在标准命令提示符下,而不是cygwin 最佳答案 system获取您想要的STDOUT行为。它还返回true作为零退出代码,这可能很有用。$?填充了有关最后一次system调

随机推荐