如何设计状态机
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仿真结果
|