verilog学习(一):状态机及tcl脚本仿真

1.为什么要使用状态机?
Verilog语言都是并行执行的,但是很多情况下我们希望按照顺序的方式进行,而状态机就可以很好的实现顺序执行。

2.状态机分为mealy型和moore型
Mealy:输出状态不仅与当前状态有关,还与输入有关。
Moore:输出只与当前状态有关。
设计时不需要关注是什么类型。

3.状态机设计规则:使用两段式结构
方法:使用一个always块描述状态转移。使用另一个always块描述数据输出。
优点:使用两段式状态机,其描述过程都是时序电路。而时序电路可以很好的避免毛刺的产生。

4.设计案例:使用状态机实现一个简单的自动售货机功能
题目描述:售货机中商品2.5元一件,每次投币为3元、1元、0.5元,需要设定找零。

  1. 状态转移图
    这里一共设置了五个状态,当投入钱数足够时,直接回到idle状态。
    除了在idle状态需要考虑投入3元钱,其他状态只需要考虑输入1元、0.5元或者没有输入。所以ABCD状态均有三个输出箭头,即三种状态迁移。

  2. 代码编写
    状态编码使用独热码,减少时序问题
    对于输入money和输出change,当值为2时代表0.5元,1代表1元,3代表3元。

module fsm(
	input	wire			clk,
	input	wire			rst_n,

	input	wire	[1:0]	money,//	1=1,2=0.5,3=3
	output	reg				cola,
	output	reg		[1:0]	change//	1=1,2=0.5,3=3
	);

reg [4:0]	state;
parameter	idle = 5'b00001;
parameter	A 	 = 5'b00010;
parameter	B 	 = 5'b00100;
parameter	C 	 = 5'b01000;
parameter	D 	 = 5'b10000;

//第一个always块描述状态转移
always @(posedge clk or negedge rst_n) begin
	if (!rst_n) begin
		state	<= idle;
	end
	else begin
		case(state)
			idle:	if (money == 2'd2) 		state <= A;
					else if (money == 2'd1)	state <= B;
					else if (money == 2'd3)	state <= idle;
					else 					state <= state;

			A:		if (money == 2'd2) 		state <= B;
					else if (money == 2'd1)	state <= C;
					else 					state <= state;

			B:		if (money == 2'd2) 		state <= C;
					else if (money == 2'd1)	state <= D;
					else 					state <= state;

			C:		if (money == 2'd2) 		state <= D;
					else if (money == 2'd1)	state <= idle;
					else 					state <= state;

			D:		if (money == 2'd2) 		state <= idle;
					else if (money == 2'd1)	state <= idle;
					else 					state <= state;
			default:	state <= idle;
		endcase
	end
end

//第二个always块描述输出
always @(posedge clk or negedge rst_n) begin
	if (!rst_n) begin
		cola	<= 1'd0;
		change	<= 2'd0;
	end
	else if ( state == C && money == 2'd1 ) begin
		cola	<= 1'd1;
		change	<= 2'd0;
	end	
	else if ( state == D && money == 2'd1 ) begin
		cola	<= 1'd1;
		change	<= 2'd2;
	end
	else if ( state == D && money == 2'd2 ) begin
		cola	<= 1'd1;
		change	<= 2'd0;
	end	
	else if ( state == idle && money == 2'd3 ) begin
		cola	<= 1'd1;
		change	<= 2'd2;
	end	
	else begin
		cola	<= 1'd0;
		change	<= 2'd0;
	end
end

endmodule
  1. 编写testbench进行结果仿真
module tb_fsm();

reg			clk;
reg			rst_n;
reg	[1:0]	money;

wire		cola;
wire[1:0]	change;

initial begin
	clk = 0;
	rst_n = 0;
	money = 0;
	#100
	rst_n = 1;
end

always begin #10 clk = ~clk; end

always begin #20 money = {$random}; end

fsm inst_fsm (
		.clk    (clk),
		.rst_n  (rst_n),
		.money  (money),
		.cola   (cola),
		.change (change)
	);


endmodule

仿真结果分析
在这里插入图片描述

5.使用tcl脚本进行仿真
注意:结构体使用时,两个virtual后面的type、function,前后都有空格

quit -sim
#退出上一次仿真

.main clear
#清除保留的临时文件

vlib work
#创建work的库

vlog ./tb_fsm.v 
#添加编译文件
vlog ./../design/*.v
#..返回上一级文件夹

vsim -voptargs=+acc work.tb_fsm
#启动tb顶层仿真

#创建一个结构体,仿真结果可以替换显示
virtual type {
	{5'b00001 idle}
	{5'b00010 one}
	{5'b00100 two}
	{5'b01000 three}
	{5'b10000 four}
} replace;

virtual function {(replace)/tb_fsm/inst_fsm/state} new_state;

#添加波形
add wave /tb_fsm/inst_fsm/*	

run 1us
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值