阿里外贸平台网站建设,如何办宽带,免费搭建网站 优帮云,北京交易中心网站6、有限状态机状态机#xff0c;只要C代码写过2年的人#xff0c;估计无人不识君#xff0c;稍微复杂的逻辑都可以借助状态机来简化问题。为了方便#xff0c;我们使用前面用过的一个例子#xff0c;来说明状态机的应用#xff0c;也就是说我们前面已经有意无意的用过状态…6、有限状态机状态机只要C代码写过2年的人估计无人不识君稍微复杂的逻辑都可以借助状态机来简化问题。为了方便我们使用前面用过的一个例子来说明状态机的应用也就是说我们前面已经有意无意的用过状态机了。我们以SPI的Slave接口为例来说明状态机的使用为了简化问题1、我们没有把信号同步到本地时钟2、把其他信号同步到SCK3、我们把SPI暂时按照单向来分析下面我们分析SPI通讯1、nCS高电平时候总线是空闲的2、nCS低电平时传输数据3、满了8个bit凑够了一个字节要保存当前已经收到的字节并准备收下一个nCS高电平的时候我们称之为idel态IDEL接受07逐个bit的时候称之为bit接受态BIT_RECV收满一个字节称之为字节转存态BYTE_SAVE model SlaveSPI(input nCS, input SCK, input MOSI, output MISO); parameter IDEL 0, BIT_RECV 1, BIT_SAVE 2; reg[3:0] bitcnt; reg[7:0] shift_in; //写入 reg[7:0] shift_out; //读出 reg[7:0] data; reg[1:0] state; reg[1:0] next_state; always (*) begin case(state) IDEL: if(nCS1b1) next_state IDEL; else next_state BIT_RECV; BIT_RECV: if(nCS1b0) bgein if(bitcnt4h8) next_state BIT_RECV; else next_state BYTE_SAVE; end else next_state IDEL; BYTE_SAVE: if(nCS1b0) next_state BIT_RECV; else next_state IDEL; defalut: next_state IDEL; endcase end always (posdge SCK) if(nCS) bitcnt0; else state next_state always (posdge SCK) case(state) BIT_RECV: begin bitcnt bitcnt4h1; shift_in {shift_in[6:0], MOSI}; end BYTE_SAVE: begin bitcnt 4h0; data deshift_in; end endcase 我用了所谓的三段式来描述这个状态机用了3个always语句 第一个always用来描述状态转移的条件 第二个always用来描述状态转移 第三个always用来描述状态机的输出也就是状态机实际要干的活 与前面帖子(同步和异步设计)中的SPI代码相比是不是冗长了很多。 冗长并不代表着脱裤子放屁自找麻烦。您难道没有反显代码很容易读懂了吗 没错这就是空间换时间的策略我们写更长的代码来增强可分析性。 状态机的代码撰写一般不复杂复杂的是状态机的构建过程这个过程中我们要分析 实际遇到的各个情况同时把状态机进行优化某些状态进行合并某些状态去掉。 有人问为何某些状态要去掉 这要说下FSM的来头了有限状态机是有限的状态机。 自然界实际的状态机往往起状态的数量是非常大的直接建模使用简直是劳民伤财。 而且现实的往往是无限的状态机这根本无法用于工程实现所以有限状态机就横空出世了。 正如软件算法中的DAGDirected Acyclic Graph有向无环图比纯粹的图有实用价值。 二叉树比多叉树也更容易实现。 越说软件和FPGA越近了。可谓是天下大势分久必合合久必分。