首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

FPGA触发器 如何设计状态机?

FPGA触发器 如何设计状态机?

如何设计状态机
1)根据实际的工作流程画出状态迁移图。
2)根据状态迁移图来编写代码。

假如有两个开关K1和K2会随着条件A的值变化而变化。



ex_fsm.v 可综合模块

[plain] view plain copy



  • module ex_fsm(  
  •     input       wire        sclk,  
  •     input       wire        rst_n,  
  •     input       wire        A,  
  •     output      reg         k1,  
  •     output      reg         k2  
  • );  

  • parameter IDLE  =   4'b0001; //使用独热码来定义状态  
  • parameter START =   4'b0010;  
  • parameter STOP  =   4'b0100;  
  • parameter CLEAR =   4'b1000;  

  • reg [3:0] state;  

  • //状态机只对状态进行处理,不对变量进行处理  
  • always @(posedge sclk or negedge rst_n)  
  •     if (rst_n == 1'b0)  
  •         state <= IDLE;  
  •     else begin  
  •         case (state)  
  •             IDLE: if (A == 1'b1)  
  •                     state <= START;  
  •             START: if (A == 1'b0)  
  •                     state <= STOP;  
  •             STOP: if (A == 1'b1)  
  •                     state <= CLEAR;  
  •             CLEAR: if (A == 1'b0)  
  •                     state <= IDLE;  
  •             default:  
  •                 state <= IDLE;  
  •             endcase  
  •     end  

  • //变量单独写在一个always块中  
  • always @(posedge sclk or negedge rst_n)  
  •     if (rst_n == 1'b0)  
  •         k1 <= 1'b0;  
  •     else if (state == IDLE && A == 1'b1)  
  •         k1 <= 1'b0;  
  •     else if (state == CLEAR && A == 1'b0)  
  •         k1 <= 1'b1;  

  • always @(posedge sclk or negedge rst_n)  
  •     if (rst_n == 1'b0)  
  •         k2 <= 1'b0;  
  •     else if (state == STOP && A == 1'b1)  
  •         k2 <= 1'b1;  
  •     else if (state == CLEAR && A == 1'b0)  
  •         k2 <= 1'b0;  

  • endmodule  


tb_ex_fsm.v 激励模块


[plain] view plain copy



  • `timescale 1ns/1ns  
  • module tb_ex_fsm;  

  • reg     sclk_r;  
  • reg     rst_n_r;  
  • reg     in_A;  
  • wire    k1;  
  • wire    k2;  

  • initial  
  • begin  
  •     rst_n_r <= 1'b0;  
  •     sclk_r <= 1'b0;  
  •     #50  
  •     rst_n_r <= 1'b1;  
  • end  

  • initial  
  • begin  
  •     in_A <= 1'b0;  
  •     #60  
  •     send_A();  
  • end  

  • always #10 sclk_r <= ~sclk_r;  

  • ex_fsm ex_fsm_inst(  
  •     .sclk   (sclk_r),  
  •     .rst_n  (rst_n_r),  
  •     .A      (in_A),  
  •     .k1     (k1),  
  •     .k2     (k2)  
  • );  

  • task send_A();  
  •     integer i;  
  •     begin  
  •         for (i=0; i< 512; i=i+1)  
  •         begin  
  •             @(posedge sclk_r)  
  •             if (i<40)  
  •                 in_A <= 1'b0;  
  •             else if (i<80)  
  •                 in_A <= 1'b1;  
  •             else if (i<120)  
  •                 in_A <= 1'b0;  
  •             else if (i<160)  
  •                 in_A <= 1'b1;  
  •             else if (i<200)  
  •                 in_A <= 1'b1;  
  •         end  
  •     end  
  • endtask  

  • endmodule  



如果每次用modelsim都手动添加仿真很麻烦,可以写一个run.do的自动仿真脚本
文件run.do 脚本

[plain] view plain copy



  • #退出当前的仿真工程  
  • quit -sim  
  • #清空命令行  
  • .main   clear  
  • #创建库  
  • vlib work  
  • #将逻辑库的名字映射到实际物理路径上来  
  • vmap    work ./work  
  • #编译代码文件到逻辑库work中  
  • vlog    -work   work    ./tb_ex_fsm.v  
  • vlog    -work   work    ./../design/*.v  
  • #启动仿真  
  • vsim    -voptargs=+acc work.tb_ex_fsm  
  • #添加波形  
  • #定义宏  
  • virtual type {  
  •     {01 IDLE}  
  •     {02 START}  
  •     {04 STOP}  
  •     {08 CLEAR}  
  • } vir_new_signal  
  • add wave    tb_ex_fsm/*  
  • virtual function {(vir_new_signal)tb_ex_fsm/ex_fsm_inst/state} new_state  
  • add wave -color yellow tb_ex_fsm/ex_fsm_inst/new_state  
  • run 100us  

目录结构

modelsim在sim文件夹下建立工程,在modelsim的命令行中执行do run.do就可以自动仿真波形了。

modelsim仿真结果

返回列表