• 野火A7学习第十次(状态机相关)


    1 状态机理论分析

    FPGA是并行执行的,如果需要处理前后顺序的事件怎么办?就需要引入我们的状态机了。
    在这里插入图片描述

    共同点,状态的跳转只和输入有关。Moore型状态机,最后的输出只和当前的状态有关与输入无关。Mealy型 最后的输出不仅和当前状态有关还和输入相关。
    在这里插入图片描述

    2 实战演练

    可乐机系统,每次售价3元,每次只能投一枚硬币

    2.1 设计规划

    在这里插入图片描述
    在这里插入图片描述

    2.2 波形绘制

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    使用mealy型状态机讲解

    在这里插入图片描述

    2.3 代码编写和编译

    在这里插入图片描述

    小知识:
    1 在低速系统中,状态机的个数小于4个,我们使用二进制码
    2 状态介于4到24个,就使用独热码
    3 状态大于24个,使用格雷码
    4 在高速系统中,无论多少个状态都建议使用独热码

    module simple_fsm
    (
    	input wire sys_clk,
    	input wire sys_rst_n,
    	input wire pi_money,
    	
    	output wire po_cola;
    );
    // 独热码(比较好的) 二进制码 格雷码 
    parameter IDLE = 3'b001;
    parameter ONE = 3'b010;
    parameter TWO = 3'b100;
    
    reg [2:0] state;
    
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(sys_rst_n == 1'b0) 
    		state <= IDLE;
    	else case(state)
    		IDLE:if(pi_money == 1'b1)
    				state <= ONE;
    			 else
    			 	state <= IDLE;
    		ONE: if(pi_money == 1'b1)
    				state <= TWO;
    			 else
    			 	state <= ONE;
    		TWO: if(pi_money == 1'b1)
    				state <= IDLE;
    			 else
    			 	state <= TWO;
    		default: state <= IDLE;
    
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(sys_rst_n == 1'b0)
    		po_cola <= 1'b0;
    	else if((state == TWO) && (pi_money == 1'b1))
    		po_cola <= 1'b1;
    	else
    		po_cola <= 1'b0;		
    
    
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    一段式:
    二段式:
    三段式:

    tb文件代码:

    `timescale 1ns/1ns
    
    module tb_simple_fsm();
    
    reg sys_clk;
    reg sys_rst_n;
    reg pi_money;
    
    wire po_cola;
    
    initial begin
    	sys_clk = 1'b0;
    	sys_rst_n <= 1'b0;
    	#20
    	sys_rst_n <= 1'b1;
    end
    
    always #10 sys_clk = ~sys_clk;
    
    // 如何对内部的状态变量进行检测
    wire [2:0] state = simple_fsm_inst.state;
    
    
    // 产生投币信号 使用随机数的方法
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(sys_rst_n == 1'b0)
    		pi_money <= 1'b0;
    	else
    		pi_money <= {$random} % 2;
    
    // 系统函数方便验证
    initial begin
    	$timeformat(-9, 0, "ns", 6);
    	$monitor("@time %t: pi_money = %b, state= %b, po_cola = %b", $time, pi_money, state, po_cola);
    end
    
    // 实例化
    simple_fsm simple_fsm_inst
    (
    	.sys_clk(sys_clk),
    	.sys_rst_n(sys_rst_n),
    	.pi_money(pi_money),
    	
    	.po_cola(po_cola);
    );
    
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    2.4 波形仿真和对比

    在这里插入图片描述
    在这里插入图片描述

    3 复杂投币机实战演练

    3.1 设计规划

    如果投币不足2.5元,不出可乐。如果超过2.5元需要找零

    在这里插入图片描述
    在这里插入图片描述

    3.2 框图和波形绘制

    在这里插入图片描述
    输入输出编码:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3.3 代码编写和编译

    module complex_fsm
    (
    	input wire sys_clk,
    	input wire sys_rst_n,
    	input wire pi_money_half,
    	input wire pi_money_one,
    
    	output wire po_cola,
    	output wire po_money
    );
    
    parameter 	IDLE = 5'b00001,
    			HALF = 5'b00010,
    			ONE  = 5'b00100,
    			ONE_HALF = 5'b01000,
    			TWO = 5'b10000;
    
    // pi_money 并没有延迟一个周期,所以assign来赋值
    wire	[1:0] pi_money;
    reg		[4:0] state;
    
    assign pi_money = {pi_money_one, pi_money_half};
    
    // 第一段 状态机的跳转
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(!sys_rst_n)
    		stats <= IDLE;
    	else	case(state)
    		IDLE:	if(pi_money == 2'b01)
    					state <= HALF;
    				else if(pi_money == 2'b10)
    					state <= ONE;
    				else
    					state <= IDLE;
    		HALF:	if(pi_money == 2'b01)
    					state <= ONE;
    				else if(pi_money == 2'b10)
    					state <= ONE_HALF;
    				else
    					state <= HALF;
    		ONE:	if(pi_monet == 2'b01)
    					state <= ONE_HALF;
    				else if(pi_money == 2'b10)
    					state <= TWO;
    				else
    					state <= ONE;
    		ONE_HALF:	if(pi_money == 2'b01)
    						state <= TWO;
    					else if(pi_money == 2'b10)
    						state <= IDLE;
    					else
    						state <= ONE_HELF;
    		TWO: 	if((pi_money == 2'b01) && (pi_money == 2'b10))
    					state <= IDLE;
    				else
    					state <= TWO;
    		default: state <= IDLE;
    	endcase
    
    // 第二段数据的输出
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(!sys_rst_n)
    		po_cola<= 1'b0;
    	else if((state == ONE_HALF && pi_money == 2'b10)
    			|| (state == TWO && pi_money == 2'b01)
    			|| (state == TWO && pi_money == 2'b10))
    		po_cola <= 1'b1;
    	else
    		po_cola <= 1'b0;
    
    // 第三段找零的输出
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(!sys_rst_n)
    		po_money<= 1'b0;
    	else if(state == TWO && pi_money == 2'b10)
    		po_money <= 1'b1;
    	else
    		po_money <= 1'b0;
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    tb文件

    `timescale 1ns/1ns
    
    module tb_complex_fsm();
    
    reg sys_clk;
    reg sys_rst_n;
    reg pi_money_half;
    reg pi_money_one;
    
    reg random_data;
    
    
    wire po_cola;
    wire po_money;
    
    initial begin
    	sys_clk = 1'b0;
    	sys_rst_n <= 1'b0;
    	#20
    	sys_rst_n <= 1'b1;
    end
    
    always #10 sys_clk = ~sys_clk;
    
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(sys_clk == 1'b0) begin
    		random_data <= 1'b0;
    	end
    	else 
    		random_data <= {$random} % 2;
    
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(sys_clk == 1'b0) begin
    		pi_money_half<= 1'b0;
    	end
    	else 
    		pi_money_half<= random_data;
    
    always@(posedge sys_clk or negedge sys_rst_n)
    	if(sys_clk == 1'b0) begin
    		pi_money_one<= 1'b0;
    	end
    	else 
    		pi_money_one<= ~random_data;
    					
    
    // 如何对内部的状态变量进行检测
    wire [2:0] pi_money= complex_fsm_inst.pi_money;
    
    
    
    // 系统函数方便验证
    initial begin
    	$timeformat(-9, 0, "ns", 6);
    	$monitor("@time %t: pi_money = %b, state= %b, po_cola = %b", $time, pi_money, state, po_cola);
    end
    
    // 实例化
    complex_fsm complex_fsm_inst
    (
    	.sys_clk(sys_clk),
    	.sys_rst_n(sys_rst_n),
    	.pi_money_half(pi_money_half),
    	.pi_money_one(pi_money_one),
    
    	.po_cola(po_cola),
    	.po_money(po_money)
    );
    
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    3.4 波形仿真与验证

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    计算机毕业设计ssm+vue+elementUI基于web的邮票鉴赏系统及实现
    传输层协议UDP/TCP中的那些端口
    FPGA UDP RGMII 千兆以太网(2)IDDR
    购买阿里云服务器需要多少钱?活动价2000元-3000元的阿里云服务器汇总
    ModStart 中HasAdminQuickCRUD 的功能使用解析
    微服务框架 SpringCloud微服务架构 16 SpringAMQP 16.1 基本介绍
    Python之第六章 内置容器 --- 正则表达式
    【面试题-Java】2022面试题干货汇总(持续更新)
    最新720全景云系统/可生成小程序+带PC端+安装教程/价值800元的720云全景系统源码
    Type-challenges题目(第三部分)
  • 原文地址:https://blog.csdn.net/qq_30093417/article/details/126572967