一段状态机仿真代码引起的思考

    状态机模型是FPGA设计三大支柱之一,明德扬把计数器设计,状态机设计和FIFO设计并称FPGA设计三大支柱。采用三段式设计的状态机具有结构清晰,逻辑清楚易于实现等特点,这也是明德扬推荐的设计方法。在照例抄写了一段状态机代码后,自己写了仿真的代码,国际惯例上代码:

//自动转换量程频率控制器
/*信号定义:
clk:		输入时钟
clr:		为整个频率计的异步复位信号
rst:		用来在量程转换开始时复位计数器
std_f_sel:	用来选择标准时基
cntover:	代表超量程
cntlow:		代表欠量程
状态A,B,C,D,E,F,采用一位热码编码
*/
module control(std_f_sel, rst, clk, clr, cntover, cntlow);
input clk, clr, cntover, cntlow;
output[1:0] std_f_sel;
output rst;
reg[1:0] std_f_sel;
reg rst;
reg[5:0] present, next; //用于保存当前状态和次态的中间变量

parameter start_f100k = 6'b000001,	//状态A编码,采用1位热码
		  f100k_cnt   = 6'b000010,	//状态B
		  start_f10k  = 6'b000100,	//状态C
		  f10k_cnt    = 6'b001000,	//状态D
		  start_f1k   = 6'b010000,	//状态E
		  f1k_cnt     = 6'b100000;	//状态F

always @(posedge clk or posedge clr)
begin
	if(clr)
		present = start_f10k; //start_f10k 位起始状态
	else 
		present = next;
end

always @(present or cntover or cntlow)
begin
	case(present)
		start_f100k:	next <=start_f10k;
		f100k_cnt:
		begin
			if(cntlow)
				next <=start_f10k;
			else 
				next <=f100k_cnt;
		end
		start_f10k:		next <=start_f1k;
		f10k_cnt:
		begin
			if(cntlow)
				next <=start_f1k;
			else if(cntover)
				next <=start_f100k;
			else 
				next <=f10k_cnt;
		end
		start_f1k:		next <=f1k_cnt;
		f1k_cnt:
		begin
			if(cntover)
				next <= start_f10k;
			else 
				next <= f1k_cnt;
		end
		default:		next <= start_f10k;	//缺省状态为起始状态
	endcase
end
always @(present)
begin
	case(present)
		start_f100k:
		begin
			rst = 1;
			std_f_sel = 2'b00;
		end
		f100k_cnt:
		begin
			rst = 0;
			std_f_sel = 2'b00;
		end
		start_f10k:
		begin
			rst = 1;
			std_f_sel = 2'b01;
		end
		f10k_cnt:
		begin
			rst = 0;
			std_f_sel = 2'b01;
		end
		start_f1k:
		begin
			rst = 1;
			std_f_sel = 2'b11;
		end
		f1k_cnt:
		begin
			rst = 0;
			std_f_sel = 2'b11;
		end
		default:
		begin
			rst = 1;
			std_f_sel = 2'b01;
		end
	endcase
end

endmodule

`timescale 1ns/1ps
module sim_stateMachine;
reg clk, clr, cntover,cntlow;
wire[1:0] std_f_sel;
wire rst;

control SM0(
	.std_f_sel (std_f_sel),
	.rst	   (rst),
	.clk	   (clk), 
	.clr	   (clr),
	.cntover   (cntover),
	.cntlow	   (cntlow)
	 );

initial
begin
	clk = 0;
	clr = 1;
	cntover = 1;
	cntlow = 0;
	#20 clr = 0;
	#2000 $finish;
end

always #20 clk = ~clk;
always #40 cntover = ~cntover;
always #20 cntlow = ~cntlow;
endmodule

测试代码从第109行看起,写的比较简单,无非定义时钟,设置初值,约定结束条件。在vivado 2018.3中进行行为仿真,如图:

从仿真结果中可以看出状态机输出结果只在1和3之间来回切换并没有覆盖所有可能的情况。看一下现态的值:

可以看出现态的值也没有覆盖所有可能的取值,一开始我以为是初值设计的不好,在尝试不同初值后发现情况依旧。我在仿真的时候为了图省事,直接用always 持续变换输入,但是结果看起来并不满意,至少这样的代码拿出去别人是不敢用的。没法了,老老实实把每一种情况的初值写出来,再进行仿真吧。这篇文章(我是直达车)讲解了仿真时应该注意的地方,可以看一下。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值