Verilog 我有两个always,模拟一个有6个状态(S0-S5)的状态机(FSM)。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Verilog 我有两个always,模拟一个有6个状态(S0-S5)的状态机(FSM)。相关的知识,希望对你有一定的参考价值。
我进入S5时判断如果or_row==1时,想让他卡在S5。但实际在FPGA板子上跑的时候,在S5停不住,过了一秒就跳到S0了,不知道是什么回事?
always @ (posedge clock_1Hz or posedge reset)
begin
if (reset) present_state=S0;
else present_state=next_state;
end
always @(present_state)
case (present_state)
S0-S4://代码省略
S5:
begin
Col=4'b1111;
LED_c=Col;
LED_r=Row;
code=out;
if(~or_row) next_state=S0;
else next_state=S5;
end
endcase
RECONFIGURE
EXEC SP_CONFIGURE \'Ad Hoc Distributed Queries\',1
RECONFIGURE
插入的代码:
INSERT INTO dbo.Resources(ResourcesUrl,ResourcesLink,ResourcesText) SELECT * FROM OPENROWSET(\'Microsoft.Jet.OLEDB.4.0\',
\'Excel 8.0;HDR=YES;Database=F:\\Book1.xls\', [sheet1$])追问
能仔细讲解下吗?看不懂。。。
参考技术A 这是神马情况?Verilog的非阻塞语句放到顺序块中,综合出来怎样的逻辑电路?
情境:
FPGA里面计数器需要复位(计数值置零),与计数器状态有关的行为是状态机控制的,即状态机为CLEAR_TIMER状态时,计数器才完成清零动作。
清零有两个条件:(1)计数器值溢出(达到OVF门限);(2)清零信号有效(1有效)。这两个条件是独立的,没有先后关系的约束。
问题是:如何写Verilog语句,才使得这两个触发的优先级相同?
有两个思路:
一个是:
always@(posedge clk)begin
if(!rst_n)begin
stat_preload <= STAT_IDLE;
end
else begin
//*** Combined Transition
if((tim_cnt >= TIIM_OVF) || (1‘b1 == tim_rst))begin // OR
stat_preload <= STAT_CLEAR_TIMER;
end
else begin
stat_preload <= stat_preload; // Status Latch
end
end
end
另一个:
always@(posedge clk)begin
if(!rst_n)begin
stat_preload <= STAT_IDLE;
end
else begin
//*** Separate Transition
if(tim_cnt >= TIM_OVF)begin stat_preload <= STAT_CLEAR_TIMER; end else begin stat_preload <= stat_preload; // Stay end if(1‘b1 == tim_rst)begin stat_preload <= STAT_CLEAR_TIMER; end else begin stat_preload <= stat_preload; // Stay end
end
end
这两种写法的区别在于:第一种,状态转移语句放在两个条件参与的单个if选择结构里面;第二种,状态转移语句放在分别的两个if选择结构里面。
状态转移图中表现为这样的两种情况:
实现和测试:
上述两种的代码和综合结果如下:
module top( rst_n, clk, X, Y, din_A, dout ); //**************************************** // Port Def. //**************************************** input wire rst_n; input wire clk; input wire X; // Conditions input wire Y; input wire[3:0] din_A; output wire[3:0] dout; //**************************************** // Variables //**************************************** reg[3:0] dout_reg; //**************************************** // Behaviour //**************************************** assign dout = dout_reg; always@(posedge clk)begin if(!rst_n)begin dout_reg <= 4‘b0; end else begin if((1‘b1 == X) || (1‘b1 == Y))begin dout_reg <= din_A; end else begin dout_reg <= dout_reg; end end end endmodule
module top( rst_n, clk, X, Y, din_A, dout ); //**************************************** // Port Def. //**************************************** input wire rst_n; input wire clk; input wire X; // Conditions input wire Y; input wire[3:0] din_A; output wire[3:0] dout; //**************************************** // Variables //**************************************** reg[3:0] dout_reg; //**************************************** // Behaviour //**************************************** assign dout = dout_reg; always@(posedge clk)begin if(!rst_n)begin dout_reg <= 4‘b0; end else begin if(1‘b1 == X)begin dout_reg <= din_A; end else begin dout_reg <= dout_reg; end if(1‘b1 == Y)begin dout_reg <= din_A; end else begin dout_reg <= dout_reg; end end end endmodule
综合器是Quartus 15.1内置的。
可以看到,第二种写法的综合结果让输入信号X没有驱动逻辑了,这样就与需求不符。
原因是什么?
第二种(分开if)情况下,虽然赋值语句都是非阻塞的<=,但是由于if语句放在顺序的begin::end结构内,所以判断和执行都是顺序处理的,状态转移和状态停留操作是一模一样的,所以X条件被省略了。
为了验证这个结论,在X,Y两个条件的基础上再加R,S两个条件,进行X,Y,R,S的顺序if,然后查看结果:
module top( rst_n, clk, X, Y, R, S, din_A, dout ); //**************************************** // Port Def. //**************************************** input wire rst_n; input wire clk; input wire X; // Conditions input wire Y; input wire R; input wire S; input wire[3:0] din_A; output wire[3:0] dout; //**************************************** // Variables //**************************************** reg[3:0] dout_reg; //**************************************** // Behaviour //**************************************** assign dout = dout_reg; always@(posedge clk)begin if(!rst_n)begin dout_reg <= 4‘b0; end else begin if(1‘b1 == X)begin dout_reg <= din_A; end else begin dout_reg <= dout_reg; end if(1‘b1 == Y)begin dout_reg <= din_A; end else begin dout_reg <= dout_reg; end if(1‘b1 == R)begin dout_reg <= din_A; end else begin dout_reg <= dout_reg; end if(1‘b1 == S)begin dout_reg <= din_A; end else begin dout_reg <= dout_reg; end end end endmodule
显然,只有S条件有效了。
结论:顺序块begin::end中的语句是顺序执行的。
以上是关于Verilog 我有两个always,模拟一个有6个状态(S0-S5)的状态机(FSM)。的主要内容,如果未能解决你的问题,请参考以下文章