1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > FPGA 三段式状态机

FPGA 三段式状态机

时间:2022-12-30 16:19:12

相关推荐

FPGA 三段式状态机

定义

状态机能够控制信号按照设定好的状态进行转移,同时完成特定输出。

FPGA是并行运行的,而状态机是用来完成那些需要顺序执行的动作。通俗地说,就是把全部的情况分成几个场景,这些场景的工作方式不同。

结构

基于明德扬的状态机架构,结构清晰,易于修改。

三段式状态机,即三个always块描述状态机.

状态机结构图:(这里图有误,是两段式的)

时序逻辑always块,当前状态的复位,次态赋值给现态。

always@(posedge clk or negedge rst_n)beginif(!rst_n)beginstate_c <= HEAD;endelse beginstate_c <= state_n;endend

组合逻辑always块,描述次态转移的方向。转移条件用信号xx2xx_start命名**,写出转移方向,不用写出具体的转移条件。**状态不变不要写成 state_n = state_n,会产生锁存器。

always@(*)begincase(state_c)HEAD:beginif(hea2typ_start)beginstate_n = TYPE;endelse beginstate_n = state_c;endendTYPE:beginif(typ2len_start)beginstate_n = LEN;endelse if(typ2dat_start)beginstate_n = DATA;endelse beginstate_n = state_c;endend...default:beginstate_n = HEAD;endendcaseend

后面用assign定义具体的转移条件;注意要加上现态,避免因两种不同状态由同一个变化条件发生转移时导致错误;状态的对齐对象是din不是dout,因为是先有din,再分状态,最后得到dout。

assign hea2typ_start = state_c==HEAD && end_cnt;assign typ2len_start = state_c==TYPE && din!=0;

组合or时序always块用来描述输出.(output logic)

always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begindout_eop <= 0;endelse if(state_c==FCS && end_fcs_cnt)begindout_eop <= 1;endelse begindout_eop <= 0;endend

注意:

4. Moore和Mealy就在这里产生区别,前者output仅与状态有关,后者output与状态和输入有关。

5. 输出的always块推荐用时序逻辑,用次态做判断。

判断条件用现态有一拍的延时。

用组合+current_state进行状态判断的话,就成了两段式的。因为组合逻辑产生毛刺,尤其是米利型状态机时;级数过长而引起建立时间违例。

6. 状态机的第二段组合逻辑,它能是时序逻辑吗?

网上没找到解答,我感觉不能。

clk到来,state_c更新,但是此刻D2用作判断的还是上一刻的state_c,所以state_n不变,去更新的state_c也不变。

编码

二进制编码

传统二进制序列。少于5种状态。

二进制编码占用的位数少,但其状态跳变需要额外的译码电路,这样的编码方式会对状态机的运行速度有所限制。独热码编码

以n bit表示n个 状态,每个状态分配一个触发器,只要本状态触发器设置为1,其余均设置为0。

5-50种状态

这样编码的译码部分可以做到最简,工作频率可以做到较高,相对于二进制而言,需要更多的位。Gray码

多于50种状态。

示例

module FSM1(i,clk,rst_n,q);input i;input clk,rst_n;output reg q;reg [5:0] cstate;reg [5:0] nstate;//状态编码eparameter s0 = 6'b000001;parameter s1 = 6'b000010;parameter s2 = 6'b000100;parameter s3 = 6'b001000;parameter s4 = 6'b010000;parameter s5 = 6'b100000;//描述对应当前状态的状态寄存器always@ (posedge clk or negedge rst_n)beginif (!rst_n)cstate <= s0; //复位后状态机处于空闲态idleelse cstate <= nstate;end //描述状态的转移always@ (cstate or i)nstate = s0; //要初始化,使得系统复位后能进入正确的状态begincase(cstate)s0: if(i) nstate = s1;else nstate = s0;s1: if(i) nstate = s1;else nstate = s2;s2: if(i) nstate = s1; else nstate = s3;s3: if(i) nstate = s4;else nstate = s0;s4: if(i) nstate = s1;else nstate = s5;s5: if(i) nstate = s1;else nstate = s3;default: nstate = s0;endcaseend//描述输出always@ (*) begin if (!rst_n) q = 1'b0;else begincase(cstate)s0: q = 1'b0;s1: q = 1'b0;s2: q = 1'b0;s3: q = 1'b0;s4: q = 1'b0;s5: q = 1'b1;default: q = 1'b0;//免除综合工具综合出锁存器endcaseendendendmodule

验证:

Quartus编译后,查看State Machine Viewer

步骤

状态转移图

Q是状态编码,X输入,Z输出。下图是mealy型,输出和输入有关。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。